Add vertical metrics support to OpenType CFF outlines. Based on a
patch from Mike Moening <MikeM@RetekSolutions.com>
* src/cff/cffgload.c (cff_face_get_vertical_metrics): New function.
(cff_slot_load): Use cff_face_get_vertical_metrics.
* docs/CHANGES: Updated.
diff --git a/ChangeLog b/ChangeLog
index b8186c5..c6ae94e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,17 +1,29 @@
+2005-11-17 Werner Lemberg <wl@gnu.org>
+
+ Add vertical metrics support to OpenType CFF outlines. Based on a
+ patch from Mike Moening <MikeM@RetekSolutions.com>
+
+ * 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 <b90201047@ntu.edu.tw>
* 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 <david@freetype.org>
diff --git a/docs/CHANGES b/docs/CHANGES
index 0a9f352..6295ec2 100644
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -6,6 +6,9 @@
- 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 f4e7753..d4ea07b 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -569,6 +569,117 @@
}
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cff_face_get_vertical_metrics */
+ /* */
+ /* <Description> */
+ /* Return the vertical metrics in font units for a given glyph. The */
+ /* metrics are the top side bearing and advance height. */
+ /* */
+ /* <Input> */
+ /* header :: A pointer to the vertical metrics structure. */
+ /* */
+ /* idx :: The glyph index. */
+ /* */
+ /* <Output> */
+ /* bearing :: The top side bearing. */
+ /* */
+ /* advance :: The advance height. */
+ /* */
+ /* <Note> */
+ /* 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 );
}