[OpenJDK 2D-Dev] Font rendering issue

Phil Race philip.race at oracle.com
Wed May 19 21:34:03 UTC 2010

Roman Kennke wrote:
> Hi Phil,
>> - Swing understands that there's no guarantee that all the pixels fit
>>    in the reported height of the line. I don't think you want to space
>>    out the text so much that you guarantee no glyph overlap.
> No, that's not really the point. Swing assumes wrongly that all pixels
> *do* fit into 'height'. This leads to (e.g.) '_' beeing cut off.

What I was saying is that they know problems can arise but its a compromise.
I recall there were attempts in the past to ensure mnemonics were properly
positioned and I would suppose, visible.
You need to use logical metrics, not the glyph's visual bounds to position
an underline otherwise it'll be like a wandering baseline
However you don't know where all the pixels fall from font-wide metrics, 
and glyphs
with diacritics have been known to be placed above the supposed max ascent.

BTW Its not just ascent and descent, there's problems on the left and 
right sometimes
as logical left and advance don't necessarily encompass all the pixels.

So maybe Swing is culpable here. Its also possible that
something isn't ideal in the delicate task of making choices about how
to round up several inter-related floating point numbers
What I'd like to have is a small test case that demonstrates exactly 
this so I can follow the chain.
Mario sounds to  have  that, right down to specific font and size and 
using the same mnemonic
positioning logic as swing.

>>  Actually
>>    due to some perhaps questionable choices of the fields in the font
>>    which should be used AND the way that the height of logical
>>    fonts is assembled (the maximum leading of all components +
>>    the maximum descent of all components + the maximum ascent of all 
>> components)
>>    its higher than I'd like. Much as I'd love to fix this its going to 
>> get someone upset,
>>    so I've steered well clear. This goes all the way back to 1.1
> Yeah.
>>   We have less compatibility history to maintain (in the behavioural 
>> sense) in the freetype code
>>    so that's easier to change.
> Yeah, but do we really want to bend what freetype reports correctly,
> only to make it fit with existing code? I.e. introduce workarounds at
> the low level to fix other (multiple levels) of workarounds and bugs at
> higher levels? I don't know. I'd rather get text rendering correct even
> if it makes somebody upset. (But that's just me..)
Leaving aside for a moment the issue of the rounding problem,
What is "correct"  metrics ?
T2K (the JDK  rasteriser) was from one of the original Apple truetype 
and Apple have always used the hhea table for ascent, descent, and linegap
and so does T2K

freetype, I don't know for sure sfnt_load_face has several options and
some of them are ifdefed out in the source I have for 2.3.5

The part that's not ifdefed out appear to use the same data as the JDK

        root->ascender  = face->horizontal.Ascender;
        root->descender = face->horizontal.Descender;

        root->height    = (FT_Short)( root->ascender - root->descender +
                                      face->horizontal.Line_Gap );

The ifdefed out code gets it from the OS/2 table's  
typoAscender/typoDescender .
(BTW there's also usWinAscent/usWinDescent. My impression is that 
Windows GDI
has always used the latter, although maybe GDI+ and other APIs use the

None of these are wrong. They are just different.
So long as they are internally consistent this is fine.

BTW as MS note you can get clipping with usWin values too ..

Since with T2K we are using data from the hhea, we are essentially getting
max ascent as ascent and max descent as descent.

This is an unfortunate state of affairs but one that's risky to change.
Where I can imagine that this might cause problems is in code that got used
to ascent/descent being "max" values, and it doesn't work so well when they
are not. Perhaps some of the problems in Swing are related to that except
that if freetype is doing this too, I'm not sure we can blame that.

>>   Anything in the shared code, I'd want to actually try out. Any claimed 
>> errors
>>   in the closed code, I'd want to track down and see if its actually so and
>>   what we can/should do about it.
> You can easily try out the reported problems. For example, fire up
> Netbeans with OpenJDK on Ubuntu or Fedora, and you'll see that the '_'
> is not rendered in many cases, which is *very* irritating because in
> code, you really want to see '_'.
>>   If I have things right, the most obvious problem Mario saw is a negative
>>   value for leading. That could be an incorrect interpretation of sign 
>> somewhere?
> I think this comes from height, ascent and descent not beeing
> 'consistent' in the sense that height-ascent-descent=leading. In this
> particular case, ascent+descent is one pixel more than height, and
> leading ends up at -1, even though in the font, you have an (unscaled)
> leading of 0. 

Is that exactly what you see ?
The final calculation for reporting the integer value for leading is 
            (int)(0.95f  + descent + leading) -  (int)(0.95f  + descent);

I must be missing something I don't see how this could end up negative 
if leading were 0
unscaled or otherwise. What could happen is if  it became a very small 
value, like -0.01, and this coincided with descent with a value like 
3.05, which
would be just enough to make the first expression round down  ..
(int) (0.95 + 3.05 - 0.01) - (int)(0.95+3.05)  => (int)(3.99) - 
(int)(4.00) => 3 - 4 => -1 ..

It looks like freetype and t2k are reading the leading from the same 
field so I
can't see that I can point to a difference there being part of it,
I think I'd need to take a look at exactly what is going on in running 
Mario's  test program.

> This is a problem introduced by the grid fitting, all of
> ascent, descent and height are adjusted for grid-fitting, but leading
> not (actually, freetype does not report a scaled linegap/leading and we
> calculate it from the other 3 values).

This doesn't seem right. They do need to be scaled to adjust for point size
but font-wide metrics are completely unaffected by hinting.
Hinting is applied to a glyph and so can affect glyph specific values such
as advance, as well as its image, but it has no bearing on font wide 

>> Seems like rounding up to get rid of it isn't addressing the real problem
> I believe that we should take the unscaled leading value from the font
> and apply the scaling transform ourselves. That's the best that we can
> do I think.

> /Roman

More information about the 2d-dev mailing list