[truetype] Improve emulation of vertical metrics.

This commit also improves the start values of vertical phantom
points.  Kudos to Greg Hitchcock for help.

* src/truetype/ttgload.c (TT_Get_VMetrics): Add parameter to pass
`yMax' value.  Replace code with fixed Microsoft definition.
(tt_get_metrics): Updated.
(TT_LOADER_SET_PP): Add explanation how to initialize phantom
points, taken from both the OpenType specification and private
communication with Greg (which will eventually be added to the
standard).
Fix horizontal position of `pp3' and `pp4'.

* src/truetype/ttgload.h: Updated.

* src/truetype/ttdriver.c (tt_get_advances): Updated.

* docs/CHANGES: Updated.
This commit is contained in:
Werner Lemberg 2013-11-06 07:14:49 +01:00
parent b1d97810c9
commit 7e4b0fbfdd
5 changed files with 107 additions and 27 deletions

View File

@ -1,3 +1,25 @@
2013-11-06 Werner Lemberg <wl@gnu.org>
[truetype] Improve emulation of vertical metrics.
This commit also improves the start values of vertical phantom
points. Kudos to Greg Hitchcock for help.
* src/truetype/ttgload.c (TT_Get_VMetrics): Add parameter to pass
`yMax' value. Replace code with fixed Microsoft definition.
(tt_get_metrics): Updated.
(TT_LOADER_SET_PP): Add explanation how to initialize phantom
points, taken from both the OpenType specification and private
communication with Greg (which will eventually be added to the
standard).
Fix horizontal position of `pp3' and `pp4'.
* src/truetype/ttgload.h: Updated.
* src/truetype/ttdriver.c (tt_get_advances): Updated.
* docs/CHANGES: Updated.
2013-11-05 Werner Lemberg <wl@gnu.org>
* builds/windows/vc2010/freetype.vcxproj: s/v110/v100/.

View File

@ -11,6 +11,10 @@ CHANGES BETWEEN 2.5 and 2.5.1
- Many fields of the `PCLT' table in SFNT based fonts (if accessed
with `FT_Get_Sfnt_Table') were computed incorrectly.
- In TrueType fonts, hinting of composite glyphs could sometimes
deliver incorrect positions of components or even distorted
shapes.
II. IMPORTANT CHANGES
@ -76,6 +80,12 @@ CHANGES BETWEEN 2.5 and 2.5.1
to set selector bit 6 to get results for selector bits 7-10,
which is wrong.
- Improved computation of emulated vertical metrics for TrueType
fonts.
- Fixed horizontal start-up position of vertical phantom points in
TrueType bytecode.
======================================================================

View File

@ -215,7 +215,8 @@
FT_UShort ah;
TT_Get_VMetrics( face, start + nn, &tsb, &ah );
/* since we don't need `tsb', we use zero for `yMax' parameter */
TT_Get_VMetrics( face, start + nn, 0, &tsb, &ah );
advances[nn] = ah;
}
}

View File

@ -85,45 +85,30 @@
/*************************************************************************/
/* */
/* Return the vertical metrics in font units for a given glyph. */
/* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
/* table, typoAscender/Descender from the `OS/2' table would be used */
/* instead, and if there were no `OS/2' table, use ascender/descender */
/* from the `hhea' table. But that is not what Microsoft's rasterizer */
/* apparently does: It uses the ppem value as the advance height, and */
/* sets the top side bearing to be zero. */
/* See macro `TT_LOADER_SET_PP' below for explanations. */
/* */
FT_LOCAL_DEF( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
FT_Pos yMax,
FT_Short* tsb,
FT_UShort* ah )
{
if ( face->vertical_info )
( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
#if 1 /* Empirically determined, at variance with what MS said */
else
{
*tsb = 0;
*ah = face->root.units_per_EM;
}
#else /* This is what MS said to do. It isn't what they do, however. */
else if ( face->os2.version != 0xFFFFU )
{
*tsb = face->os2.sTypoAscender;
*tsb = face->os2.sTypoAscender - yMax;
*ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
}
else
{
*tsb = face->horizontal.Ascender;
*tsb = face->horizontal.Ascender - yMax;
*ah = face->horizontal.Ascender - face->horizontal.Descender;
}
#endif
FT_TRACE5(( " advance height (font units): %d\n", *ah ));
FT_TRACE5(( " top side bearing (font units): %d\n", *tsb ));
}
@ -146,6 +131,7 @@
&left_bearing,
&advance_width );
TT_Get_VMetrics( face, glyph_index,
loader->bbox.yMax,
&top_bearing,
&advance_height );
@ -1263,18 +1249,78 @@
}
/* Calculate the four phantom points. */
/* The first two stand for horizontal origin and advance. */
/* The last two stand for vertical advance and origin. */
/*
* Calculate the phantom points
*
* Defining the right side bearing (rsb) as
*
* rsb = aw - (lsb + xmax - xmin)
*
* (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
* and `xmax' the glyph's minimum and maximum x value), the OpenType
* specification defines the initial position of horizontal phantom points
* as
*
* pp1 = (xmin - lsb, 0) ,
* pp2 = (pp1 + aw, 0) .
*
* However, the specification lacks the precise definition of vertical
* phantom points. Greg Hitchcock provided the following explanation.
*
* - a `vmtx' table is present
*
* For any glyph, the minimum and maximum y values (`ymin' and `ymax')
* are given in the `glyf' table, the top side bearing (tsb) and advance
* height (ah) are given in the `vmtx' table. The bottom side bearing
* (bsb) is then calculated as
*
* bsb = ah - (tsb + ymax - ymin) ,
*
* and the initial position of vertical phantom points is
*
* pp3 = (x, ymax + tsb) ,
* pp4 = (x, pp3 - ah) .
*
* See below for value `x'.
*
* - no `vmtx' table in the font
*
* If there is an `OS/2' table, we set
*
* DefaultAscender = sTypoAscender ,
* DefaultDescender = sTypoDescender ,
*
* otherwise we use data from the `hhea' table:
*
* DefaultAscender = Ascender ,
* DefaultDescender = Descender .
*
* With these two variables we can now set
*
* ah = DefaultAscender - sDefaultDescender ,
* tsb = DefaultAscender - yMax ,
*
* and proceed as if a `vmtx' table was present.
*
* Usually we have
*
* x = aw / 2 ,
*
* but there is a compatibility case where it can be set to
*
* x = -DefaultDescender -
* ((DefaultAscender - DefaultDescender - aw) / 2) .
*
*/
#define TT_LOADER_SET_PP( loader ) \
do { \
(loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
(loader)->pp1.y = 0; \
(loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
(loader)->pp2.y = 0; \
(loader)->pp3.x = 0; \
(loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
(loader)->pp4.x = 0; \
(loader)->pp3.x = (loader)->advance / 2; \
(loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing; \
(loader)->pp4.x = (loader)->advance / 2; \
(loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
} while ( 0 )

View File

@ -43,6 +43,7 @@ FT_BEGIN_HEADER
FT_LOCAL( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
FT_Pos yMax,
FT_Short* tsb,
FT_UShort* ah );