Index: src/cff/cffgload.c |
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c |
index 84847fda57029861ac9e135af87f394f776bf469..1904ca019a6945875110ffa35d584de67c49c69d 100644 |
--- a/src/cff/cffgload.c |
+++ b/src/cff/cffgload.c |
@@ -4,7 +4,7 @@ |
/* */ |
/* OpenType Glyph Loader (body). */ |
/* */ |
-/* Copyright 1996-2012 by */ |
+/* Copyright 1996-2013 by */ |
/* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
/* */ |
/* This file is part of the FreeType project, and may only be used, */ |
@@ -21,10 +21,12 @@ |
#include FT_INTERNAL_STREAM_H |
#include FT_INTERNAL_SFNT_H |
#include FT_OUTLINE_H |
+#include FT_CFF_DRIVER_H |
#include "cffobjs.h" |
#include "cffload.h" |
#include "cffgload.h" |
+#include "cf2ft.h" /* for cf2_decoder_parse_charstrings */ |
#include "cfferrs.h" |
@@ -39,6 +41,8 @@ |
#define FT_COMPONENT trace_cffgload |
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE |
+ |
typedef enum CFF_Operator_ |
{ |
cff_op_unknown = 0, |
@@ -209,6 +213,8 @@ |
2 /* setcurrentpoint */ |
}; |
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ |
+ |
/*************************************************************************/ |
/*************************************************************************/ |
@@ -412,7 +418,7 @@ |
CFF_Builder *builder = &decoder->builder; |
CFF_Font cff = (CFF_Font)builder->face->extra.data; |
CFF_SubFont sub = &cff->top_font; |
- FT_Error error = CFF_Err_Ok; |
+ FT_Error error = FT_Err_Ok; |
/* manage CID fonts */ |
@@ -424,7 +430,7 @@ |
if ( fd_index >= cff->num_subfonts ) |
{ |
FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" )); |
- error = CFF_Err_Invalid_File_Format; |
+ error = FT_THROW( Invalid_File_Format ); |
goto Exit; |
} |
@@ -455,22 +461,24 @@ |
decoder->glyph_width = sub->private_dict.default_width; |
decoder->nominal_width = sub->private_dict.nominal_width; |
+ decoder->current_subfont = sub; /* for Adobe's CFF handler */ |
+ |
Exit: |
return error; |
} |
/* check that there is enough space for `count' more points */ |
- static FT_Error |
- check_points( CFF_Builder* builder, |
- FT_Int count ) |
+ FT_LOCAL_DEF( FT_Error ) |
+ cff_check_points( CFF_Builder* builder, |
+ FT_Int count ) |
{ |
return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); |
} |
/* add a new point, do not check space */ |
- static void |
+ FT_LOCAL_DEF( void ) |
cff_builder_add_point( CFF_Builder* builder, |
FT_Pos x, |
FT_Pos y, |
@@ -484,9 +492,22 @@ |
FT_Vector* point = outline->points + outline->n_points; |
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; |
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE |
+ CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); |
+ |
- point->x = x >> 16; |
- point->y = y >> 16; |
+ if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) |
+ { |
+ point->x = x >> 16; |
+ point->y = y >> 16; |
+ } |
+ else |
+#endif |
+ { |
+ /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ |
+ point->x = x >> 10; |
+ point->y = y >> 10; |
+ } |
*control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); |
} |
@@ -495,7 +516,7 @@ |
/* check space for a new on-curve point, then add it */ |
- static FT_Error |
+ FT_LOCAL_DEF( FT_Error ) |
cff_builder_add_point1( CFF_Builder* builder, |
FT_Pos x, |
FT_Pos y ) |
@@ -503,7 +524,7 @@ |
FT_Error error; |
- error = check_points( builder, 1 ); |
+ error = cff_check_points( builder, 1 ); |
if ( !error ) |
cff_builder_add_point( builder, x, y, 1 ); |
@@ -522,7 +543,7 @@ |
if ( !builder->load_points ) |
{ |
outline->n_contours++; |
- return CFF_Err_Ok; |
+ return FT_Err_Ok; |
} |
error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); |
@@ -540,12 +561,12 @@ |
/* if a path was begun, add its first on-curve point */ |
- static FT_Error |
+ FT_LOCAL_DEF( FT_Error ) |
cff_builder_start_point( CFF_Builder* builder, |
FT_Pos x, |
FT_Pos y ) |
{ |
- FT_Error error = CFF_Err_Ok; |
+ FT_Error error = FT_Err_Ok; |
/* test whether we are building a new contour */ |
@@ -562,7 +583,7 @@ |
/* close the current contour */ |
- static void |
+ FT_LOCAL_DEF( void ) |
cff_builder_close_contour( CFF_Builder* builder ) |
{ |
FT_Outline* outline = builder->current; |
@@ -607,7 +628,7 @@ |
} |
- static FT_Int |
+ FT_LOCAL_DEF( FT_Int ) |
cff_lookup_glyph_by_stdcharcode( CFF_Font cff, |
FT_Int charcode ) |
{ |
@@ -636,7 +657,7 @@ |
} |
- static FT_Error |
+ FT_LOCAL_DEF( FT_Error ) |
cff_get_glyph_data( TT_Face face, |
FT_UInt glyph_index, |
FT_Byte** pointer, |
@@ -672,7 +693,7 @@ |
} |
- static void |
+ FT_LOCAL_DEF( void ) |
cff_free_glyph_data( TT_Face face, |
FT_Byte** pointer, |
FT_ULong length ) |
@@ -707,6 +728,8 @@ |
} |
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE |
+ |
static FT_Error |
cff_operator_seac( CFF_Decoder* decoder, |
FT_Pos asb, |
@@ -728,7 +751,7 @@ |
if ( decoder->seac ) |
{ |
FT_ERROR(( "cff_operator_seac: invalid nested seac\n" )); |
- return CFF_Err_Syntax_Error; |
+ return FT_THROW( Syntax_Error ); |
} |
adx += decoder->builder.left_bearing.x; |
@@ -756,7 +779,7 @@ |
{ |
FT_ERROR(( "cff_operator_seac:" |
" invalid seac character code arguments\n" )); |
- return CFF_Err_Syntax_Error; |
+ return FT_THROW( Syntax_Error ); |
} |
/* If we are trying to load a composite glyph, do not load the */ |
@@ -925,7 +948,7 @@ |
limit = zone->limit = charstring_base + charstring_len; |
ip = zone->cursor = zone->base; |
- error = CFF_Err_Ok; |
+ error = FT_Err_Ok; |
x = builder->pos_x; |
y = builder->pos_y; |
@@ -953,11 +976,14 @@ |
/* this is an operand, push it on the stack */ |
+ |
+ /* if we use shifts, all computations are done with unsigned */ |
+ /* values; the conversion to a signed value is the last step */ |
if ( v == 28 ) |
{ |
if ( ip + 1 >= limit ) |
goto Syntax_Error; |
- val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] ); |
+ val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] ); |
ip += 2; |
} |
else if ( v < 247 ) |
@@ -978,10 +1004,10 @@ |
{ |
if ( ip + 3 >= limit ) |
goto Syntax_Error; |
- val = ( (FT_Int32)ip[0] << 24 ) | |
- ( (FT_Int32)ip[1] << 16 ) | |
- ( (FT_Int32)ip[2] << 8 ) | |
- ip[3]; |
+ val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | |
+ ( (FT_UInt32)ip[1] << 16 ) | |
+ ( (FT_UInt32)ip[2] << 8 ) | |
+ (FT_UInt32)ip[3] ); |
ip += 4; |
if ( charstring_type == 2 ) |
shift = 0; |
@@ -989,12 +1015,12 @@ |
if ( decoder->top - stack >= CFF_MAX_OPERANDS ) |
goto Stack_Overflow; |
- val <<= shift; |
+ val = (FT_Int32)( (FT_UInt32)val << shift ); |
*decoder->top++ = val; |
#ifdef FT_DEBUG_LEVEL_TRACE |
if ( !( val & 0xFFFFL ) ) |
- FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) )); |
+ FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) )); |
else |
FT_TRACE4(( " %.2f", val / 65536.0 )); |
#endif |
@@ -1411,8 +1437,8 @@ |
case cff_op_rlineto: |
FT_TRACE4(( " rlineto\n" )); |
- if ( cff_builder_start_point ( builder, x, y ) || |
- check_points( builder, num_args / 2 ) ) |
+ if ( cff_builder_start_point( builder, x, y ) || |
+ cff_check_points( builder, num_args / 2 ) ) |
goto Fail; |
if ( num_args < 2 ) |
@@ -1446,8 +1472,8 @@ |
if ( num_args == 0 ) |
break; |
- if ( cff_builder_start_point ( builder, x, y ) || |
- check_points( builder, num_args ) ) |
+ if ( cff_builder_start_point( builder, x, y ) || |
+ cff_check_points( builder, num_args ) ) |
goto Fail; |
args = stack; |
@@ -1480,8 +1506,8 @@ |
nargs = num_args - num_args % 6; |
- if ( cff_builder_start_point ( builder, x, y ) || |
- check_points( builder, nargs / 2 ) ) |
+ if ( cff_builder_start_point( builder, x, y ) || |
+ cff_check_points( builder, nargs / 2 ) ) |
goto Fail; |
args -= nargs; |
@@ -1529,7 +1555,7 @@ |
nargs--; |
} |
- if ( check_points( builder, 3 * ( nargs / 4 ) ) ) |
+ if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) |
goto Fail; |
while ( args < decoder->top ) |
@@ -1573,7 +1599,7 @@ |
nargs--; |
} |
- if ( check_points( builder, 3 * ( nargs / 4 ) ) ) |
+ if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) |
goto Fail; |
while ( args < decoder->top ) |
@@ -1613,7 +1639,7 @@ |
nargs = num_args & ~2; |
args -= nargs; |
- if ( check_points( builder, ( nargs / 4 ) * 3 ) ) |
+ if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) ) |
goto Stack_Underflow; |
phase = ( op == cff_op_hvcurveto ); |
@@ -1666,8 +1692,8 @@ |
nargs = num_args & ~1; |
num_lines = ( nargs - 6 ) / 2; |
- if ( cff_builder_start_point( builder, x, y ) || |
- check_points( builder, num_lines + 3 ) ) |
+ if ( cff_builder_start_point( builder, x, y ) || |
+ cff_check_points( builder, num_lines + 3 ) ) |
goto Fail; |
args -= nargs; |
@@ -1711,8 +1737,8 @@ |
nargs = nargs - nargs % 6 + 2; |
num_curves = ( nargs - 2 ) / 6; |
- if ( cff_builder_start_point ( builder, x, y ) || |
- check_points( builder, num_curves * 3 + 2 ) ) |
+ if ( cff_builder_start_point( builder, x, y ) || |
+ cff_check_points( builder, num_curves * 3 + 2 ) ) |
goto Fail; |
args -= nargs; |
@@ -1752,7 +1778,7 @@ |
/* -- make sure we have enough space for the start point if it */ |
/* needs to be added */ |
if ( cff_builder_start_point( builder, x, y ) || |
- check_points( builder, 6 ) ) |
+ cff_check_points( builder, 6 ) ) |
goto Fail; |
/* record the starting point's y position for later use */ |
@@ -1801,7 +1827,7 @@ |
/* adding six more points; 4 control points, 2 on-curve points */ |
if ( cff_builder_start_point( builder, x, y ) || |
- check_points( builder, 6 ) ) |
+ cff_check_points( builder, 6 ) ) |
goto Fail; |
/* record the starting point's y-position for later use */ |
@@ -1854,7 +1880,7 @@ |
/* adding six more points; 4 control points, 2 on-curve points */ |
if ( cff_builder_start_point( builder, x, y ) || |
- check_points( builder, 6 ) ) |
+ cff_check_points( builder, 6 ) ) |
goto Fail; |
/* record the starting point's x, y position for later use */ |
@@ -1917,7 +1943,7 @@ |
FT_TRACE4(( " flex\n" )); |
if ( cff_builder_start_point( builder, x, y ) || |
- check_points( builder, 6 ) ) |
+ cff_check_points( builder, 6 ) ) |
goto Fail; |
for ( count = 6; count > 0; count-- ) |
@@ -1968,7 +1994,7 @@ |
else |
{ |
if ( !error ) |
- error = CFF_Err_Ok; |
+ error = FT_Err_Ok; |
cff_builder_close_contour( builder ); |
@@ -2470,7 +2496,7 @@ |
FT_ERROR(( " %d", ip[0] )); |
FT_ERROR(( "\n" )); |
- return CFF_Err_Unimplemented_Feature; |
+ return FT_THROW( Unimplemented_Feature ); |
} |
decoder->top = args; |
@@ -2489,17 +2515,19 @@ |
Syntax_Error: |
FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" )); |
- return CFF_Err_Invalid_File_Format; |
+ return FT_THROW( Invalid_File_Format ); |
Stack_Underflow: |
FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" )); |
- return CFF_Err_Too_Few_Arguments; |
+ return FT_THROW( Too_Few_Arguments ); |
Stack_Overflow: |
FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" )); |
- return CFF_Err_Stack_Overflow; |
+ return FT_THROW( Stack_Overflow ); |
} |
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ |
+ |
/*************************************************************************/ |
/*************************************************************************/ |
@@ -2526,7 +2554,7 @@ |
cff_compute_max_advance( TT_Face face, |
FT_Int* max_advance ) |
{ |
- FT_Error error = CFF_Err_Ok; |
+ FT_Error error = FT_Err_Ok; |
CFF_Decoder decoder; |
FT_Int glyph_index; |
CFF_Font cff = (CFF_Font)face->other; |
@@ -2564,12 +2592,12 @@ |
} |
/* ignore the error if one has occurred -- skip to next glyph */ |
- error = CFF_Err_Ok; |
+ error = FT_Err_Ok; |
} |
*max_advance = decoder.builder.advance.x; |
- return CFF_Err_Ok; |
+ return FT_Err_Ok; |
} |
@@ -2585,7 +2613,7 @@ |
FT_Error error; |
CFF_Decoder decoder; |
TT_Face face = (TT_Face)glyph->root.face; |
- FT_Bool hinting, force_scaling; |
+ FT_Bool hinting, scaled, force_scaling; |
CFF_Font cff = (CFF_Font)face->extra.data; |
FT_Matrix font_matrix; |
@@ -2606,11 +2634,11 @@ |
glyph_index = cff_charset_cid_to_gindex( &cff->charset, |
glyph_index ); |
if ( glyph_index == 0 ) |
- return CFF_Err_Invalid_Argument; |
+ return FT_THROW( Invalid_Argument ); |
} |
} |
else if ( glyph_index >= cff->num_glyphs ) |
- return CFF_Err_Invalid_Argument; |
+ return FT_THROW( Invalid_Argument ); |
if ( load_flags & FT_LOAD_NO_RECURSE ) |
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; |
@@ -2653,6 +2681,11 @@ |
if ( !error ) |
{ |
+ FT_Bool has_vertical_info; |
+ FT_UShort advance; |
+ FT_Short dummy; |
+ |
+ |
glyph->root.outline.n_points = 0; |
glyph->root.outline.n_contours = 0; |
@@ -2679,6 +2712,39 @@ |
glyph->root.bitmap_left = metrics.horiBearingX; |
glyph->root.bitmap_top = metrics.horiBearingY; |
} |
+ |
+ /* compute linear advance widths */ |
+ |
+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, |
+ glyph_index, |
+ &dummy, |
+ &advance ); |
+ glyph->root.linearHoriAdvance = advance; |
+ |
+ 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 */ |
+ if ( has_vertical_info ) |
+ { |
+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, |
+ glyph_index, |
+ &dummy, |
+ &advance ); |
+ glyph->root.linearVertAdvance = advance; |
+ } |
+ else |
+ { |
+ /* make up vertical ones */ |
+ if ( face->os2.version != 0xFFFFU ) |
+ glyph->root.linearVertAdvance = (FT_Pos) |
+ ( face->os2.sTypoAscender - face->os2.sTypoDescender ); |
+ else |
+ glyph->root.linearVertAdvance = (FT_Pos) |
+ ( face->horizontal.Ascender - face->horizontal.Descender ); |
+ } |
+ |
return error; |
} |
} |
@@ -2688,7 +2754,7 @@ |
/* return immediately if we only want the embedded bitmaps */ |
if ( load_flags & FT_LOAD_SBITS_ONLY ) |
- return CFF_Err_Invalid_Argument; |
+ return FT_THROW( Invalid_Argument ); |
/* if we have a CID subfont, use its matrix (which has already */ |
/* been multiplied with the root matrix) */ |
@@ -2700,6 +2766,7 @@ |
FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, |
glyph_index ); |
+ |
if ( fd_index >= cff->num_subfonts ) |
fd_index = (FT_Byte)( cff->num_subfonts - 1 ); |
@@ -2727,12 +2794,21 @@ |
glyph->root.outline.n_points = 0; |
glyph->root.outline.n_contours = 0; |
- hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && |
- ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); |
+ /* top-level code ensures that FT_LOAD_NO_HINTING is set */ |
+ /* if FT_LOAD_NO_SCALE is active */ |
+ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); |
+ scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); |
+ glyph->hint = hinting; |
+ glyph->scaled = scaled; |
glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ |
{ |
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE |
+ CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face ); |
+#endif |
+ |
+ |
FT_Byte* charstring; |
FT_ULong charstring_len; |
@@ -2756,9 +2832,26 @@ |
if ( error ) |
goto Glyph_Build_Finished; |
- error = cff_decoder_parse_charstrings( &decoder, |
- charstring, |
- charstring_len ); |
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE |
+ /* choose which CFF renderer to use */ |
+ if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) |
+ error = cff_decoder_parse_charstrings( &decoder, |
+ charstring, |
+ charstring_len ); |
+ else |
+#endif |
+ { |
+ error = cf2_decoder_parse_charstrings( &decoder, |
+ charstring, |
+ charstring_len ); |
+ |
+ /* Adobe's engine uses 16.16 numbers everywhere; */ |
+ /* as a consequence, glyphs larger than 2000ppem get rejected */ |
+ if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) |
+ { |
+ /* XXX to be implemented */ |
+ } |
+ } |
cff_free_glyph_data( face, &charstring, charstring_len ); |
@@ -2856,14 +2949,8 @@ |
glyph->root.linearHoriAdvance = decoder.glyph_width; |
glyph->root.internal->glyph_transformed = 0; |
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS |
- has_vertical_info = FT_BOOL( face->vertical_info && |
- face->vertical.number_Of_VMetrics > 0 && |
- face->vertical.long_metrics ); |
-#else |
has_vertical_info = FT_BOOL( face->vertical_info && |
face->vertical.number_Of_VMetrics > 0 ); |
-#endif |
/* get the vertical metrics from the vtmx table if we have one */ |
if ( has_vertical_info ) |