[sfnt] Use typo metrics if OS/2 fsSelection USE_TYPO_METRICS bit is set.

If the OS/2 table exists and fsSelection bit 7 (USE_TYPO_METRICS) is set,
use the sTypo* set of values to compute the FT_Face's ascender, descender
and height. Otherwise, fall back to old behavior.

* src/sfnt/sfobjs.c (sfnt_load_face): Implement.
This commit is contained in:
Nikolaus Waxweiler 2019-02-02 15:45:31 +00:00
parent f686ad46a3
commit f72b00746c
2 changed files with 74 additions and 50 deletions

View File

@ -1,3 +1,13 @@
2019-02-02 Nikolaus Waxweiler <madigens@gmail.com>
[sfnt] Use typo metrics if OS/2 fsSelection USE_TYPO_METRICS bit is set.
If the OS/2 table exists and fsSelection bit 7 (USE_TYPO_METRICS) is set,
use the sTypo* set of values to compute the FT_Face's ascender, descender
and height. Otherwise, fall back to old behavior.
* src/sfnt/sfobjs.c (sfnt_load_face): Implement.
2019-01-18 John Tytgat <John.Tytgat@esko.com> 2019-01-18 John Tytgat <John.Tytgat@esko.com>
[sfnt] Handle TT fonts having two PostScript font names (#55471). [sfnt] Handle TT fonts having two PostScript font names (#55471).
@ -420,7 +430,7 @@
* src/base/ftobjs.c (ft_glyphslot_preset_bimap): Another tweak. * src/base/ftobjs.c (ft_glyphslot_preset_bimap): Another tweak.
This one should be clearer. When the rounded monochrome bbox collapses This one should be clearer. When the rounded monochrome bbox collapses
we add a pixel that covers most if not all original cbox. we add a pixel that covers most if not all original cbox.
2018-09-21 Alexei Podtelezhnikov <apodtele@gmail.com> 2018-09-21 Alexei Podtelezhnikov <apodtele@gmail.com>

View File

@ -1641,59 +1641,73 @@
root->units_per_EM = face->header.Units_Per_EM; root->units_per_EM = face->header.Units_Per_EM;
/* XXX: Computing the ascender/descender/height is very different */ /*
/* from what the specification tells you. Apparently, we */ * Computing the ascender/descender/height is tricky.
/* must be careful because */ *
/* */ * The OpenType specification v1.8.3 says:
/* - not all fonts have an OS/2 table; in this case, we take */ *
/* the values in the horizontal header. However, these */ * [OS/2's] sTypoAscender, sTypoDescender and sTypoLineGap fields
/* values very often are not reliable. */ * are intended to allow applications to lay out documents in a
/* */ * typographically-correct and portable fashion.
/* - otherwise, the correct typographic values are in the */ *
/* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ * This is somewhat at odds with the decades of backwards
/* */ * compatibility, operating systems and applications doing whatever
/* However, certain fonts have these fields set to 0. */ * they want, not to mention broken fonts.
/* Rather, they have usWinAscent & usWinDescent correctly */ *
/* set (but with different values). */ * Not all fonts have an OS/2 table; in this case, we take the values
/* */ * in the horizontal header, although there is nothing stopping the
/* As an example, Arial Narrow is implemented through four */ * values from being unreliable. Even with a OS/2 table, certain fonts
/* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ * set the sTypoAscender, sTypoDescender and sTypoLineGap fields to 0
/* */ * and instead correctly set usWinAscent and usWinDescent.
/* Strangely, all fonts have the same values in their */ *
/* sTypoXXX fields, except ARIALNB which sets them to 0. */ * As an example, Arial Narrow is shipped as four files ARIALN.TTF,
/* */ * ARIALNI.TTF, ARIALNB.TTF and ARIALNBI.TTF. Strangely, all fonts have
/* On the other hand, they all have different */ * the same values in their sTypo* fields, except ARIALNB.ttf which
/* usWinAscent/Descent values -- as a conclusion, the OS/2 */ * sets them to 0. All of them have different usWinAscent/Descent
/* table cannot be used to compute the text height reliably! */ * values. The OS/2 table therefore cannot be trusted for computing the
/* */ * text height reliably.
*
* As a compromise, do the following:
*
* 1. If the OS/2 table exists and the fsSelection bit 7 is set
* (USE_TYPO_METRICS), trust the font and use the sTypo* metrics.
* 2. Otherwise, use the `hhea' table's metrics.
* 3. If they are zero and the OS/2 table exists,
* 1. use the OS/2 table's sTypo* metrics if they are non-zero.
* 2. Otherwise, use the OS/2 table's usWin* metrics.
*/
/* The ascender and descender are taken from the `hhea' table. */ if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 128 )
/* If zero, they are taken from the `OS/2' table. */
root->ascender = face->horizontal.Ascender;
root->descender = face->horizontal.Descender;
root->height = root->ascender - root->descender +
face->horizontal.Line_Gap;
if ( !( root->ascender || root->descender ) )
{ {
if ( face->os2.version != 0xFFFFU ) root->ascender = face->os2.sTypoAscender;
root->descender = face->os2.sTypoDescender;
root->height = root->ascender - root->descender +
face->os2.sTypoLineGap;
}
else
{
root->ascender = face->horizontal.Ascender;
root->descender = face->horizontal.Descender;
root->height = root->ascender - root->descender +
face->horizontal.Line_Gap;
if ( !( root->ascender || root->descender ) )
{ {
if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) if ( face->os2.version != 0xFFFFU )
{ {
root->ascender = face->os2.sTypoAscender; if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
root->descender = face->os2.sTypoDescender; {
root->ascender = face->os2.sTypoAscender;
root->height = root->ascender - root->descender + root->descender = face->os2.sTypoDescender;
face->os2.sTypoLineGap; root->height = root->ascender - root->descender +
} face->os2.sTypoLineGap;
else }
{ else
root->ascender = (FT_Short)face->os2.usWinAscent; {
root->descender = -(FT_Short)face->os2.usWinDescent; root->ascender = (FT_Short)face->os2.usWinAscent;
root->descender = -(FT_Short)face->os2.usWinDescent;
root->height = root->ascender - root->descender; root->height = root->ascender - root->descender;
}
} }
} }
} }