Java: ¿Ascenso de FontMetrics incorrecto?

Cuando miro el javadoc paraFontMetric.getAscent() Veo

El ascenso de la fuente es la distancia desde la línea base de la fuente hasta la parte superior de la mayoría de los caracteres alfanuméricos. Algunos caracteres en la fuente pueden extenderse por encima de la línea de ascenso de la fuente.

Pero escribí un programa de demostración rápida y veo esto:

donde las 4 líneas horizontales para cada fila de texto son:

osición de la línea base bajada porgetDescent()baseline positionosición de la línea de base planteada porgetAscent()osición de la línea de base planteada porgetHeight()

Observe el espacio entre la línea getAscent () y la parte superior de los caracteres. He examinado la mayoría de las fuentes y tamaños, y siempre existe esta brecha. (Mientras que el descenso de la fuente se ve bien).¿Lo que da

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);
    }
}

Respuestas a la pregunta(3)

Su respuesta a la pregunta