Java:FontMetrics上升不正确? [英] Java: FontMetrics ascent incorrect?

查看:125
本文介绍了Java:FontMetrics上升不正确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我查看javadoc 记入字母。



例如,添加变形金刚ÄÖÜ表明他们的trema更接近上升(尽管他们仍然没有达到它)。



寻找更一般的上升定义我发现维基百科中的定义


[..] ascent 跨越基线和距离基线最远的字形顶部之间的距离。上升和下降可能包括也可能不包括由重音符号或变音符号添加的距离。


所以看起来即使在排版中也没有精确,绝对的定义。


When I look at the javadoc for FontMetric.getAscent() I see:

The font ascent is the distance from the font's baseline to the top of most alphanumeric characters. Some characters in the Font might extend above the font ascent line.

But I wrote a quick demo program and I see this:

where the 4 horizontal lines for each row of text are:

  • baseline position lowered by getDescent()
  • baseline position
  • baseline position raised by getAscent()
  • baseline position raised by getHeight()

Notice the space between the getAscent() line and the top of the characters. I've looked at most of the fonts and sizes, and there's always this gap. (Whereas the font descent looks just right.) What gives?

package com.example.fonts;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextPane;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class FontMetricsExample extends JFrame
{
    static final int marg = 10;
    public FontMetricsExample()
    {
        super(FontMetricsExample.class.getSimpleName());

        JPanel panel = new JPanel(new BorderLayout());
        JPanel fontPanel = new JPanel(new BorderLayout());
        final JTextPane textSource = new JTextPane();
        textSource.setText("ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
                +"abcdefghijklmnopqrstuvwxyz\n"
                +"0123456789!@#$%^&*()[]{}");
        final SpinnerNumberModel fontSizeModel = 
              new SpinnerNumberModel(18, 4, 32, 1);
        final String fonts[] = 
              GraphicsEnvironment.getLocalGraphicsEnvironment()
                .getAvailableFontFamilyNames();
        final JComboBox fontFamilyBox = new JComboBox(fonts);
        fontFamilyBox.setSelectedItem("Arial");

        final JPanel text = new JPanel() {
            @Override protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                String fontFamilyName = 
                         fonts[fontFamilyBox.getSelectedIndex()]; 
                int fontSize = fontSizeModel.getNumber().intValue();
                Font f = new Font(fontFamilyName, 0, fontSize);
                g.setFont(f);
                FontMetrics fm = g.getFontMetrics();
                int lineHeight = fm.getHeight();
                String[] s0 = textSource.getText().split("\n");
                int x0 = marg;
                int y0 = getHeight()-marg-(marg+lineHeight)*s0.length;
                for (int i = 0; i < s0.length; ++i)
                {
                    y0 += marg+lineHeight;
                    String s = s0[i];
                    g.drawString(s, x0, y0);
                    int w = fm.stringWidth(s);
                    for (int yofs : Arrays.asList(
                            0,   // baseline
                            -fm.getHeight(),
                            -fm.getAscent(),
                            fm.getDescent()))
                    {
                        g.drawLine(x0,y0+yofs,x0+w,y0+yofs);
                    }
                }
            }
        };
        final JSpinner fontSizeSpinner = new JSpinner(fontSizeModel);
        fontSizeSpinner.getModel().addChangeListener(
               new ChangeListener() {           
            @Override public void stateChanged(ChangeEvent e) {
                text.repaint();
            }
        });
        text.setMinimumSize(new Dimension(200,100));
        text.setPreferredSize(new Dimension(400,150));
        ActionListener repainter = new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
                text.repaint();
            }           
        };
        textSource.getDocument().addDocumentListener(new DocumentListener() {
            @Override public void changedUpdate(DocumentEvent e) {
                text.repaint();             
            }
            @Override public void insertUpdate(DocumentEvent e) {}
            @Override public void removeUpdate(DocumentEvent e) {}
        });
        fontFamilyBox.addActionListener(repainter);

        fontPanel.add(fontFamilyBox, BorderLayout.CENTER);
        fontPanel.add(fontSizeSpinner, BorderLayout.EAST);
        fontPanel.add(textSource, BorderLayout.SOUTH);
        panel.add(fontPanel, BorderLayout.NORTH);
        panel.add(text, BorderLayout.CENTER);       
        setContentPane(panel);
        pack();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        new FontMetricsExample().setVisible(true);
    }
}

解决方案

One possible reason is that this value takes into accounts letters with diacritics.

For example, adding the umlauts ÄÖÜ shows that their trema are much closer to the ascent (although they still don't quite reach it).

Looking for a more general definition of ascent I find the definition in Wikipedia:

[..] the ascent spans the distance between the baseline and the top of the glyph that reaches farthest from the baseline. The ascent and descent may or may not include distance added by accents or diacritical marks.

So it seems that even within typography there is no precise, absolute definition.

这篇关于Java:FontMetrics上升不正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆