在给定字体大小和dpi屏幕分辨率的情况下,Java2d/AWT文本呈现的奇怪大小/边界?
我刚开始在屏幕上直接使用Java2D/AWT呈现文本。从本质上讲,它是有效的,但我很难理解AWT报告并在屏幕上呈现的结果的像素大小/尺寸 参数:在给定字体大小和dpi屏幕分辨率的情况下,Java2d/AWT文本呈现的奇怪大小/边界?,java,fonts,size,awt,dpi,Java,Fonts,Size,Awt,Dpi,我刚开始在屏幕上直接使用Java2D/AWT呈现文本。从本质上讲,它是有效的,但我很难理解AWT报告并在屏幕上呈现的结果的像素大小/尺寸 参数: 文本为“这是一个字形测试” 字体是java.awt.Font[family=Dialog,name=sans,style=plain,size=72](pt) 屏幕分辨率96 dpi 平台是x86-64 Linux X11,带有Java 8 屏幕分辨率由Toolkit.getDefaultToolkit().getScreenResolution(
- 文本为“这是一个字形测试”
- 字体是java.awt.Font[family=Dialog,name=sans,style=plain,size=72](pt)
- 屏幕分辨率96 dpi
- 平台是x86-64 Linux X11,带有Java 8
- 边界是java.awt.geom.Rectangle2D$Float[x=0.0,y=-71.55469,w=448.0,h=55.875]
- 字体上升:45像素
- 字体下降:12像素
- 字体高度:57像素
- 有人能重现类似于我的价值观吗?还是它们非常不典型
- 如何计算边界高度/字体高度?(我预计字体高度为96像素,72像素)
- 或者:在Java中,字体大小参数的解释(单位)是什么
- 正是由于AWT中的舍入或其他不准确错误,使得界限。h与度量值、高度和度量值、上升+下降不同,还是这种差异是有价值的信息
- 我是否遗漏了其他相关参数?(此处不涉及仿射变换。)
- 是否有一种安全(跨平台)的方法可以在96 dpi设备和72 pt字体大小上使字体高度可靠地达到96 px?(将字体大小乘以常量值是否可以接受?)
- 问题解决:是我的错强>
更准确地说:我实际上不是通过简单的
newfont(Font.DIALOG,Font.PLAIN,72))
或类似方法初始化Font对象,而是使用newfont(Map attributes)
构造函数。那张地图上有各种各样的字体属性,都是从我的配置中预设的。因为一个变量预设了错误的值,它实际上包含了一个map.put(上标,上标_SUPER)代码>(在我的实际代码中没有这里显示的那么清楚)
因此,这些奇怪的边界实际上是字体一直被创建为其较小的上标变体的结果。否则,边界/创建的文本大小将更接近我的预期:
对话框,样式=普通,大小=72],高度:84,上升:67,下降:17,边界:java.awt.geom.Rectangle2D$Float[x=0.0,y=-66.83203,w=681.0,h=83.8125]
虽然它们的尺寸与目标尺寸不完全相同,但它们更接近目标尺寸。感谢用户1803551的MCVE建议,使我走上正轨。为了完整起见,这里是(省略):
公共最终类TextRenderTest扩展了WindowAdapter{
int-fontSource;
静态私有最终字符串TESTTEXT=“这是一个glyph测试”;
静态公共void main(字符串[]args){new TextRenderTest().main();}
空干管(){
帧帧=新帧(“文本渲染测试”){
@替代公共空白绘制(图形g){
FontMetrics fm;
字体;
g、 setFont(fontSource++%2==0?createFont():新字体(Font.DIALOG,Font.PLAIN,72));
g、 抽绳(TESTTEXT,16,96);
fm=g.getFontMetrics();
System.out.println(
“DPI:+Toolkit.getDefaultToolkit().getScreenResolution()+
,字体:“+g.getFont()+”,字体高度:“+fm.getHeight()+
,上升:“+fm.getAscent()+”,下降:“+fm.getDescent()+
,边界:“+fm.getStringBounds(TESTTEXT,g));};
框架立根(64,32,800,280);
frame.setVisible(true);
frame.addWindowListener(此);
}
静态专用字体createFont(){
HashMap-map=新的HashMap(9,1.0f);
map.put(FAMILY,“sans”);
map.put(重量,500);
map.put(宽度,1);
map.put(大小72);
map.put(上标,上标_SUPER)5944不太可能没有,特别是因为它已经存在了很长一段时间,而且Javadoc可以非常复杂。
public final class TextRenderTest extends WindowAdapter {
int fontSource;
static private final String TESTTEXT = "This is a glyph test";
static public void main (String [] args) { new TextRenderTest ().main (); }
void main () {
Frame frame = new Frame ("Text render test") {
@Override public void paint (Graphics g) {
FontMetrics fm;
Font font;
g.setFont (fontSource++ % 2 == 0 ? createFont () : new Font (Font.DIALOG, Font.PLAIN, 72));
g.drawString (TESTTEXT, 16, 96);
fm = g.getFontMetrics ();
System.out.println (
"DPI: " + Toolkit.getDefaultToolkit ().getScreenResolution () +
", font: " + g.getFont () + ", font height: " + fm.getHeight () +
", ascent: " + fm.getAscent () + ", descent: " + fm.getDescent () +
", bounds: " + fm.getStringBounds (TESTTEXT, g)); } };
frame.setBounds (64, 32, 800, 280);
frame.setVisible (true);
frame.addWindowListener (this);
}
static private Font createFont () {
HashMap <TextAttribute,Object> map = new HashMap<TextAttribute,Object> (9, 1.0f);
map.put (FAMILY, "sans");
map.put (WEIGHT, 500);
map.put (WIDTH, 1);
map.put (SIZE, 72);
map.put (SUPERSCRIPT, SUPERSCRIPT_SUPER); // <-- Something like this was the fault
return new Font (map);
}
@Override public void windowClosing (WindowEvent event) { event.getWindow ().dispose (); }
}