我刚写了一些代码来缩放字体以适应矩形(长度)。它从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;
}
答案 0 :(得分:18)
半伪代码:
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);
}
我不确定为什么你传入Font因为它没有被使用......
答案 1 :(得分:3)
您可以使用插值搜索:
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;
}
答案 2 :(得分:3)
将所有宽度变量更改为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);
}
答案 3 :(得分:2)
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;
}
答案 4 :(得分:1)
您可以使用二进制搜索模式提高效率 - 高/低,具有一定的粒度 - 1点,0.5点或0.25点。
例如,猜测18,太高了?移到9,太低了? 13.5,太低了? 15.75,太高了? 14!
答案 5 :(得分:0)
另一种显而易见的方法是在位图上预先绘制文本,然后缩小位图以适应矩形;但是,由于手工制作的字体设计和提示等,找到合适的字体大小会产生最佳效果(尽管可能不是最快)。