00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <ft2build.h>
00029 #include FT_INTERNAL_STREAM_H
00030 #include FT_TRUETYPE_TAGS_H
00031 #include "ttpost.h"
00032
00033 #include "sferrors.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042 #undef FT_COMPONENT
00043 #define FT_COMPONENT trace_ttpost
00044
00045
00046
00047
00048
00049 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
00050
00051
00052 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
00053
00054 #define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) )
00055
00056
00057 #else
00058
00059
00060
00061
00062
00063
00064 #define MAC_NAME( x ) ( (FT_String*)tt_post_default_names[x] )
00065
00066
00067
00068 static const FT_String* const tt_post_default_names[258] =
00069 {
00070
00071 ".notdef", ".null", "CR", "space", "exclam",
00072 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
00073
00074 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
00075 "comma", "hyphen", "period", "slash", "zero",
00076
00077 "one", "two", "three", "four", "five",
00078 "six", "seven", "eight", "nine", "colon",
00079
00080 "semicolon", "less", "equal", "greater", "question",
00081 "at", "A", "B", "C", "D",
00082
00083 "E", "F", "G", "H", "I",
00084 "J", "K", "L", "M", "N",
00085
00086 "O", "P", "Q", "R", "S",
00087 "T", "U", "V", "W", "X",
00088
00089 "Y", "Z", "bracketleft", "backslash", "bracketright",
00090 "asciicircum", "underscore", "grave", "a", "b",
00091
00092 "c", "d", "e", "f", "g",
00093 "h", "i", "j", "k", "l",
00094
00095 "m", "n", "o", "p", "q",
00096 "r", "s", "t", "u", "v",
00097
00098 "w", "x", "y", "z", "braceleft",
00099 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
00100
00101 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
00102 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
00103
00104 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
00105 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
00106
00107 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
00108 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
00109
00110 "dagger", "degree", "cent", "sterling", "section",
00111 "bullet", "paragraph", "germandbls", "registered", "copyright",
00112
00113 "trademark", "acute", "dieresis", "notequal", "AE",
00114 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
00115
00116 "yen", "mu", "partialdiff", "summation", "product",
00117 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
00118
00119 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
00120 "radical", "florin", "approxequal", "Delta", "guillemotleft",
00121
00122 "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
00123 "Otilde", "OE", "oe", "endash", "emdash",
00124
00125 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
00126 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
00127
00128 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
00129 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
00130
00131 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
00132 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
00133
00134 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
00135 "dotlessi", "circumflex", "tilde", "macron", "breve",
00136
00137 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
00138 "caron", "Lslash", "lslash", "Scaron", "scaron",
00139
00140 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
00141 "Yacute", "yacute", "Thorn", "thorn", "minus",
00142
00143 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
00144 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
00145
00146 "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
00147 "Ccaron", "ccaron", "dmacron",
00148 };
00149
00150
00151 #endif
00152
00153
00154 static FT_Error
00155 load_format_20( TT_Face face,
00156 FT_Stream stream )
00157 {
00158 FT_Memory memory = stream->memory;
00159 FT_Error error;
00160
00161 FT_Int num_glyphs;
00162 FT_UShort num_names;
00163
00164 FT_UShort* glyph_indices = 0;
00165 FT_Char** name_strings = 0;
00166
00167
00168 if ( FT_READ_USHORT( num_glyphs ) )
00169 goto Exit;
00170
00171
00172
00173
00174
00175
00176
00177 if ( num_glyphs > face->max_profile.numGlyphs )
00178 {
00179 error = SFNT_Err_Invalid_File_Format;
00180 goto Exit;
00181 }
00182
00183
00184 {
00185 FT_Int n;
00186
00187
00188 if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) ||
00189 FT_FRAME_ENTER( num_glyphs * 2L ) )
00190 goto Fail;
00191
00192 for ( n = 0; n < num_glyphs; n++ )
00193 glyph_indices[n] = FT_GET_USHORT();
00194
00195 FT_FRAME_EXIT();
00196 }
00197
00198
00199 {
00200 FT_Int n;
00201
00202
00203 num_names = 0;
00204
00205 for ( n = 0; n < num_glyphs; n++ )
00206 {
00207 FT_Int idx;
00208
00209
00210 idx = glyph_indices[n];
00211 if ( idx >= 258 )
00212 {
00213 idx -= 257;
00214 if ( idx > num_names )
00215 num_names = (FT_UShort)idx;
00216 }
00217 }
00218 }
00219
00220
00221 {
00222 FT_UShort n;
00223
00224
00225 if ( FT_NEW_ARRAY( name_strings, num_names ) )
00226 goto Fail;
00227
00228 for ( n = 0; n < num_names; n++ )
00229 {
00230 FT_UInt len;
00231
00232
00233 if ( FT_READ_BYTE ( len ) ||
00234 FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
00235 FT_STREAM_READ ( name_strings[n], len ) )
00236 goto Fail1;
00237
00238 name_strings[n][len] = '\0';
00239 }
00240 }
00241
00242
00243 {
00244 TT_Post_20 table = &face->postscript_names.names.format_20;
00245
00246
00247 table->num_glyphs = (FT_UShort)num_glyphs;
00248 table->num_names = (FT_UShort)num_names;
00249 table->glyph_indices = glyph_indices;
00250 table->glyph_names = name_strings;
00251 }
00252 return SFNT_Err_Ok;
00253
00254 Fail1:
00255 {
00256 FT_UShort n;
00257
00258
00259 for ( n = 0; n < num_names; n++ )
00260 FT_FREE( name_strings[n] );
00261 }
00262
00263 Fail:
00264 FT_FREE( name_strings );
00265 FT_FREE( glyph_indices );
00266
00267 Exit:
00268 return error;
00269 }
00270
00271
00272 static FT_Error
00273 load_format_25( TT_Face face,
00274 FT_Stream stream )
00275 {
00276 FT_Memory memory = stream->memory;
00277 FT_Error error;
00278
00279 FT_Int num_glyphs;
00280 FT_Char* offset_table = 0;
00281
00282
00283
00284 if ( FT_READ_USHORT( num_glyphs ) )
00285 goto Exit;
00286
00287
00288 if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 )
00289 {
00290 error = SFNT_Err_Invalid_File_Format;
00291 goto Exit;
00292 }
00293
00294 if ( FT_NEW_ARRAY( offset_table, num_glyphs ) ||
00295 FT_STREAM_READ( offset_table, num_glyphs ) )
00296 goto Fail;
00297
00298
00299 {
00300 FT_Int n;
00301
00302
00303 for ( n = 0; n < num_glyphs; n++ )
00304 {
00305 FT_Long idx = (FT_Long)n + offset_table[n];
00306
00307
00308 if ( idx < 0 || idx > num_glyphs )
00309 {
00310 error = SFNT_Err_Invalid_File_Format;
00311 goto Fail;
00312 }
00313 }
00314 }
00315
00316
00317 {
00318 TT_Post_25 table = &face->postscript_names.names.format_25;
00319
00320
00321 table->num_glyphs = (FT_UShort)num_glyphs;
00322 table->offsets = offset_table;
00323 }
00324
00325 return SFNT_Err_Ok;
00326
00327 Fail:
00328 FT_FREE( offset_table );
00329
00330 Exit:
00331 return error;
00332 }
00333
00334
00335 static FT_Error
00336 load_post_names( TT_Face face )
00337 {
00338 FT_Stream stream;
00339 FT_Error error;
00340 FT_Fixed format;
00341
00342
00343
00344 stream = face->root.stream;
00345
00346
00347 error = face->goto_table( face, TTAG_post, stream, 0 );
00348 if ( error )
00349 goto Exit;
00350
00351 format = face->postscript.FormatType;
00352
00353
00354 if ( FT_STREAM_SKIP( 32 ) )
00355 goto Exit;
00356
00357
00358 if ( format == 0x00020000L )
00359 error = load_format_20( face, stream );
00360 else if ( format == 0x00028000L )
00361 error = load_format_25( face, stream );
00362 else
00363 error = SFNT_Err_Invalid_File_Format;
00364
00365 face->postscript_names.loaded = 1;
00366
00367 Exit:
00368 return error;
00369 }
00370
00371
00372 FT_LOCAL_DEF( void )
00373 tt_face_free_ps_names( TT_Face face )
00374 {
00375 FT_Memory memory = face->root.memory;
00376 TT_Post_Names names = &face->postscript_names;
00377 FT_Fixed format;
00378
00379
00380 if ( names->loaded )
00381 {
00382 format = face->postscript.FormatType;
00383
00384 if ( format == 0x00020000L )
00385 {
00386 TT_Post_20 table = &names->names.format_20;
00387 FT_UShort n;
00388
00389
00390 FT_FREE( table->glyph_indices );
00391 table->num_glyphs = 0;
00392
00393 for ( n = 0; n < table->num_names; n++ )
00394 FT_FREE( table->glyph_names[n] );
00395
00396 FT_FREE( table->glyph_names );
00397 table->num_names = 0;
00398 }
00399 else if ( format == 0x00028000L )
00400 {
00401 TT_Post_25 table = &names->names.format_25;
00402
00403
00404 FT_FREE( table->offsets );
00405 table->num_glyphs = 0;
00406 }
00407 }
00408 names->loaded = 0;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 FT_LOCAL_DEF( FT_Error )
00435 tt_face_get_ps_name( TT_Face face,
00436 FT_UInt idx,
00437 FT_String** PSname )
00438 {
00439 FT_Error error;
00440 TT_Post_Names names;
00441 FT_Fixed format;
00442
00443 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
00444 FT_Service_PsCMaps psnames;
00445 #endif
00446
00447
00448 if ( !face )
00449 return SFNT_Err_Invalid_Face_Handle;
00450
00451 if ( idx >= (FT_UInt)face->max_profile.numGlyphs )
00452 return SFNT_Err_Invalid_Glyph_Index;
00453
00454 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
00455 psnames = (FT_Service_PsCMaps)face->psnames;
00456 if ( !psnames )
00457 return SFNT_Err_Unimplemented_Feature;
00458 #endif
00459
00460 names = &face->postscript_names;
00461
00462
00463 *PSname = MAC_NAME( 0 );
00464
00465 format = face->postscript.FormatType;
00466
00467 if ( format == 0x00010000L )
00468 {
00469 if ( idx < 258 )
00470 *PSname = MAC_NAME( idx );
00471 }
00472 else if ( format == 0x00020000L )
00473 {
00474 TT_Post_20 table = &names->names.format_20;
00475
00476
00477 if ( !names->loaded )
00478 {
00479 error = load_post_names( face );
00480 if ( error )
00481 goto End;
00482 }
00483
00484 if ( idx < (FT_UInt)table->num_glyphs )
00485 {
00486 FT_UShort name_index = table->glyph_indices[idx];
00487
00488
00489 if ( name_index < 258 )
00490 *PSname = MAC_NAME( name_index );
00491 else
00492 *PSname = (FT_String*)table->glyph_names[name_index - 258];
00493 }
00494 }
00495 else if ( format == 0x00028000L )
00496 {
00497 TT_Post_25 table = &names->names.format_25;
00498
00499
00500 if ( !names->loaded )
00501 {
00502 error = load_post_names( face );
00503 if ( error )
00504 goto End;
00505 }
00506
00507 if ( idx < (FT_UInt)table->num_glyphs )
00508 {
00509 idx += table->offsets[idx];
00510 *PSname = MAC_NAME( idx );
00511 }
00512 }
00513
00514
00515
00516 End:
00517 return SFNT_Err_Ok;
00518 }
00519
00520
00521