需要一种缩放字体以适合矩形的方法

我刚刚编写了一些代码来缩放字体以适应矩形(长度)。 它从18宽度开始并向下迭代直到它适合。

这似乎非常低效,但我找不到一种非循环方式来做到这一点。 此行适用于可缩放的游戏网格中的标签,因此我无法看到解决方案(包裹,切断和延伸超过矩形都是不可接受的)。

它实际上非常快,我正在为数百个矩形做这个,而且速度足以让它减慢触摸速度。

如果没有人提出更好的东西,我只会从表中加载起始猜测(因此它比18更接近)并使用它 – 除了延迟效果很好。

public Font scaleFont(String text, Rectangle rect, Graphics g, Font pFont) { float nextTry=18.0f; Font font=pFont; while(x > 4) { font=g.getFont().deriveFont(nextTry); FontMetrics fm=g.getFontMetrics(font); int width=fm.stringWidth(text); if(width <= rect.width) return font; nextTry*=.9; } return font; } 

半假代码:

 public Font scaleFont(String text, Rectangle rect, Graphics g, Font pFont) { float fontSize = 20.0f; Font font = pFont; font = g.getFont().deriveFont(fontSize); int width = g.getFontMetrics(font).stringWidth(text); fontSize = (rect.width / width ) * fontSize; return g.getFont().deriveFont(fontSize); } 

我不知道为什么你传递pFont,因为它没有使用…

您可以使用插值搜索:

 public static Font scaleFont(String text, Rectangle rect, Graphics g, Font pFont) { float min=0.1f; float max=72f; float size=18.0f; Font font=pFont; while(max - min <= 0.1) { font = g.getFont().deriveFont(size); FontMetrics fm = g.getFontMetrics(font); int width = fm.stringWidth(text); if (width == rect.width) { return font; } else { if (width < rect.width) { min = size; } else { max = size; } size = Math.min(max, Math.max(min, size * (float)rect.width / (float)width)); } } return font; } 

将所有宽度变量更改为float而不是int以获得更好的结果。

 public static Font scaleFontToFit(String text, int width, Graphics g, Font pFont) { float fontSize = pFont.getSize(); float fWidth = g.getFontMetrics(pFont).stringWidth(text); if(fWidth <= width) return pFont; fontSize = ((float)width / fWidth) * fontSize; return pFont.deriveFont(fontSize); } 
 private Font scaleFont ( String text, Rectangle rect, Graphics gc ) { final float fMinimumFont = 0.1f; float fMaximumFont = 1000f; /* Use Point2d.Float to hold ( font, width of font in pixels ) pairs. */ Point2D.Float lowerPoint = new Point2D.Float ( fMinimumFont, getWidthInPixelsOfString ( text, fMinimumFont, gc ) ); Point2D.Float upperPoint = new Point2D.Float ( fMaximumFont, getWidthInPixelsOfString ( text, fMaximumFont, gc ) ); Point2D.Float midPoint = new Point2D.Float (); for ( int i = 0; i < 50; i++ ) { float middleFont = ( lowerPoint.x + upperPoint.x ) / 2; midPoint.setLocation ( middleFont, getWidthInPixelsOfString ( text, middleFont, gc ) ); if ( midPoint.y >= rect.getWidth () * .95 && midPoint.y <= rect.getWidth () ) break; else if ( midPoint.y < rect.getWidth () ) lowerPoint.setLocation ( midPoint ); else if ( midPoint.y > rect.getWidth () ) upperPoint.setLocation ( midPoint ); } fMaximumFont = midPoint.x; Font font = gc.getFont ().deriveFont ( fMaximumFont ); /* Now use Point2d.Float to hold ( font, height of font in pixels ) pairs. */ lowerPoint.setLocation ( fMinimumFont, getHeightInPixelsOfString ( text, fMinimumFont, gc ) ); upperPoint.setLocation ( fMaximumFont, getHeightInPixelsOfString ( text, fMaximumFont, gc ) ); if ( upperPoint.y < rect.getHeight () ) return font; for ( int i = 0; i < 50; i++ ) { float middleFont = ( lowerPoint.x + upperPoint.x ) / 2; midPoint.setLocation ( middleFont, getHeightInPixelsOfString ( text, middleFont, gc ) ); if ( midPoint.y >= rect.getHeight () * .95 && midPoint.y <= rect.getHeight () ) break; else if ( midPoint.y < rect.getHeight () ) lowerPoint.setLocation ( midPoint ); else if ( midPoint.y > rect.getHeight () ) upperPoint.setLocation ( midPoint ); } fMaximumFont = midPoint.x; font = gc.getFont ().deriveFont ( fMaximumFont ); return font; } private float getWidthInPixelsOfString ( String str, float fontSize, Graphics gc ) { Font font = gc.getFont ().deriveFont ( fontSize ); return getWidthInPixelsOfString ( str, font, gc ); } private float getWidthInPixelsOfString ( String str, Font font, Graphics gc ) { FontMetrics fm = gc.getFontMetrics ( font ); int nWidthInPixelsOfCurrentFont = fm.stringWidth ( str ); return (float) nWidthInPixelsOfCurrentFont; } private float getHeightInPixelsOfString ( String string, float fontSize, Graphics gc ) { Font font = gc.getFont ().deriveFont ( fontSize ); return getHeightInPixelsOfString ( string, font, gc ); } private float getHeightInPixelsOfString ( String string, Font font, Graphics gc ) { FontMetrics metrics = gc.getFontMetrics ( font ); int nHeightInPixelsOfCurrentFont = (int) metrics.getStringBounds ( string, gc ).getHeight () - metrics.getDescent () - metrics.getLeading (); return (float) nHeightInPixelsOfCurrentFont * .75f; } 

您可以使用二进制搜索模式提高效率 – 高/低,具有一定的粒度 – 1分,0.5分或0.25分。

例如,猜测18,太高了? 移到9,太低了? 13.5,太低了? 15.75,太高了? 14!

一种不同的,显而易见的方法是在位图上预先绘制文本,然后缩小位图以适应矩形; 但是,由于手工制作的字体设计和提示等,找到合适的字体大小会产生最佳效果(尽管可能不是最快)。