<Swing Dev> Text rendering/layout problem in Swing

Roman Kennke roman at kennke.org
Fri May 7 20:06:52 UTC 2010


While hunting a bug in the Freetype Fontscaler, I came over an issue in
the way Swing lays out and renders text.

In many (if not all) cases in Swing, FontMetrics.getHeight() is used to
lay out text inside a text component or label. For example, in
PlainView, we use numberOfLines * fm.getHeight() to determine the height
of the text component. I believe this is wrong. Font height is defined
as the distance between two consecutive lines of text, from baseline to
baseline. As the API docs state, two lines can overlap a little, for
example, the undershoot of a 'g' can overlap into the next line. This is
what actually happens with Freetype on certain fonts (I can see this on
a Ubuntu install when running the Font2Demo for example, see
http://www.limasoftware.net/neugens/downloads/stuff/font2dbug/bug.png).
The problem is that the undershoot is then sometimes clipped away. The
correct way to measure these things is (according to several sources I
found in the web):

- Use ascent to determine the amount of space from the top of a text
frame/component to the first baseline.
- Use height to determine the amount of space from one baseline to the
next.
- Use descent to determine the amount of space from the last baseline to
the bottom of the text frame/component.

This is also consonant with the API docs of FontMetrics.getHeight(). Due
to hinting effects it is not necessarily the case that height = ascent +
descent + leading. In particular, it can happen that height < ascent +
descent + leading. Also, in cases where leading != 0, it is possible
that a text component ends up with a pixel (or so) too much space at the
bottom (the additional leading of the last line, which is actually not
necessary).

For single line text components (labels, fields) this boils down to
using fm.getAscent() + fm.getDescent() for the total height.

For multiline text components this needs to be fm.getAscent() + numLines
* fm.getHeight() + fm.getDescent().

Doing this for labels (see attached patch) fixes the problem that I see
with OpenJDK+FreeType on Ubuntu as mentioned above. But it is clear that
this problem exists all over the place in Swing. My question would be if
it is considered feasible to fix this or if such a change would not even
be considered due to compatibility reasons and similar. I believe this
will improve text rendering subtly but considerably.

Thanks, Roman

-------------- next part --------------
A non-text attachment was scrubbed...
Name: fixlabellayout.patch
Type: text/x-patch
Size: 577 bytes
Desc: not available
URL: <http://mail.openjdk.java.net/pipermail/swing-dev/attachments/20100507/7ee072b1/fixlabellayout.patch>


More information about the swing-dev mailing list