ref: 5cd21551131ef3a9690ecbefcc9782286ee5199e
parent: 67b912d2fa17caa921f513cae180c7aae28b1bc6
author: Werner Lemberg <[email protected]>
date: Fri Apr 10 03:01:01 EDT 2015
[cff] Update advance width handling to OpenType 1.7. Problem reported by Behdad. * src/cff/cffdrivr.c (cff_get_advances): Handle SFNT case separately. * src/cff/cffgload.c (cff_slot_load): Use advance width and side bearing values from `hmtx' table if present.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2015-04-10 Werner Lemberg <[email protected]>
+
+ [cff] Update advance width handling to OpenType 1.7.
+
+ Problem reported by Behdad.
+
+ * src/cff/cffdrivr.c (cff_get_advances): Handle SFNT case
+ separately.
+
+ * src/cff/cffgload.c (cff_slot_load): Use advance width and side
+ bearing values from `hmtx' table if present.
+
2015-04-03 Alexei Podtelezhnikov <[email protected]>
* src/autofit/afhints.c (af_glyph_hints_reload): Use do-while loop.
--- a/include/internal/tttypes.h
+++ b/include/internal/tttypes.h
@@ -1111,7 +1111,7 @@
/* This field also contains the associated */
/* vertical metrics table (`vmtx'), if found. */
/* IMPORTANT: The contents of this field is */
- /* undefined if the `verticalInfo' field is */
+ /* undefined if the `vertical_info' field is */
/* unset. */
/* */
/* num_names :: The number of name records within this */
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -195,6 +195,68 @@
FT_GlyphSlot slot = face->glyph;
+ if ( FT_IS_SFNT( face ) )
+ {
+ /* OpenType 1.7 mandates that the data from `hmtx' table be used; */
+ /* it is no longer necessary that those values are identical to */
+ /* the values in the `CFF' table */
+
+ TT_Face ttface = (TT_Face)face;
+ FT_Short dummy;
+
+
+ if ( flags & FT_LOAD_VERTICAL_LAYOUT )
+ {
+ /* check whether we have data from the `vmtx' table at all; */
+ /* otherwise we extract the info from the CFF glyphstrings */
+ /* (instead of synthesizing a global value using the `OS/2' */
+ /* table) */
+ if ( !ttface->vertical_info )
+ goto Missing_Table;
+
+ for ( nn = 0; nn < count; nn++ )
+ {
+ FT_UShort ah;
+
+
+ ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
+ 1,
+ start + nn,
+ &dummy,
+ &ah );
+
+ FT_TRACE5(( " idx %d: advance height %d font units\n",
+ start + nn, ah ));
+ advances[nn] = ah;
+ }
+ }
+ else
+ {
+ /* check whether we have data from the `hmtx' table at all */
+ if ( !ttface->horizontal.number_Of_HMetrics )
+ goto Missing_Table;
+
+ for ( nn = 0; nn < count; nn++ )
+ {
+ FT_UShort aw;
+
+
+ ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
+ 0,
+ start + nn,
+ &dummy,
+ &aw );
+
+ FT_TRACE5(( " idx %d: advance width %d font units\n",
+ start + nn, aw ));
+ advances[nn] = aw;
+ }
+ }
+
+ return error;
+ }
+
+ Missing_Table:
flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
for ( nn = 0; nn < count; nn++ )
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -2725,7 +2725,7 @@
face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 );
- /* get the vertical metrics from the vtmx table if we have one */
+ /* get the vertical metrics from the vmtx table if we have one */
if ( has_vertical_info )
{
(void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
@@ -2953,15 +2953,33 @@
FT_Bool has_vertical_info;
- /* copy the _unscaled_ advance width */
- metrics->horiAdvance = decoder.glyph_width;
- glyph->root.linearHoriAdvance = decoder.glyph_width;
+ if ( face->horizontal.number_Of_HMetrics )
+ {
+ FT_Short horiBearingX = 0;
+ FT_UShort horiAdvance = 0;
+
+
+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
+ glyph_index,
+ &horiBearingX,
+ &horiAdvance );
+ metrics->horiAdvance = horiAdvance;
+ metrics->horiBearingX = horiBearingX;
+ glyph->root.linearHoriAdvance = horiAdvance;
+ }
+ else
+ {
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.glyph_width;
+ glyph->root.linearHoriAdvance = decoder.glyph_width;
+ }
+
glyph->root.internal->glyph_transformed = 0;
has_vertical_info = FT_BOOL( face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 );
- /* get the vertical metrics from the vtmx table if we have one */
+ /* get the vertical metrics from the vmtx table if we have one */
if ( has_vertical_info )
{
FT_Short vertBearingY = 0;
@@ -2968,10 +2986,10 @@
FT_UShort vertAdvance = 0;
- (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
- glyph_index,
- &vertBearingY,
- &vertAdvance );
+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
+ glyph_index,
+ &vertBearingY,
+ &vertAdvance );
metrics->vertBearingY = vertBearingY;
metrics->vertAdvance = vertAdvance;
}
@@ -3046,7 +3064,9 @@
metrics->width = cbox.xMax - cbox.xMin;
metrics->height = cbox.yMax - cbox.yMin;
- metrics->horiBearingX = cbox.xMin;
+ if ( !face->horizontal.number_Of_HMetrics )
+ metrics->horiBearingX = cbox.xMin;
+
metrics->horiBearingY = cbox.yMax;
if ( has_vertical_info )