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

标签 java graphics fonts awt

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

这看起来效率低得可怕,但我找不到一种非循环的方式来做到这一点。 这条线用于可缩放的游戏网格中的标签,因此我看不到解决方案(环绕、切断和延伸超过矩形都是 Not Acceptable )。

它实际上非常快,我正在对数百个矩形执行此操作,它的速度足以将其速度减慢一点。

如果没有人想出更好的方法,我将只从表中加载起始猜测(这样它比 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 font) {
    float fontSize = 20.0f;

    font = g.getFont().deriveFont(fontSize);
    int width = g.getFontMetrics(font).stringWidth(text);
    fontSize = (rect.width / width ) * fontSize;
    return g.getFont().deriveFont(fontSize);
}

迭代的推导:

/**
 * Adjusts the given {@link Font}/{@link String} size such that it fits
 * within the bounds of the given {@link Rectangle}.
 *
 * @param label    Contains the text and font to scale.
 * @param dst      The bounds for fitting the string.
 * @param graphics The context for rendering the string.
 * @return A new {@link Font} instance that is guaranteed to write the given
 * string within the bounds of the given {@link Rectangle}.
 */
public Font scaleFont(
    final JLabel label, final Rectangle dst, final Graphics graphics ) {
  assert label != null;
  assert dst != null;
  assert graphics != null;

  final var font = label.getFont();
  final var text = label.getText();

  final var frc = ((Graphics2D) graphics).getFontRenderContext();

  final var dstWidthPx = dst.getWidth();
  final var dstHeightPx = dst.getHeight();

  var minSizePt = 1f;
  var maxSizePt = 1000f;
  var scaledFont = font;
  float scaledPt = scaledFont.getSize();

  while( maxSizePt - minSizePt > 1f ) {
    scaledFont = scaledFont.deriveFont( scaledPt );

    final var layout = new TextLayout( text, scaledFont, frc );
    final var fontWidthPx = layout.getVisibleAdvance();

    final var metrics = scaledFont.getLineMetrics( text, frc );
    final var fontHeightPx = metrics.getHeight();

    if( (fontWidthPx > dstWidthPx) || (fontHeightPx > dstHeightPx) ) {
      maxSizePt = scaledPt;
    }
    else {
      minSizePt = scaledPt;
    }

    scaledPt = (minSizePt + maxSizePt) / 2;
  }

  return scaledFont.deriveFont( (float) Math.floor( scaledPt ) );
}

假设您要向具有矩形边界 r 的组件添加标签,以便标签完全填充组件的区域。可以这样写:

final Font DEFAULT_FONT = new Font( "DejaVu Sans", BOLD, 12 );
final Color COLOUR_LABEL = new Color( 33, 33, 33 );

// TODO: Return a valid container component instance.
final var r = getComponent().getBounds();
final var graphics = getComponent().getGraphics();

final int width = (int) r.getWidth();
final int height = (int) r.getHeight();

final var label = new JLabel( text );
label.setFont( DEFAULT_FONT );
label.setSize( width, height );
label.setForeground( COLOUR_LABEL );

final var scaledFont = scaleFont( label, r, graphics );
label.setFont( scaledFont );

关于java - 需要一种缩放字体以适合矩形的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/876234/

相关文章:

java - 如何根据一组值更新数据模型

java - Android DrawText 不适用于 SurfaceView

c# - 根据鼠标拖动方向和模型中的位置旋转模型组

latex - 如何在 LaTeX 中使用 "fake"倾斜文本?

Java 按钮/gridbaglayout

java - java中线程的等待和通知顺序

已初始化对象的 Java 线程安全

java - 从 jpanel 获取 (g) 图形

android - 如何以编程方式将字体自定义字体设置为 Spinner 文本?

c# - 在VB.net/C#中直接使用资源字体