Graphics2D 文本 - 字体大小变化导致 X 轴偏移
Graphics2D text - font size change causes shift on X axis
将文本**写入 Graphics2D
对象时,我发现当我更改字体大小时,文本的 x 位置会发生变化。随着尺寸的增加,x 位置增加。无论我用什么方法写文本都会发生这种情况:drawString
、fill
或 draw
与 GlyphVector
或 drawGlyphVector
.
** 文本的起始字符和字体类型都会更改此行为:Sans Serif 字体,其中起始字符的最左侧笔画是竖线(P、H、L、E 等。 .) 受影响最大。如果字体是 Serif and/or 开始字符的最左边的笔划不是垂直的(W、y、Y、T、X 等...),这种行为会减少或消除。
下面是一个说明此行为的示例程序:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class FontSizeTest {
public FontSizeTest() {
super();
}
public static void main(String[] args) throws IOException {
int width = 700, height = 120;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
FontRenderContext frc = g2d.getFontRenderContext();
Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 10);
GlyphVector gv;
Rectangle pixelBounds;
g2d.setColor(Color.BLACK);
g2d.translate(10, 100);
for(float size : new float[]{40f, 80f, 120f}) {
font = font.deriveFont(size);
gv = font.createGlyphVector(frc, "Hello World");
pixelBounds = gv.getPixelBounds(frc, 0, 0);
System.out.printf("font: %s%npixel bounds: %s%n", font, pixelBounds);
g2d.fill(gv.getOutline());
g2d.draw(pixelBounds);
}
g2d.dispose();
File pngFile = new File("FontSizeTest.png");
ImageIO.write(image, "png", pngFile);
System.out.printf("png file written: %s%n", pngFile.getCanonicalPath());
}
}
此程序的输出是控制台信息:
font: java.awt.Font[family=SansSerif,name=SansSerif,style=plain,size=40]
pixel bounds: java.awt.Rectangle[x=4,y=-31,width=217,height=31]
font: java.awt.Font[family=SansSerif,name=SansSerif,style=plain,size=80]
pixel bounds: java.awt.Rectangle[x=7,y=-62,width=432,height=63]
font: java.awt.Font[family=SansSerif,name=SansSerif,style=plain,size=120]
pixel bounds: java.awt.Rectangle[x=11,y=-93,width=651,height=94]
png file written: FontSizeTest.png
和图像:
请注意较大的字体大小如何从较小的字体大小绘制偏移量。
如果这是预期的行为,我可以通过获取像素边界的偏移量并使用 translate
调整 x 坐标来调整它;我只是不确定这是预期的行为。我觉得我做错了什么 - 缺少一些 Graphics2D
编程方法。
This page 可能无法直接回答您的问题。但是它有很多关于 Graphics2D 的例子。
此效果是字体的正常行为。甚至 Microsoft Word 在不同大小的文本行中也有这种偏移。
如果您想将所有文本行对齐到同一像素行,您可以将 translate
与您提到的计算像素边界一起使用。
一种更优雅的方法是在 GlyphVector 中移动字形位置。这也会导致 getPixelBounds
结果发生变化。
public static void adjust(GlyphVector gv){
// calc the adjust Factor
int adjust = (int)Math.round(gv.getGlyphVisualBounds(0).getBounds2D().getMinX());
// Shift all the Glyphs in Vector
for (int i = 0; i < gv.getNumGlyphs(); i++) {
Point2D point = gv.getGlyphPosition(i);
gv.setGlyphPosition( i, new Point2D.Double(
point.getX() - adjust,
point.getY()));
}
}
在创建字形向量并获得所需结果后,在代码中使用它。
gv = font.createGlyphVector(frc, "Hello World");
adjust(gv);
将文本**写入 Graphics2D
对象时,我发现当我更改字体大小时,文本的 x 位置会发生变化。随着尺寸的增加,x 位置增加。无论我用什么方法写文本都会发生这种情况:drawString
、fill
或 draw
与 GlyphVector
或 drawGlyphVector
.
** 文本的起始字符和字体类型都会更改此行为:Sans Serif 字体,其中起始字符的最左侧笔画是竖线(P、H、L、E 等。 .) 受影响最大。如果字体是 Serif and/or 开始字符的最左边的笔划不是垂直的(W、y、Y、T、X 等...),这种行为会减少或消除。
下面是一个说明此行为的示例程序:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class FontSizeTest {
public FontSizeTest() {
super();
}
public static void main(String[] args) throws IOException {
int width = 700, height = 120;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
FontRenderContext frc = g2d.getFontRenderContext();
Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 10);
GlyphVector gv;
Rectangle pixelBounds;
g2d.setColor(Color.BLACK);
g2d.translate(10, 100);
for(float size : new float[]{40f, 80f, 120f}) {
font = font.deriveFont(size);
gv = font.createGlyphVector(frc, "Hello World");
pixelBounds = gv.getPixelBounds(frc, 0, 0);
System.out.printf("font: %s%npixel bounds: %s%n", font, pixelBounds);
g2d.fill(gv.getOutline());
g2d.draw(pixelBounds);
}
g2d.dispose();
File pngFile = new File("FontSizeTest.png");
ImageIO.write(image, "png", pngFile);
System.out.printf("png file written: %s%n", pngFile.getCanonicalPath());
}
}
此程序的输出是控制台信息:
font: java.awt.Font[family=SansSerif,name=SansSerif,style=plain,size=40]
pixel bounds: java.awt.Rectangle[x=4,y=-31,width=217,height=31]
font: java.awt.Font[family=SansSerif,name=SansSerif,style=plain,size=80]
pixel bounds: java.awt.Rectangle[x=7,y=-62,width=432,height=63]
font: java.awt.Font[family=SansSerif,name=SansSerif,style=plain,size=120]
pixel bounds: java.awt.Rectangle[x=11,y=-93,width=651,height=94]
png file written: FontSizeTest.png
和图像:
请注意较大的字体大小如何从较小的字体大小绘制偏移量。
如果这是预期的行为,我可以通过获取像素边界的偏移量并使用 translate
调整 x 坐标来调整它;我只是不确定这是预期的行为。我觉得我做错了什么 - 缺少一些 Graphics2D
编程方法。
This page 可能无法直接回答您的问题。但是它有很多关于 Graphics2D 的例子。
此效果是字体的正常行为。甚至 Microsoft Word 在不同大小的文本行中也有这种偏移。
如果您想将所有文本行对齐到同一像素行,您可以将 translate
与您提到的计算像素边界一起使用。
一种更优雅的方法是在 GlyphVector 中移动字形位置。这也会导致 getPixelBounds
结果发生变化。
public static void adjust(GlyphVector gv){
// calc the adjust Factor
int adjust = (int)Math.round(gv.getGlyphVisualBounds(0).getBounds2D().getMinX());
// Shift all the Glyphs in Vector
for (int i = 0; i < gv.getNumGlyphs(); i++) {
Point2D point = gv.getGlyphPosition(i);
gv.setGlyphPosition( i, new Point2D.Double(
point.getX() - adjust,
point.getY()));
}
}
在创建字形向量并获得所需结果后,在代码中使用它。
gv = font.createGlyphVector(frc, "Hello World");
adjust(gv);