diff options
author | Konstantin Ritt <ritt.ks@gmail.com> | 2015-03-19 17:34:42 +0400 |
---|---|---|
committer | Konstantin Ritt <ritt.ks@gmail.com> | 2015-03-20 13:42:29 +0000 |
commit | 2eaf0cf8fd6e7c290497fedb08134a89e7b49b1d (patch) | |
tree | 0a4f7bf528e87d0b0a71ce7fccf702b87f4cdec1 /src/3rdparty/freetype/src/cff/cffgload.c | |
parent | 77c518a50334d4dcf2476a4f39edc1e3990c7f0b (diff) |
Update bundled FreeType to 2.5.5
Removed everything, imported with help of import_from_tarball.sh script,
and then added a pre-generated builds/unix/ftconfig.h
Task-number: QTBUG-44648
Change-Id: Iea948e41f7761f1580382b3763d04c7a61383382
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/3rdparty/freetype/src/cff/cffgload.c')
-rw-r--r-- | src/3rdparty/freetype/src/cff/cffgload.c | 414 |
1 files changed, 271 insertions, 143 deletions
diff --git a/src/3rdparty/freetype/src/cff/cffgload.c b/src/3rdparty/freetype/src/cff/cffgload.c index 9330c05882..758a3d3bbd 100644 --- a/src/3rdparty/freetype/src/cff/cffgload.c +++ b/src/3rdparty/freetype/src/cff/cffgload.c @@ -4,8 +4,7 @@ /* */ /* OpenType Glyph Loader (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ -/* 2010 by */ +/* Copyright 1996-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,11 +21,12 @@ #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H #include FT_OUTLINE_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_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" @@ -41,6 +41,8 @@ #define FT_COMPONENT trace_cffgload +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + typedef enum CFF_Operator_ { cff_op_unknown = 0, @@ -211,6 +213,8 @@ 2 /* setcurrentpoint */ }; +#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ + /*************************************************************************/ /*************************************************************************/ @@ -394,7 +398,7 @@ /* initialize Type2 decoder */ decoder->cff = cff; - decoder->num_globals = cff->num_global_subrs; + decoder->num_globals = cff->global_subrs_index.count; decoder->globals = cff->global_subrs; decoder->globals_bias = cff_compute_bias( cff->top_font.font_dict.charstring_type, @@ -414,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 */ @@ -426,11 +430,11 @@ 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; } - FT_TRACE4(( "glyph index %d (subfont %d):\n", glyph_index, fd_index )); + FT_TRACE3(( " in subfont %d:\n", fd_index )); sub = cff->subfonts[fd_index]; @@ -443,12 +447,8 @@ builder->hints_globals = (void *)internal->subfonts[fd_index]; } } -#ifdef FT_DEBUG_LEVEL_TRACE - else - FT_TRACE4(( "glyph index %d:\n", glyph_index )); -#endif - decoder->num_locals = sub->num_local_subrs; + decoder->num_locals = sub->local_subrs_index.count; decoder->locals = sub->local_subrs; decoder->locals_bias = cff_compute_bias( decoder->cff->top_font.font_dict.charstring_type, @@ -457,22 +457,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, @@ -486,9 +488,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 ); } @@ -497,7 +512,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 ) @@ -505,7 +520,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 ); @@ -524,7 +539,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 ); @@ -542,12 +557,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 */ @@ -564,7 +579,7 @@ /* close the current contour */ - static void + FT_LOCAL_DEF( void ) cff_builder_close_contour( CFF_Builder* builder ) { FT_Outline* outline = builder->current; @@ -609,7 +624,7 @@ } - static FT_Int + FT_LOCAL_DEF( FT_Int ) cff_lookup_glyph_by_stdcharcode( CFF_Font cff, FT_Int charcode ) { @@ -638,7 +653,7 @@ } - static FT_Error + FT_LOCAL_DEF( FT_Error ) cff_get_glyph_data( TT_Face face, FT_UInt glyph_index, FT_Byte** pointer, @@ -674,7 +689,7 @@ } - static void + FT_LOCAL_DEF( void ) cff_free_glyph_data( TT_Face face, FT_Byte** pointer, FT_ULong length ) @@ -688,7 +703,7 @@ /* callback function. */ if ( face->root.internal->incremental_interface ) { - FT_Data data; + FT_Data data; data.pointer = *pointer; @@ -709,6 +724,8 @@ } +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + static FT_Error cff_operator_seac( CFF_Decoder* decoder, FT_Pos asb, @@ -730,7 +747,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; @@ -758,7 +775,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 */ @@ -812,10 +829,10 @@ charstring_len ); decoder->seac = FALSE; + cff_free_glyph_data( face, &charstring, charstring_len ); + if ( error ) goto Exit; - - cff_free_glyph_data( face, &charstring, charstring_len ); } /* Save the left bearing, advance and glyph width of the base */ @@ -842,10 +859,10 @@ charstring_len ); decoder->seac = FALSE; + cff_free_glyph_data( face, &charstring, charstring_len ); + if ( error ) goto Exit; - - cff_free_glyph_data( face, &charstring, charstring_len ); } /* Restore the left side bearing, advance and glyph width */ @@ -927,7 +944,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; @@ -955,11 +972,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 ) @@ -980,10 +1000,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; @@ -991,12 +1011,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 @@ -1160,8 +1180,8 @@ op = cff_op_flex1; break; default: - /* decrement ip for syntax error message */ - ip--; + FT_TRACE4(( " unknown op (12, %d)\n", v )); + break; } } break; @@ -1214,11 +1234,12 @@ op = cff_op_hvcurveto; break; default: + FT_TRACE4(( " unknown op (%d)\n", v )); break; } if ( op == cff_op_unknown ) - goto Syntax_Error; + continue; /* check arguments */ req_args = cff_argument_counts[op]; @@ -1340,6 +1361,14 @@ decoder->num_hints += num_args / 2; } + /* In a valid charstring there must be at least one byte */ + /* after `hintmask' or `cntrmask' (e.g., for a `return' */ + /* instruction). Additionally, there must be space for */ + /* `num_hints' bits. */ + + if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit ) + goto Syntax_Error; + if ( hinter ) { if ( op == cff_op_hintmask ) @@ -1358,20 +1387,18 @@ FT_UInt maskbyte; - FT_TRACE4(( " (maskbytes: " )); + FT_TRACE4(( " (maskbytes:" )); for ( maskbyte = 0; - maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3); + maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 ); maskbyte++, ip++ ) - FT_TRACE4(( "0x%02X", *ip )); + FT_TRACE4(( " 0x%02X", *ip )); FT_TRACE4(( ")\n" )); } #else ip += ( decoder->num_hints + 7 ) >> 3; #endif - if ( ip >= limit ) - goto Syntax_Error; args = stack; break; @@ -1406,8 +1433,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 ) @@ -1433,11 +1460,16 @@ FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n" : " vlineto\n" )); - if ( num_args < 1 ) + if ( num_args < 0 ) goto Stack_Underflow; - if ( cff_builder_start_point ( builder, x, y ) || - check_points( builder, num_args ) ) + /* there exist subsetted fonts (found in PDFs) */ + /* which call `hlineto' without arguments */ + if ( num_args == 0 ) + break; + + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, num_args ) ) goto Fail; args = stack; @@ -1470,8 +1502,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; @@ -1503,11 +1535,9 @@ goto Stack_Underflow; /* if num_args isn't of the form 4n or 4n+1, */ - /* we reduce it to 4n+1 */ + /* we enforce it by clearing the second bit */ - nargs = num_args - num_args % 4; - if ( num_args - nargs > 0 ) - nargs += 1; + nargs = num_args & ~2; if ( cff_builder_start_point( builder, x, y ) ) goto Fail; @@ -1521,7 +1551,7 @@ nargs--; } - if ( check_points( builder, 3 * ( nargs / 4 ) ) ) + if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) goto Fail; while ( args < decoder->top ) @@ -1550,11 +1580,9 @@ goto Stack_Underflow; /* if num_args isn't of the form 4n or 4n+1, */ - /* we reduce it to 4n+1 */ + /* we enforce it by clearing the second bit */ - nargs = num_args - num_args % 4; - if ( num_args - nargs > 0 ) - nargs += 1; + nargs = num_args & ~2; if ( cff_builder_start_point( builder, x, y ) ) goto Fail; @@ -1567,7 +1595,7 @@ nargs--; } - if ( check_points( builder, 3 * ( nargs / 4 ) ) ) + if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) goto Fail; while ( args < decoder->top ) @@ -1602,14 +1630,12 @@ goto Stack_Underflow; /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */ - /* we reduce it to the largest one which fits */ + /* we enforce it by clearing the second bit */ - nargs = num_args - num_args % 4; - if ( num_args - nargs > 0 ) - nargs += 1; + 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 ); @@ -1662,8 +1688,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; @@ -1707,8 +1733,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; @@ -1748,7 +1774,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 */ @@ -1797,7 +1823,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 */ @@ -1850,7 +1876,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 */ @@ -1913,7 +1939,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-- ) @@ -1953,6 +1979,7 @@ /* Save glyph width so that the subglyphs don't overwrite it. */ FT_Pos glyph_width = decoder->glyph_width; + error = cff_operator_seac( decoder, 0L, args[-4], args[-3], (FT_Int)( args[-2] >> 16 ), @@ -1962,9 +1989,6 @@ } else { - if ( !error ) - error = CFF_Err_Ok; - cff_builder_close_contour( builder ); /* close hints recording session */ @@ -1975,10 +1999,12 @@ goto Syntax_Error; /* apply hints to the loaded glyph outline now */ - hinter->apply( hinter->hints, - builder->current, - (PSH_Globals)builder->hints_globals, - decoder->hint_mode ); + error = hinter->apply( hinter->hints, + builder->current, + (PSH_Globals)builder->hints_globals, + decoder->hint_mode ); + if ( error ) + goto Fail; } /* add current outline to the glyph slot */ @@ -2275,7 +2301,11 @@ /* subsequent `pop' operands should add the arguments, */ /* this is the implementation described for `unknown' other */ /* subroutines in the Type1 spec. */ + /* */ + /* XXX Fix return arguments (see discussion below). */ args -= 2 + ( args[-2] >> 16 ); + if ( args < stack ) + goto Stack_Underflow; break; case cff_op_pop: @@ -2285,6 +2315,22 @@ FT_TRACE4(( " pop (invalid op)\n" )); + /* XXX Increasing `args' is wrong: After a certain number of */ + /* `pop's we get a stack overflow. Reason for doing it is */ + /* code like this (actually found in a CFF font): */ + /* */ + /* 17 1 3 callothersubr */ + /* pop */ + /* callsubr */ + /* */ + /* Since we handle `callothersubr' as a no-op, and */ + /* `callsubr' needs at least one argument, `pop' can't be a */ + /* no-op too as it basically should be. */ + /* */ + /* The right solution would be to provide real support for */ + /* `callothersubr' as done in `t1decode.c', however, given */ + /* the fact that CFF fonts with `pop' are invalid, it is */ + /* questionable whether it is worth the time. */ args++; break; @@ -2445,10 +2491,13 @@ FT_ERROR(( " %d", ip[0] )); FT_ERROR(( "\n" )); - return CFF_Err_Unimplemented_Feature; + return FT_THROW( Unimplemented_Feature ); } - decoder->top = args; + decoder->top = args; + + if ( decoder->top - stack >= CFF_MAX_OPERANDS ) + goto Stack_Overflow; } /* general operator processing */ @@ -2461,17 +2510,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 */ + /*************************************************************************/ /*************************************************************************/ @@ -2498,7 +2549,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; @@ -2536,12 +2587,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; } @@ -2557,7 +2608,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; @@ -2578,11 +2629,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; @@ -2625,6 +2676,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; @@ -2651,6 +2707,39 @@ glyph->root.bitmap_left = metrics.horiBearingX; glyph->root.bitmap_top = metrics.horiBearingY; } + + /* compute linear advance widths */ + + (void)( (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 ) + { + (void)( (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; } } @@ -2660,7 +2749,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) */ @@ -2668,11 +2757,16 @@ /* this scaling is only relevant if the PS hinter isn't active */ if ( cff->num_subfonts ) { - FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, - glyph_index ); + FT_ULong top_upm, sub_upm; + FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, + glyph_index ); - FT_ULong top_upm = cff->top_font.font_dict.units_per_em; - FT_ULong sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em; + + if ( fd_index >= cff->num_subfonts ) + fd_index = (FT_Byte)( cff->num_subfonts - 1 ); + + top_upm = cff->top_font.font_dict.units_per_em; + sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em; font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; @@ -2695,12 +2789,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; @@ -2717,48 +2820,79 @@ /* now load the unscaled outline */ error = cff_get_glyph_data( face, glyph_index, &charstring, &charstring_len ); - if ( !error ) + if ( error ) + goto Glyph_Build_Finished; + + error = cff_decoder_prepare( &decoder, size, glyph_index ); + if ( error ) + goto Glyph_Build_Finished; + +#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 = cff_decoder_prepare( &decoder, size, glyph_index ); - if ( !error ) + 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 ) ) { - error = cff_decoder_parse_charstrings( &decoder, + /* this time, we retry unhinted and scale up the glyph later on */ + /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ + /* 0x400 for both `x_scale' and `y_scale' in this case) */ + hinting = FALSE; + force_scaling = TRUE; + glyph->hint = hinting; + + error = cf2_decoder_parse_charstrings( &decoder, charstring, charstring_len ); + } + } - cff_free_glyph_data( face, &charstring, charstring_len ); + cff_free_glyph_data( face, &charstring, charstring_len ); + if ( error ) + goto Glyph_Build_Finished; #ifdef FT_CONFIG_OPTION_INCREMENTAL - /* Control data and length may not be available for incremental */ - /* fonts. */ - if ( face->root.internal->incremental_interface ) - { - glyph->root.control_data = 0; - glyph->root.control_len = 0; - } - else + /* Control data and length may not be available for incremental */ + /* fonts. */ + if ( face->root.internal->incremental_interface ) + { + glyph->root.control_data = 0; + glyph->root.control_len = 0; + } + else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - /* We set control_data and control_len if charstrings is loaded. */ - /* See how charstring loads at cff_index_access_element() in */ - /* cffload.c. */ - { - CFF_Index csindex = &cff->charstrings_index; + /* We set control_data and control_len if charstrings is loaded. */ + /* See how charstring loads at cff_index_access_element() in */ + /* cffload.c. */ + { + CFF_Index csindex = &cff->charstrings_index; - if ( csindex->offsets ) - { - glyph->root.control_data = csindex->bytes + - csindex->offsets[glyph_index] - 1; - glyph->root.control_len = charstring_len; - } - } + if ( csindex->offsets ) + { + glyph->root.control_data = csindex->bytes + + csindex->offsets[glyph_index] - 1; + glyph->root.control_len = charstring_len; } } - /* save new glyph tables */ - cff_builder_done( &decoder.builder ); + Glyph_Build_Finished: + /* save new glyph tables, if no error */ + if ( !error ) + cff_builder_done( &decoder.builder ); + /* XXX: anything to do for broken glyph entry? */ } #ifdef FT_CONFIG_OPTION_INCREMENTAL @@ -2819,14 +2953,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 ) @@ -2835,10 +2963,10 @@ FT_UShort vertAdvance = 0; - ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, - glyph_index, - &vertBearingY, - &vertAdvance ); + (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1, + glyph_index, + &vertBearingY, + &vertAdvance ); metrics->vertBearingY = vertBearingY; metrics->vertAdvance = vertAdvance; } @@ -2919,7 +3047,7 @@ if ( has_vertical_info ) metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2; - else + else { if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) ft_synthesize_vertical_metrics( metrics, |