The problem I am facing is, that the descent that I get from a font metrics object seems to be incorrect. This is only noticable on very big fonts. I already tried using the FontMetrics#getDescent
-method and the FontMetrics#getStringBounds
-Method of which i then used height
and y
to manually make out the descent. While both give a slightly different result, both are incorrect. What is the most correct way to get a correct baseline for a pre-defined set of characters? In my case it'd be the characters 0-9
. These should all have the same baseline and therefore be easy to center. So my assumption at least.
Here's an example showcasing the problem:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.UIManager;
public class Draw
{
public static void main( String[] args )
{
JFrame frame = new JFrame();
frame.add( new X() );
frame.pack();
frame.setSize( 150, 300 );
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
private static class X extends JComponent
{
private final Font xFont;
public X()
{
xFont = UIManager.getFont( "Label.font" ).deriveFont( 40.0f );
}
@Override
public void paint( Graphics g )
{
g.setColor( Color.YELLOW );
g.fillRect( 0, 0, getWidth(), getHeight() );
g.setColor( Color.BLACK );
g.drawLine( 0, getHeight() / 2, getWidth() - 1, getHeight() / 2 );
g.setFont( xFont );
g.drawString( "X", getWidth() / 2, getHeight() / 2 + g.getFontMetrics().getDescent() );
}
}
}
The black line represents the middle of the component. The vertical center of the X
should be aligned with the line.
The following seems to work even with large fonts. The adjustment was to subtract both the leading
and the descent
from the ascent
and divide by two. It would seem if you don't include the leading, the text drifts for large fonts. In this example, the font size is 300
. For smaller fonts, it may not be a problem.
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(0, getHeight() / 2, getWidth(),
getHeight() / 2);
g.setFont(xFont);
String s = "X";
FontMetrics fm = g.getFontMetrics();
int swidth = fm.stringWidth(s);
int ctrx = getWidth() / 2;
int ctry = getHeight() / 2;
int mheight = fm.getAscent() - fm.getDescent() - fm.getLeading();
g.drawString(s, ctrx - swidth/2, ctry + mheight/2);
}