From 5cd21551131ef3a9690ecbefcc9782286ee5199e Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Fri, 10 Apr 2015 07:01:01 +0200 Subject: [PATCH] [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. --- ChangeLog | 12 ++++++++ include/internal/tttypes.h | 2 +- src/cff/cffdrivr.c | 62 ++++++++++++++++++++++++++++++++++++++ src/cff/cffgload.c | 40 ++++++++++++++++++------ 4 files changed, 105 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 985a889fb..ad0c031e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2015-04-10 Werner Lemberg + + [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 * src/autofit/afhints.c (af_glyph_hints_reload): Use do-while loop. diff --git a/include/internal/tttypes.h b/include/internal/tttypes.h index 1d442f7b9..31dd0aac6 100644 --- a/include/internal/tttypes.h +++ b/include/internal/tttypes.h @@ -1111,7 +1111,7 @@ FT_BEGIN_HEADER /* 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 */ diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c index 35e23b97d..f46a1c574 100644 --- 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++ ) diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index b5bc4a27e..d73138717 100644 --- 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,25 +2953,43 @@ 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; 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 )