diff --git a/ChangeLog b/ChangeLog index b8186c545..c6ae94e2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,17 +1,29 @@ +2005-11-17 Werner Lemberg + + Add vertical metrics support to OpenType CFF outlines. Based on a + patch from Mike Moening + + * src/cff/cffgload.c (cff_face_get_vertical_metrics): New function. + (cff_slot_load): Use cff_face_get_vertical_metrics. + + * docs/CHANGES: Updated. + 2005-11-17 Chia-I Wu * src/base/ftcalc.c (FT_MulTo64): Commented out. - * include/freetype/internal/ftcalc.h (FT_SqrtFixed), src/base/ftcalc.c - (FT_SqrtFixed), include/freetype/internal/ftdebug.h + * include/freetype/internal/ftcalc.h (FT_SqrtFixed), + src/base/ftcalc.c (FT_SqrtFixed), + include/freetype/internal/ftdebug.h (FT_Trace_Get_Count, + FT_Trace_Get_Name, FT_Message, FT_Panic), src/base/ftdebug.c (FT_Trace_Get_Count, FT_Trace_Get_Name, FT_Message, FT_Panic), - src/base/ftdebug.c (FT_Trace_Get_Count, FT_Trace_Get_Name, FT_Message, - FT_Panic), include/freetype/internal/ftobjs.h (FT_New_Memory, - FT_Done_Memory), include/freetype/internal/ftstream.h - (FT_Stream_Open), src/base/ftsystem.c (FT_New_Memory, FT_Done_Memory, - FT_Stream_Open): s/FT_EXPORT/FT_BASE/. + include/freetype/internal/ftobjs.h (FT_New_Memory, FT_Done_Memory), + include/freetype/internal/ftstream.h (FT_Stream_Open), + src/base/ftsystem.c (FT_New_Memory, FT_Done_Memory, FT_Stream_Open): + s/FT_EXPORT/FT_BASE/. - * builds/exports.mk: Manually add TT_New_Context to EXPORTS_LIST too. + * builds/exports.mk: Manually add TT_New_Context to EXPORTS_LIST + too. 2005-11-15 David Turner diff --git a/docs/CHANGES b/docs/CHANGES index 0a9f3520c..6295ec2f3 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -6,6 +6,9 @@ LATEST CHANGES BETWEEN 2.2.0 and 2.1.10 - The FT_HAS_KERNING macro always returned 0. + - CFF OpenType fonts didn't return correct vertical metrics for + glyphs with outlines. + II. IMPORTANT CHANGES - A new API `FT_TrueTypeGX_Validate' (in FT_GX_VALIDATE_H) has diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index f4e775308..d4ea07b36 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -569,6 +569,117 @@ } + /*************************************************************************/ + /* */ + /* */ + /* cff_face_get_vertical_metrics */ + /* */ + /* */ + /* Return the vertical metrics in font units for a given glyph. The */ + /* metrics are the top side bearing and advance height. */ + /* */ + /* */ + /* header :: A pointer to the vertical metrics structure. */ + /* */ + /* idx :: The glyph index. */ + /* */ + /* */ + /* bearing :: The top side bearing. */ + /* */ + /* advance :: The advance height. */ + /* */ + /* */ + /* Horizontal metric values are directly computed from the CFF data, */ + /* bypassing the `hmtx' table completely. */ + /* */ +#ifdef FT_OPTIMIZE_MEMORY + + static void + cff_face_get_vertical_metrics( TT_Face face, + FT_UInt idx, + FT_Short *abearing, + FT_UShort *aadvance ) + { + TT_VertHeader* header; + FT_Byte* p; + FT_Byte* limit; + FT_UShort k; + + + header = &face->vertical; + p = face->vert_metrics; + limit = p + face->vert_metrics_size; + + k = header->number_Of_VMetrics; + + if ( k > 0 ) + { + if ( idx < (FT_UInt)k ) + { + p += 4 * idx; + if ( p + 4 > limit ) + goto NoData; + + *aadvance = FT_NEXT_USHORT( p ); + *abearing = FT_NEXT_SHORT( p ); + } + else + { + p += 4 * ( k - 1 ); + if ( p + 4 > limit ) + goto NoData; + + *aadvance = FT_NEXT_USHORT( p ); + p += 2 + 2 * ( idx - k ); + if ( p + 2 > limit ) + *abearing = 0; + else + *abearing = FT_PEEK_SHORT( p ); + } + } + else + { + NoData: + *abearing = 0; + *aadvance = 0; + } + } + +#else /* !FT_OPTIMIZE_MEMORY */ + + static void + cff_face_get_vertical_metrics( TT_Face face, + FT_UInt idx, + FT_Short *abearing, + FT_UShort *aadvance ) + { + TT_VertHeader* header = &face->vertical; + TT_LongMetrics longs_m; + FT_UShort k = header->number_Of_VMetrics; + + + if ( k == 0 ) + { + *abearing = *aadvance = 0; + return; + } + + if ( idx < (FT_UInt)k ) + { + longs_m = (TT_LongMetrics)header->long_metrics + idx; + *abearing = longs_m->bearing; + *aadvance = longs_m->advance; + } + else + { + *abearing = ((TT_ShortMetrics*)header->short_metrics)[idx - k]; + *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance; + } + } + +#endif /* !FT_OPTIMIZE_MEMORY */ + + static FT_Error cff_get_glyph_data( TT_Face face, FT_UInt glyph_index, @@ -1299,7 +1410,7 @@ goto Fail; args = stack; - while (args < decoder->top ) + while ( args < decoder->top ) { if ( phase ) x += args[0]; @@ -1425,7 +1536,7 @@ goto Fail; args = stack; - if (num_args < 4 || ( num_args % 4 ) > 1 ) + if ( num_args < 4 || ( num_args % 4 ) > 1 ) goto Stack_Underflow; if ( check_points( builder, ( num_args / 4 ) * 3 ) ) @@ -1772,7 +1883,8 @@ /* close hints recording session */ if ( hinter ) { - if (hinter->close( hinter->hints, builder->current->n_points ) ) + if ( hinter->close( hinter->hints, + builder->current->n_points ) ) goto Syntax_Error; /* apply hints to the loaded glyph outline now */ @@ -2048,7 +2160,7 @@ case cff_op_ifelse: { - FT_Fixed cond = (args[2] <= args[3]); + FT_Fixed cond = ( args[2] <= args[3] ); FT_TRACE4(( " ifelse" )); @@ -2268,22 +2380,6 @@ #endif /* 0 */ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /********** *********/ - /********** *********/ - /********** UNHINTED GLYPH LOADER *********/ - /********** *********/ - /********** The following code is in charge of loading a *********/ - /********** single outline. It completely ignores hinting *********/ - /********** and is used when FT_LOAD_NO_HINTING is set. *********/ - /********** *********/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - FT_LOCAL_DEF( FT_Error ) cff_slot_load( CFF_GlyphSlot glyph, CFF_Size size, @@ -2515,8 +2611,26 @@ /* make up vertical ones */ metrics->vertAdvance = 0; + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + glyph->root.linearVertAdvance = 0; + /* get the vertical metrics from the vtmx table if we have one */ + if ( face->vertical_info && + face->vertical.number_Of_VMetrics > 0 && + face->vertical.long_metrics != 0 ) + { + FT_Short vertBearingY = 0; + FT_UShort vertAdvance = 0; + + + cff_face_get_vertical_metrics( face, glyph_index, + &vertBearingY, &vertAdvance ); + metrics->vertBearingY = vertBearingY; + metrics->vertAdvance = vertAdvance; + } + glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; glyph->root.outline.flags = 0; @@ -2536,6 +2650,7 @@ advance.y = 0; FT_Vector_Transform( &advance, &font_matrix ); metrics->horiAdvance = advance.x + font_offset.x; + advance.x = 0; advance.y = metrics->vertAdvance; FT_Vector_Transform( &advance, &font_matrix ); @@ -2560,8 +2675,8 @@ } /* Then scale the metrics */ - metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); - metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); } /* compute the other metrics */ @@ -2573,10 +2688,6 @@ metrics->horiBearingX = cbox.xMin; metrics->horiBearingY = cbox.yMax; - /* make up vertical ones */ - metrics->vertBearingX = 0; - metrics->vertBearingY = 0; - if ( hinting ) ft_glyphslot_grid_fit_metrics( &glyph->root ); }