2

因此,与 SO 上的类似问题略有不同,但对我如何使用仿射变换来缩小或扩大文本字符串以使整体大小与要绘制的区域成比例的任何见解?

例如,我希望字体为区域宽度的 50%。

我继承了一些这样的代码,但我真的不明白它在做什么

Font font = new Font("Arial", Font.BOLD, 12);
FontRenderContext context = graphics.getFontRenderContext();
graphics.setFont(font);
Rectangle2D bounds = graphics.getFont().getStringBounds("Hello world", context);

LineMetrics line = font.getLineMetrics(text, context);
float xScale = (float) (region.width / bounds.getWidth());
float yScale = (region.height / (line.getAscent() + line.getDescent()));

double x = region.x;
double y = region.y + region.height - (yScale * line.getDescent());
AffineTransform transformation = AffineTransform.getTranslateInstance(x, y);

if (xScale > yScale)
    transformation.scale(yScale, yScale);
else
    transformation.scale(xScale, xScale);

graphics.setFont(font.deriveFont(transformation));
graphics.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);

int centerX = region.width / 2;
int centerY = region.height / 2;
graphics.drawString(text, centerX, centerY - (int) bounds.getHeight());

它似乎将大小设置为合理的值,但不是在该区域中居中。如果你能阐明它试图做什么,那就太好了。

非常感谢任何指针(只要它们不是字面上指向 java 字体教程的指针)。

4

1 回答 1

3

基本上,这“似乎”试图将文本集中在“给定”区域内......

// Set the base, start font
Font font = new Font("Arial", Font.BOLD, 12);
// Get rendering context
FontRenderContext context = graphics.getFontRenderContext();
// Set the font used by the graphics context...
graphics.setFont(font);
// Get the rectangle "bounds" of the text
Rectangle2D bounds = graphics.getFont().getStringBounds("Hello world", context);
// Get the line metrics, which describes things like the fonts decent and ascent
LineMetrics line = font.getLineMetrics(text, context);
// Calculate the scaling requirements
float xScale = (float) (region.width / bounds.getWidth());
float yScale = (region.height / (line.getAscent() + line.getDescent()));

// Calculate the offset for the text
double x = region.x;
double y = region.y + region.height - (yScale * line.getDescent());
// Create a new transformation, translating the x, y position
// This appears to be trying to place the text at the bottom
// left position of the region, but the problem is, this then gets
// scaled, when means that this translation is no longer the same...   
AffineTransform transformation = AffineTransform.getTranslateInstance(x, y);

// Apply a scale...
if (xScale > yScale)
    transformation.scale(yScale, yScale);
else
    transformation.scale(xScale, xScale);

// Create a new instance of the font using the transformation
graphics.setFont(font.deriveFont(transformation));
// Make it look pretty
graphics.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);

// Render the font within the region...
int centerX = region.width / 2;
int centerY = region.height / 2;
graphics.drawString(text, centerX, centerY - (int) bounds.getHeight());

现在,说了这么多,我很难让它发挥作用。因为您只是Font基于转换创建一个新的,所以丢弃翻译会更简单,例如......

// Base font
Font font = new Font("Arial", Font.BOLD, 12);
// Get the fonts metrics
FontMetrics fm = g2d.getFontMetrics(font);

// Calculate the scaling requirements
float xScale = (float) (region.width / fm.stringWidth(text));
float yScale = (region.height / fm.getHeight());

// Determine which access to scale on...
float scale = 0f;
if (xScale > yScale) {
    scale = yScale;
} else {
    scale = xScale;
}

// Create a new font using the scaling facter
g2d.setFont(font.deriveFont(AffineTransform.getScaleInstance(scale, scale)));
// Make it pretty
g2d.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);

// Get the "scaled" metrics
fm = g2d.getFontMetrics();

// Position the text at the left, bottom position of the
// specified region...
int x = 0;
int y = (region.height - fm.getHeight()) + fm.getAscent();
g2d.drawString(text, x, y);

不确定这是否完全正确(您正在寻找什么),但这就是您提供的代码“似乎”试图做的事情......

于 2013-11-14T23:27:01.933 回答