diff options
Diffstat (limited to 'src/3rdparty/freetype/src/cff/cffload.c')
-rw-r--r-- | src/3rdparty/freetype/src/cff/cffload.c | 341 |
1 files changed, 203 insertions, 138 deletions
diff --git a/src/3rdparty/freetype/src/cff/cffload.c b/src/3rdparty/freetype/src/cff/cffload.c index 64d1395723..d9bec5966b 100644 --- a/src/3rdparty/freetype/src/cff/cffload.c +++ b/src/3rdparty/freetype/src/cff/cffload.c @@ -4,7 +4,7 @@ /* */ /* OpenType and CFF data/program tables loader (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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, */ @@ -20,7 +20,6 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_STREAM_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H #include FT_TRUETYPE_TAGS_H #include FT_TYPE1_TABLES_H @@ -251,7 +250,7 @@ if ( offsize < 1 || offsize > 4 ) { - error = FT_Err_Invalid_Table; + error = FT_THROW( Invalid_Table ); goto Exit; } @@ -270,7 +269,7 @@ if ( size == 0 ) { - error = CFF_Err_Invalid_Table; + error = FT_THROW( Invalid_Table ); goto Exit; } @@ -319,7 +318,7 @@ static FT_Error cff_index_load_offsets( CFF_Index idx ) { - FT_Error error = CFF_Err_Ok; + FT_Error error = FT_Err_Ok; FT_Stream stream = idx->stream; FT_Memory memory = stream->memory; @@ -377,18 +376,22 @@ } - /* allocate a table containing pointers to an index's elements */ + /* Allocate a table containing pointers to an index's elements. */ + /* The `pool' argument makes this function convert the index */ + /* entries to C-style strings (this is, NULL-terminated). */ static FT_Error cff_index_get_pointers( CFF_Index idx, - FT_Byte*** table ) + FT_Byte*** table, + FT_Byte** pool ) { - FT_Error error = CFF_Err_Ok; - FT_Memory memory = idx->stream->memory; - FT_ULong n, offset, old_offset; - FT_Byte** t; + FT_Error error = FT_Err_Ok; + FT_Memory memory = idx->stream->memory; + FT_Byte** t = NULL; + FT_Byte* new_bytes = NULL; - *table = 0; + + *table = NULL; if ( idx->offsets == NULL ) { @@ -397,28 +400,65 @@ goto Exit; } - if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) ) + if ( idx->count > 0 && + !FT_NEW_ARRAY( t, idx->count + 1 ) && + ( !pool || !FT_ALLOC( new_bytes, + idx->data_size + idx->count ) ) ) { - old_offset = 1; - for ( n = 0; n <= idx->count; n++ ) + FT_ULong n, cur_offset; + FT_ULong extra = 0; + FT_Byte* org_bytes = idx->bytes; + + + /* at this point, `idx->offsets' can't be NULL */ + cur_offset = idx->offsets[0] - 1; + + /* sanity check */ + if ( cur_offset != 0 ) + { + FT_TRACE0(( "cff_index_get_pointers:" + " invalid first offset value %d set to zero\n", + cur_offset )); + cur_offset = 0; + } + + if ( !pool ) + t[0] = org_bytes + cur_offset; + else + t[0] = new_bytes + cur_offset; + + for ( n = 1; n <= idx->count; n++ ) { - /* at this point, `idx->offsets' can't be NULL */ - offset = idx->offsets[n]; - if ( !offset ) - offset = old_offset; + FT_ULong next_offset = idx->offsets[n] - 1; + /* two sanity checks for invalid offset tables */ - else if ( offset < old_offset ) - offset = old_offset; + if ( next_offset < cur_offset ) + next_offset = cur_offset; + else if ( next_offset > idx->data_size ) + next_offset = idx->data_size; - else if ( offset - 1 >= idx->data_size && n < idx->count ) - offset = old_offset; + if ( !pool ) + t[n] = org_bytes + next_offset; + else + { + t[n] = new_bytes + next_offset + extra; - t[n] = idx->bytes + offset - 1; + if ( next_offset != cur_offset ) + { + FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] ); + t[n][0] = '\0'; + t[n] += 1; + extra++; + } + } - old_offset = offset; + cur_offset = next_offset; } *table = t; + + if ( pool ) + *pool = new_bytes; } Exit: @@ -432,7 +472,7 @@ FT_Byte** pbytes, FT_ULong* pbyte_len ) { - FT_Error error = CFF_Err_Ok; + FT_Error error = FT_Err_Ok; if ( idx && idx->count > element ) @@ -479,6 +519,18 @@ } } + /* XXX: should check off2 does not exceed the end of this entry; */ + /* at present, only truncate off2 at the end of this stream */ + if ( off2 > stream->size + 1 || + idx->data_offset > stream->size - off2 + 1 ) + { + FT_ERROR(( "cff_index_access_element:" + " offset to next entry (%d)" + " exceeds the end of stream (%d)\n", + off2, stream->size - idx->data_offset + 1 )); + off2 = stream->size - idx->data_offset + 1; + } + /* access element */ if ( off1 && off2 > off1 ) { @@ -505,7 +557,7 @@ } } else - error = CFF_Err_Invalid_Argument; + error = FT_THROW( Invalid_Argument ); Exit: return error; @@ -526,10 +578,12 @@ } + /* get an entry from Name INDEX */ FT_LOCAL_DEF( FT_String* ) - cff_index_get_name( CFF_Index idx, - FT_UInt element ) + cff_index_get_name( CFF_Font font, + FT_UInt element ) { + CFF_Index idx = &font->name_index; FT_Memory memory = idx->stream->memory; FT_Byte* bytes; FT_ULong byte_len; @@ -553,42 +607,35 @@ } + /* get an entry from String INDEX */ FT_LOCAL_DEF( FT_String* ) - cff_index_get_sid_string( CFF_Index idx, - FT_UInt sid, - FT_Service_PsCMaps psnames ) + cff_index_get_string( CFF_Font font, + FT_UInt element ) + { + return ( element < font->num_strings ) + ? (FT_String*)font->strings[element] + : NULL; + } + + + FT_LOCAL_DEF( FT_String* ) + cff_index_get_sid_string( CFF_Font font, + FT_UInt sid ) { /* value 0xFFFFU indicates a missing dictionary entry */ if ( sid == 0xFFFFU ) - return 0; + return NULL; /* if it is not a standard string, return it */ if ( sid > 390 ) - return cff_index_get_name( idx, sid - 391 ); + return cff_index_get_string( font, sid - 391 ); /* CID-keyed CFF fonts don't have glyph names */ - if ( !psnames ) - return 0; - - /* that's a standard string, fetch a copy from the PSName module */ - { - FT_String* name = 0; - const char* adobe_name = psnames->adobe_std_strings( sid ); - - - if ( adobe_name ) - { - FT_Memory memory = idx->stream->memory; - FT_Error error; + if ( !font->psnames ) + return NULL; - - (void)FT_STRDUP( name, adobe_name ); - - FT_UNUSED( error ); - } - - return name; - } + /* this is a standard string */ + return (FT_String *)font->psnames->adobe_std_strings( sid ); } @@ -642,6 +689,13 @@ if ( FT_READ_USHORT( num_ranges ) ) goto Exit; + if ( !num_ranges ) + { + FT_TRACE0(( "CFF_Load_FD_Select: empty FDSelect array\n" )); + error = FT_THROW( Invalid_File_Format ); + goto Exit; + } + fdselect->data_size = num_ranges * 3 + 2; Load_Data: @@ -650,7 +704,7 @@ break; default: /* hmm... that's wrong */ - error = CFF_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); } Exit: @@ -672,7 +726,7 @@ break; case 3: - /* first, compare to cache */ + /* first, compare to the cache */ if ( (FT_UInt)( glyph_index - fdselect->cache_first ) < fdselect->cache_count ) { @@ -680,7 +734,7 @@ break; } - /* then, lookup the ranges array */ + /* then, look up the ranges array */ { FT_Byte* p = fdselect->data; FT_Byte* p_limit = p + fdselect->data_size; @@ -703,7 +757,7 @@ /* update cache */ fdselect->cache_first = first; - fdselect->cache_count = limit-first; + fdselect->cache_count = limit - first; fdselect->cache_fd = fd2; break; } @@ -744,11 +798,12 @@ goto Exit; for ( i = 0; i < num_glyphs; i++ ) + { if ( charset->sids[i] > max_cid ) max_cid = charset->sids[i]; - max_cid++; + } - if ( FT_NEW_ARRAY( charset->cids, max_cid ) ) + if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) ) goto Exit; /* When multiple GIDs map to the same CID, we choose the lowest */ @@ -772,7 +827,7 @@ FT_UInt result = 0; - if ( cid < charset->max_cid ) + if ( cid <= charset->max_cid ) result = charset->cids[cid]; return result; @@ -812,7 +867,7 @@ FT_Bool invert ) { FT_Memory memory = stream->memory; - FT_Error error = CFF_Err_Ok; + FT_Error error = FT_Err_Ok; FT_UShort glyph_sid; @@ -846,20 +901,7 @@ goto Exit; for ( j = 1; j < num_glyphs; j++ ) - { - FT_UShort sid = FT_GET_USHORT(); - - - /* this constant is given in the CFF specification */ - if ( sid < 65000L ) - charset->sids[j] = sid; - else - { - FT_TRACE0(( "cff_charset_load:" - " invalid SID value %d set to zero\n", sid )); - charset->sids[j] = 0; - } - } + charset->sids[j] = FT_GET_USHORT(); FT_FRAME_EXIT(); } @@ -892,18 +934,12 @@ goto Exit; } - /* check whether the range contains at least one valid glyph; */ - /* the constant is given in the CFF specification */ - if ( glyph_sid >= 65000L ) { - FT_ERROR(( "cff_charset_load: invalid SID range\n" )); - error = CFF_Err_Invalid_File_Format; - goto Exit; - } - /* try to rescue some of the SIDs if `nleft' is too large */ - if ( nleft > 65000L - 1L || glyph_sid >= 65000L - nleft ) { - FT_ERROR(( "cff_charset_load: invalid SID range trimmed\n" )); - nleft = ( FT_UInt )( 65000L - 1L - glyph_sid ); + if ( glyph_sid > 0xFFFFL - nleft ) + { + FT_ERROR(( "cff_charset_load: invalid SID range trimmed" + " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid )); + nleft = ( FT_UInt )( 0xFFFFL - glyph_sid ); } /* Fill in the range of sids -- `nleft + 1' glyphs. */ @@ -915,7 +951,7 @@ default: FT_ERROR(( "cff_charset_load: invalid table format\n" )); - error = CFF_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Exit; } } @@ -938,7 +974,7 @@ { FT_ERROR(( "cff_charset_load: implicit charset larger than\n" "predefined charset (Adobe ISO-Latin)\n" )); - error = CFF_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -956,7 +992,7 @@ { FT_ERROR(( "cff_charset_load: implicit charset larger than\n" "predefined charset (Adobe Expert)\n" )); - error = CFF_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -974,7 +1010,7 @@ { FT_ERROR(( "cff_charset_load: implicit charset larger than\n" "predefined charset (Adobe Expert Subset)\n" )); - error = CFF_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -988,7 +1024,7 @@ break; default: - error = CFF_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Exit; } } @@ -1029,7 +1065,7 @@ FT_ULong base_offset, FT_ULong offset ) { - FT_Error error = CFF_Err_Ok; + FT_Error error = FT_Err_Ok; FT_UInt count; FT_UInt j; FT_UShort glyph_sid; @@ -1039,7 +1075,7 @@ /* Check for charset->sids. If we do not have this, we fail. */ if ( !charset->sids ) { - error = CFF_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -1159,7 +1195,7 @@ default: FT_ERROR(( "cff_encoding_load: invalid table format\n" )); - error = CFF_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -1240,9 +1276,7 @@ if ( gid != 0 ) { encoding->codes[j] = (FT_UShort)gid; - - if ( encoding->count < j + 1 ) - encoding->count = j + 1; + encoding->count = j + 1; } else { @@ -1254,7 +1288,7 @@ default: FT_ERROR(( "cff_encoding_load: invalid table format\n" )); - error = CFF_Err_Invalid_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Exit; } } @@ -1287,7 +1321,7 @@ /* set defaults */ FT_MEM_ZERO( top, sizeof ( *top ) ); - top->underline_position = -100L << 16; + top->underline_position = -( 100L << 16 ); top->underline_thickness = 50L << 16; top->charstring_type = 2; top->font_matrix.xx = 0x10000L; @@ -1310,7 +1344,10 @@ error = cff_index_access_element( idx, font_index, &dict, &dict_len ); if ( !error ) + { + FT_TRACE4(( " top dictionary:\n" )); error = cff_parser_run( &parser, dict, dict + dict_len ); + } cff_index_forget_element( idx, &dict ); @@ -1339,6 +1376,7 @@ FT_FRAME_ENTER( font->font_dict.private_size ) ) goto Exit; + FT_TRACE4(( " private dictionary:\n" )); error = cff_parser_run( &parser, (FT_Byte*)stream->cursor, (FT_Byte*)stream->limit ); @@ -1361,9 +1399,8 @@ if ( error ) goto Exit; - font->num_local_subrs = font->local_subrs_index.count; error = cff_index_get_pointers( &font->local_subrs_index, - &font->local_subrs ); + &font->local_subrs, NULL ); if ( error ) goto Exit; } @@ -1409,9 +1446,12 @@ FT_Memory memory = stream->memory; FT_ULong base_offset; CFF_FontRecDict dict; + CFF_IndexRec string_index; + FT_Int subfont_index; FT_ZERO( font ); + FT_ZERO( &string_index ); font->stream = stream; font->memory = memory; @@ -1427,8 +1467,8 @@ font->header_size < 4 || font->absolute_offsize > 4 ) { - FT_TRACE2(( "[not a CFF font header]\n" )); - error = CFF_Err_Unknown_File_Format; + FT_TRACE2(( " not a CFF font header\n" )); + error = FT_THROW( Unknown_File_Format ); goto Exit; } @@ -1438,22 +1478,49 @@ /* read the name, top dict, string and global subrs index */ if ( FT_SET_ERROR( cff_index_init( &font->name_index, - stream, 0 ) ) || + stream, 0 ) ) || FT_SET_ERROR( cff_index_init( &font->font_dict_index, - stream, 0 ) ) || - FT_SET_ERROR( cff_index_init( &font->string_index, - stream, 0 ) ) || + stream, 0 ) ) || + FT_SET_ERROR( cff_index_init( &string_index, + stream, 1 ) ) || FT_SET_ERROR( cff_index_init( &font->global_subrs_index, - stream, 1 ) ) ) + stream, 1 ) ) || + FT_SET_ERROR( cff_index_get_pointers( &string_index, + &font->strings, + &font->string_pool ) ) ) goto Exit; - /* well, we don't really forget the `disabled' fonts... */ - font->num_faces = font->name_index.count; - if ( face_index >= (FT_Int)font->num_faces ) + font->num_strings = string_index.count; + + if ( pure_cff ) + { + /* well, we don't really forget the `disabled' fonts... */ + subfont_index = face_index; + + if ( subfont_index >= (FT_Int)font->name_index.count ) + { + FT_ERROR(( "cff_font_load:" + " invalid subfont index for pure CFF font (%d)\n", + subfont_index )); + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + font->num_faces = font->name_index.count; + } + else { - FT_ERROR(( "cff_font_load: incorrect face index = %d\n", - face_index )); - error = CFF_Err_Invalid_Argument; + subfont_index = 0; + + if ( font->name_index.count > 1 ) + { + FT_ERROR(( "cff_font_load:" + " invalid CFF font with multiple subfonts\n" + " " + " in SFNT wrapper\n" )); + error = FT_THROW( Invalid_File_Format ); + goto Exit; + } } /* in case of a font format check, simply exit now */ @@ -1461,9 +1528,10 @@ goto Exit; /* now, parse the top-level font dictionary */ + FT_TRACE4(( "parsing top-level\n" )); error = cff_subfont_load( &font->top_font, &font->font_dict_index, - face_index, + subfont_index, stream, base_offset, library ); @@ -1481,7 +1549,7 @@ if ( dict->cid_registry != 0xFFFFU ) { CFF_IndexRec fd_index; - CFF_SubFont sub; + CFF_SubFont sub = NULL; FT_UInt idx; @@ -1513,6 +1581,7 @@ for ( idx = 0; idx < fd_index.count; idx++ ) { sub = font->subfonts[idx]; + FT_TRACE4(( "parsing subfont %u\n", idx )); error = cff_subfont_load( sub, &fd_index, idx, stream, base_offset, library ); if ( error ) @@ -1538,16 +1607,14 @@ if ( dict->charstrings_offset == 0 ) { FT_ERROR(( "cff_font_load: no charstrings offset\n" )); - error = CFF_Err_Unknown_File_Format; + error = FT_THROW( Invalid_File_Format ); goto Exit; } - /* explicit the global subrs */ - font->num_global_subrs = font->global_subrs_index.count; - font->num_glyphs = font->charstrings_index.count; + font->num_glyphs = font->charstrings_index.count; error = cff_index_get_pointers( &font->global_subrs_index, - &font->global_subrs ) ; + &font->global_subrs, NULL ); if ( error ) goto Exit; @@ -1579,9 +1646,11 @@ /* get the font name (/CIDFontName for CID-keyed fonts, */ /* /FontName otherwise) */ - font->font_name = cff_index_get_name( &font->name_index, face_index ); + font->font_name = cff_index_get_name( font, subfont_index ); Exit: + cff_index_done( &string_index ); + return error; } @@ -1594,7 +1663,6 @@ cff_index_done( &font->global_subrs_index ); - cff_index_done( &font->string_index ); cff_index_done( &font->font_dict_index ); cff_index_done( &font->name_index ); cff_index_done( &font->charstrings_index ); @@ -1617,21 +1685,18 @@ CFF_Done_FD_Select( &font->fd_select, font->stream ); - if (font->font_info != NULL) - { - FT_FREE( font->font_info->version ); - FT_FREE( font->font_info->notice ); - FT_FREE( font->font_info->full_name ); - FT_FREE( font->font_info->family_name ); - FT_FREE( font->font_info->weight ); - FT_FREE( font->font_info ); - } + FT_FREE( font->font_info ); - FT_FREE( font->registry ); - FT_FREE( font->ordering ); - - FT_FREE( font->global_subrs ); FT_FREE( font->font_name ); + FT_FREE( font->global_subrs ); + FT_FREE( font->strings ); + FT_FREE( font->string_pool ); + + if ( font->cf2_instance.finalizer ) + { + font->cf2_instance.finalizer( font->cf2_instance.data ); + FT_FREE( font->cf2_instance.data ); + } } |