static void t42_parse_encoding( T42_Face face, T42_Loader loader ) { T42_Parser parser = &loader->parser; FT_Byte* cur; FT_Byte* limit = parser->root.limit; PSAux_Service psaux = (PSAux_Service)face->psaux; T1_Skip_Spaces( parser ); cur = parser->root.cursor; if ( cur >= limit ) { FT_ERROR(( "t42_parse_encoding: out of bounds\n" )); parser->root.error = T42_Err_Invalid_File_Format; return; } /* if we have a number or `[', the encoding is an array, */ /* and we must load it now */ if ( ft_isdigit( *cur ) || *cur == '[' ) { T1_Encoding encode = &face->type1.encoding; FT_UInt count, n; PS_Table char_table = &loader->encoding_table; FT_Memory memory = parser->root.memory; FT_Error error; FT_Bool only_immediates = 0; /* read the number of entries in the encoding; should be 256 */ if ( *cur == '[' ) { count = 256; only_immediates = 1; parser->root.cursor++; } else count = (FT_UInt)T1_ToInt( parser ); T1_Skip_Spaces( parser ); if ( parser->root.cursor >= limit ) return; /* we use a T1_Table to store our charnames */ loader->num_chars = encode->num_chars = count; if ( FT_NEW_ARRAY( encode->char_index, count ) || FT_NEW_ARRAY( encode->char_name, count ) || FT_SET_ERROR( psaux->ps_table_funcs->init( char_table, count, memory ) ) ) { parser->root.error = error; return; } /* We need to `zero' out encoding_table.elements */ for ( n = 0; n < count; n++ ) { char* notdef = (char *)".notdef"; T1_Add_Table( char_table, n, notdef, 8 ); } /* Now we need to read records of the form */ /* */ /* ... charcode /charname ... */ /* */ /* for each entry in our table. */ /* */ /* We simply look for a number followed by an immediate */ /* name. Note that this ignores correctly the sequence */ /* that is often seen in type42 fonts: */ /* */ /* 0 1 255 { 1 index exch /.notdef put } for dup */ /* */ /* used to clean the encoding array before anything else. */ /* */ /* Alternatively, if the array is directly given as */ /* */ /* /Encoding [ ... ] */ /* */ /* we only read immediates. */ n = 0; T1_Skip_Spaces( parser ); while ( parser->root.cursor < limit ) { cur = parser->root.cursor; /* we stop when we encounter `def' or `]' */ if ( *cur == 'd' && cur + 3 < limit ) { if ( cur[1] == 'e' && cur[2] == 'f' && t42_is_space( cur[3] ) ) { FT_TRACE6(( "encoding end\n" )); cur += 3; break; } } if ( *cur == ']' ) { FT_TRACE6(( "encoding end\n" )); cur++; break; } /* check whether we have found an entry */ if ( ft_isdigit( *cur ) || only_immediates ) { FT_Int charcode; if ( only_immediates ) charcode = n; else { charcode = (FT_Int)T1_ToInt( parser ); T1_Skip_Spaces( parser ); } cur = parser->root.cursor; if ( *cur == '/' && cur + 2 < limit && n < count ) { FT_PtrDist len; cur++; parser->root.cursor = cur; T1_Skip_PS_Token( parser ); if ( parser->root.error ) return; len = parser->root.cursor - cur; parser->root.error = T1_Add_Table( char_table, charcode, cur, len + 1 ); if ( parser->root.error ) return; char_table->elements[charcode][len] = '\0'; n++; } } else { T1_Skip_PS_Token( parser ); if ( parser->root.error ) return; } T1_Skip_Spaces( parser ); } face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; parser->root.cursor = cur; } /* Otherwise, we should have either `StandardEncoding', */ /* `ExpertEncoding', or `ISOLatin1Encoding' */ else { if ( cur + 17 < limit && ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; else if ( cur + 15 < limit && ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; else if ( cur + 18 < limit && ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; else { FT_ERROR(( "t42_parse_encoding: invalid token\n" )); parser->root.error = T42_Err_Invalid_File_Format; } } }
static FT_Error load_format_20( TT_Face face, FT_Stream stream, FT_Long post_limit ) { FT_Memory memory = stream->memory; FT_Error error; FT_Int num_glyphs; FT_UShort num_names; FT_UShort* glyph_indices = 0; FT_Char** name_strings = 0; if ( FT_READ_USHORT( num_glyphs ) ) goto Exit; /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ /* than the value in the maxp table (cf. cyberbit.ttf). */ /* There already exist fonts which have more than 32768 glyph names */ /* in this table, so the test for this threshold has been dropped. */ if ( num_glyphs > face->max_profile.numGlyphs ) { error = SFNT_Err_Invalid_File_Format; goto Exit; } /* load the indices */ { FT_Int n; if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) || FT_FRAME_ENTER( num_glyphs * 2L ) ) goto Fail; for ( n = 0; n < num_glyphs; n++ ) glyph_indices[n] = FT_GET_USHORT(); FT_FRAME_EXIT(); } /* compute number of names stored in table */ { FT_Int n; num_names = 0; for ( n = 0; n < num_glyphs; n++ ) { FT_Int idx; idx = glyph_indices[n]; if ( idx >= 258 ) { idx -= 257; if ( idx > num_names ) num_names = (FT_UShort)idx; } } } /* now load the name strings */ { FT_UShort n; if ( FT_NEW_ARRAY( name_strings, num_names ) ) goto Fail; for ( n = 0; n < num_names; n++ ) { FT_UInt len; if ( FT_STREAM_POS() >= post_limit ) break; else { FT_TRACE6(( "load_format_20: %d byte left in post table\n", post_limit - FT_STREAM_POS() )); if ( FT_READ_BYTE( len ) ) goto Fail1; } if ( (FT_Int)len > post_limit || FT_STREAM_POS() > post_limit - (FT_Int)len ) { FT_ERROR(( "load_format_20:" " exceeding string length (%d)," " truncating at end of post table (%d byte left)\n", len, post_limit - FT_STREAM_POS() )); len = FT_MAX( 0, post_limit - FT_STREAM_POS() ); } if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) || FT_STREAM_READ( name_strings[n], len ) ) goto Fail1; name_strings[n][len] = '\0'; } if ( n < num_names ) { FT_ERROR(( "load_format_20:" " all entries in post table are already parsed," " using NULL names for gid %d - %d\n", n, num_names - 1 )); for ( ; n < num_names; n++ ) if ( FT_NEW_ARRAY( name_strings[n], 1 ) ) goto Fail1; else name_strings[n][0] = '\0'; } } /* all right, set table fields and exit successfully */ { TT_Post_20 table = &face->postscript_names.names.format_20; table->num_glyphs = (FT_UShort)num_glyphs; table->num_names = (FT_UShort)num_names; table->glyph_indices = glyph_indices; table->glyph_names = name_strings; } return SFNT_Err_Ok; Fail1: { FT_UShort n; for ( n = 0; n < num_names; n++ ) FT_FREE( name_strings[n] ); } Fail: FT_FREE( name_strings ); FT_FREE( glyph_indices ); Exit: return error; }