| 1 | /**************************************************************************** | 
|---|
| 2 | * | 
|---|
| 3 | * ttpost.c | 
|---|
| 4 | * | 
|---|
| 5 | *   PostScript name table processing for TrueType and OpenType fonts | 
|---|
| 6 | *   (body). | 
|---|
| 7 | * | 
|---|
| 8 | * Copyright (C) 1996-2019 by | 
|---|
| 9 | * David Turner, Robert Wilhelm, and Werner Lemberg. | 
|---|
| 10 | * | 
|---|
| 11 | * This file is part of the FreeType project, and may only be used, | 
|---|
| 12 | * modified, and distributed under the terms of the FreeType project | 
|---|
| 13 | * license, LICENSE.TXT.  By continuing to use, modify, or distribute | 
|---|
| 14 | * this file you indicate that you have read the license and | 
|---|
| 15 | * understand and accept it fully. | 
|---|
| 16 | * | 
|---|
| 17 | */ | 
|---|
| 18 |  | 
|---|
| 19 | /************************************************************************** | 
|---|
| 20 | * | 
|---|
| 21 | * The post table is not completely loaded by the core engine.  This | 
|---|
| 22 | * file loads the missing PS glyph names and implements an API to access | 
|---|
| 23 | * them. | 
|---|
| 24 | * | 
|---|
| 25 | */ | 
|---|
| 26 |  | 
|---|
| 27 |  | 
|---|
| 28 | #include <ft2build.h> | 
|---|
| 29 | #include FT_INTERNAL_DEBUG_H | 
|---|
| 30 | #include FT_INTERNAL_STREAM_H | 
|---|
| 31 | #include FT_TRUETYPE_TAGS_H | 
|---|
| 32 |  | 
|---|
| 33 |  | 
|---|
| 34 | #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES | 
|---|
| 35 |  | 
|---|
| 36 | #include "ttpost.h" | 
|---|
| 37 |  | 
|---|
| 38 | #include "sferrors.h" | 
|---|
| 39 |  | 
|---|
| 40 |  | 
|---|
| 41 | /************************************************************************** | 
|---|
| 42 | * | 
|---|
| 43 | * The macro FT_COMPONENT is used in trace mode.  It is an implicit | 
|---|
| 44 | * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log | 
|---|
| 45 | * messages during execution. | 
|---|
| 46 | */ | 
|---|
| 47 | #undef  FT_COMPONENT | 
|---|
| 48 | #define FT_COMPONENT  ttpost | 
|---|
| 49 |  | 
|---|
| 50 |  | 
|---|
| 51 | /* If this configuration macro is defined, we rely on the `psnames' */ | 
|---|
| 52 | /* module to grab the glyph names.                                  */ | 
|---|
| 53 |  | 
|---|
| 54 | #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES | 
|---|
| 55 |  | 
|---|
| 56 |  | 
|---|
| 57 | #include FT_SERVICE_POSTSCRIPT_CMAPS_H | 
|---|
| 58 |  | 
|---|
| 59 | #define MAC_NAME( x )  (FT_String*)psnames->macintosh_name( (FT_UInt)(x) ) | 
|---|
| 60 |  | 
|---|
| 61 |  | 
|---|
| 62 | #else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ | 
|---|
| 63 |  | 
|---|
| 64 |  | 
|---|
| 65 | /* Otherwise, we ignore the `psnames' module, and provide our own  */ | 
|---|
| 66 | /* table of Mac names.  Thus, it is possible to build a version of */ | 
|---|
| 67 | /* FreeType without the Type 1 driver & psnames module.            */ | 
|---|
| 68 |  | 
|---|
| 69 | #define MAC_NAME( x )  (FT_String*)tt_post_default_names[x] | 
|---|
| 70 |  | 
|---|
| 71 | /* the 258 default Mac PS glyph names; see file `tools/glnames.py' */ | 
|---|
| 72 |  | 
|---|
| 73 | static const FT_String* const  tt_post_default_names[258] = | 
|---|
| 74 | { | 
|---|
| 75 | /*   0 */ | 
|---|
| 76 | ".notdef", ".null", "nonmarkingreturn", "space", "exclam", | 
|---|
| 77 | "quotedbl", "numbersign", "dollar", "percent", "ampersand", | 
|---|
| 78 | /*  10 */ | 
|---|
| 79 | "quotesingle", "parenleft", "parenright", "asterisk", "plus", | 
|---|
| 80 | "comma", "hyphen", "period", "slash", "zero", | 
|---|
| 81 | /*  20 */ | 
|---|
| 82 | "one", "two", "three", "four", "five", | 
|---|
| 83 | "six", "seven", "eight", "nine", "colon", | 
|---|
| 84 | /*  30 */ | 
|---|
| 85 | "semicolon", "less", "equal", "greater", "question", | 
|---|
| 86 | "at", "A", "B", "C", "D", | 
|---|
| 87 | /*  40 */ | 
|---|
| 88 | "E", "F", "G", "H", "I", | 
|---|
| 89 | "J", "K", "L", "M", "N", | 
|---|
| 90 | /*  50 */ | 
|---|
| 91 | "O", "P", "Q", "R", "S", | 
|---|
| 92 | "T", "U", "V", "W", "X", | 
|---|
| 93 | /*  60 */ | 
|---|
| 94 | "Y", "Z", "bracketleft", "backslash", "bracketright", | 
|---|
| 95 | "asciicircum", "underscore", "grave", "a", "b", | 
|---|
| 96 | /*  70 */ | 
|---|
| 97 | "c", "d", "e", "f", "g", | 
|---|
| 98 | "h", "i", "j", "k", "l", | 
|---|
| 99 | /*  80 */ | 
|---|
| 100 | "m", "n", "o", "p", "q", | 
|---|
| 101 | "r", "s", "t", "u", "v", | 
|---|
| 102 | /*  90 */ | 
|---|
| 103 | "w", "x", "y", "z", "braceleft", | 
|---|
| 104 | "bar", "braceright", "asciitilde", "Adieresis", "Aring", | 
|---|
| 105 | /* 100 */ | 
|---|
| 106 | "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", | 
|---|
| 107 | "aacute", "agrave", "acircumflex", "adieresis", "atilde", | 
|---|
| 108 | /* 110 */ | 
|---|
| 109 | "aring", "ccedilla", "eacute", "egrave", "ecircumflex", | 
|---|
| 110 | "edieresis", "iacute", "igrave", "icircumflex", "idieresis", | 
|---|
| 111 | /* 120 */ | 
|---|
| 112 | "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", | 
|---|
| 113 | "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", | 
|---|
| 114 | /* 130 */ | 
|---|
| 115 | "dagger", "degree", "cent", "sterling", "section", | 
|---|
| 116 | "bullet", "paragraph", "germandbls", "registered", "copyright", | 
|---|
| 117 | /* 140 */ | 
|---|
| 118 | "trademark", "acute", "dieresis", "notequal", "AE", | 
|---|
| 119 | "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", | 
|---|
| 120 | /* 150 */ | 
|---|
| 121 | "yen", "mu", "partialdiff", "summation", "product", | 
|---|
| 122 | "pi", "integral", "ordfeminine", "ordmasculine", "Omega", | 
|---|
| 123 | /* 160 */ | 
|---|
| 124 | "ae", "oslash", "questiondown", "exclamdown", "logicalnot", | 
|---|
| 125 | "radical", "florin", "approxequal", "Delta", "guillemotleft", | 
|---|
| 126 | /* 170 */ | 
|---|
| 127 | "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde", | 
|---|
| 128 | "Otilde", "OE", "oe", "endash", "emdash", | 
|---|
| 129 | /* 180 */ | 
|---|
| 130 | "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", | 
|---|
| 131 | "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", | 
|---|
| 132 | /* 190 */ | 
|---|
| 133 | "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", | 
|---|
| 134 | "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", | 
|---|
| 135 | /* 200 */ | 
|---|
| 136 | "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", | 
|---|
| 137 | "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", | 
|---|
| 138 | /* 210 */ | 
|---|
| 139 | "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", | 
|---|
| 140 | "dotlessi", "circumflex", "tilde", "macron", "breve", | 
|---|
| 141 | /* 220 */ | 
|---|
| 142 | "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", | 
|---|
| 143 | "caron", "Lslash", "lslash", "Scaron", "scaron", | 
|---|
| 144 | /* 230 */ | 
|---|
| 145 | "Zcaron", "zcaron", "brokenbar", "Eth", "eth", | 
|---|
| 146 | "Yacute", "yacute", "Thorn", "thorn", "minus", | 
|---|
| 147 | /* 240 */ | 
|---|
| 148 | "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", | 
|---|
| 149 | "onequarter", "threequarters", "franc", "Gbreve", "gbreve", | 
|---|
| 150 | /* 250 */ | 
|---|
| 151 | "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", | 
|---|
| 152 | "Ccaron", "ccaron", "dcroat", | 
|---|
| 153 | }; | 
|---|
| 154 |  | 
|---|
| 155 |  | 
|---|
| 156 | #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ | 
|---|
| 157 |  | 
|---|
| 158 |  | 
|---|
| 159 | static FT_Error | 
|---|
| 160 | load_format_20( TT_Face    face, | 
|---|
| 161 | FT_Stream  stream, | 
|---|
| 162 | FT_ULong   post_limit ) | 
|---|
| 163 | { | 
|---|
| 164 | FT_Memory   memory = stream->memory; | 
|---|
| 165 | FT_Error    error; | 
|---|
| 166 |  | 
|---|
| 167 | FT_Int      num_glyphs; | 
|---|
| 168 | FT_UShort   num_names; | 
|---|
| 169 |  | 
|---|
| 170 | FT_UShort*  glyph_indices = NULL; | 
|---|
| 171 | FT_Char**   name_strings  = NULL; | 
|---|
| 172 |  | 
|---|
| 173 |  | 
|---|
| 174 | if ( FT_READ_USHORT( num_glyphs ) ) | 
|---|
| 175 | goto Exit; | 
|---|
| 176 |  | 
|---|
| 177 | /* UNDOCUMENTED!  The number of glyphs in this table can be smaller */ | 
|---|
| 178 | /* than the value in the maxp table (cf. cyberbit.ttf).             */ | 
|---|
| 179 |  | 
|---|
| 180 | /* There already exist fonts which have more than 32768 glyph names */ | 
|---|
| 181 | /* in this table, so the test for this threshold has been dropped.  */ | 
|---|
| 182 |  | 
|---|
| 183 | if ( num_glyphs > face->max_profile.numGlyphs ) | 
|---|
| 184 | { | 
|---|
| 185 | error = FT_THROW( Invalid_File_Format ); | 
|---|
| 186 | goto Exit; | 
|---|
| 187 | } | 
|---|
| 188 |  | 
|---|
| 189 | /* load the indices */ | 
|---|
| 190 | { | 
|---|
| 191 | FT_Int  n; | 
|---|
| 192 |  | 
|---|
| 193 |  | 
|---|
| 194 | if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) || | 
|---|
| 195 | FT_FRAME_ENTER( num_glyphs * 2L )          ) | 
|---|
| 196 | goto Fail; | 
|---|
| 197 |  | 
|---|
| 198 | for ( n = 0; n < num_glyphs; n++ ) | 
|---|
| 199 | glyph_indices[n] = FT_GET_USHORT(); | 
|---|
| 200 |  | 
|---|
| 201 | FT_FRAME_EXIT(); | 
|---|
| 202 | } | 
|---|
| 203 |  | 
|---|
| 204 | /* compute number of names stored in table */ | 
|---|
| 205 | { | 
|---|
| 206 | FT_Int  n; | 
|---|
| 207 |  | 
|---|
| 208 |  | 
|---|
| 209 | num_names = 0; | 
|---|
| 210 |  | 
|---|
| 211 | for ( n = 0; n < num_glyphs; n++ ) | 
|---|
| 212 | { | 
|---|
| 213 | FT_Int  idx; | 
|---|
| 214 |  | 
|---|
| 215 |  | 
|---|
| 216 | idx = glyph_indices[n]; | 
|---|
| 217 | if ( idx >= 258 ) | 
|---|
| 218 | { | 
|---|
| 219 | idx -= 257; | 
|---|
| 220 | if ( idx > num_names ) | 
|---|
| 221 | num_names = (FT_UShort)idx; | 
|---|
| 222 | } | 
|---|
| 223 | } | 
|---|
| 224 | } | 
|---|
| 225 |  | 
|---|
| 226 | /* now load the name strings */ | 
|---|
| 227 | { | 
|---|
| 228 | FT_UShort  n; | 
|---|
| 229 |  | 
|---|
| 230 |  | 
|---|
| 231 | if ( FT_NEW_ARRAY( name_strings, num_names ) ) | 
|---|
| 232 | goto Fail; | 
|---|
| 233 |  | 
|---|
| 234 | for ( n = 0; n < num_names; n++ ) | 
|---|
| 235 | { | 
|---|
| 236 | FT_UInt  len; | 
|---|
| 237 |  | 
|---|
| 238 |  | 
|---|
| 239 | if ( FT_STREAM_POS() >= post_limit ) | 
|---|
| 240 | break; | 
|---|
| 241 | else | 
|---|
| 242 | { | 
|---|
| 243 | FT_TRACE6(( "load_format_20: %d byte left in post table\n", | 
|---|
| 244 | post_limit - FT_STREAM_POS() )); | 
|---|
| 245 |  | 
|---|
| 246 | if ( FT_READ_BYTE( len ) ) | 
|---|
| 247 | goto Fail1; | 
|---|
| 248 | } | 
|---|
| 249 |  | 
|---|
| 250 | if ( len > post_limit                   || | 
|---|
| 251 | FT_STREAM_POS() > post_limit - len ) | 
|---|
| 252 | { | 
|---|
| 253 | FT_Int  d = (FT_Int)post_limit - (FT_Int)FT_STREAM_POS(); | 
|---|
| 254 |  | 
|---|
| 255 |  | 
|---|
| 256 | FT_ERROR(( "load_format_20:" | 
|---|
| 257 | " exceeding string length (%d)," | 
|---|
| 258 | " truncating at end of post table (%d byte left)\n", | 
|---|
| 259 | len, d )); | 
|---|
| 260 | len = (FT_UInt)FT_MAX( 0, d ); | 
|---|
| 261 | } | 
|---|
| 262 |  | 
|---|
| 263 | if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) || | 
|---|
| 264 | FT_STREAM_READ( name_strings[n], len   ) ) | 
|---|
| 265 | goto Fail1; | 
|---|
| 266 |  | 
|---|
| 267 | name_strings[n][len] = '\0'; | 
|---|
| 268 | } | 
|---|
| 269 |  | 
|---|
| 270 | if ( n < num_names ) | 
|---|
| 271 | { | 
|---|
| 272 | FT_ERROR(( "load_format_20:" | 
|---|
| 273 | " all entries in post table are already parsed," | 
|---|
| 274 | " using NULL names for gid %d - %d\n", | 
|---|
| 275 | n, num_names - 1 )); | 
|---|
| 276 | for ( ; n < num_names; n++ ) | 
|---|
| 277 | if ( FT_NEW_ARRAY( name_strings[n], 1 ) ) | 
|---|
| 278 | goto Fail1; | 
|---|
| 279 | else | 
|---|
| 280 | name_strings[n][0] = '\0'; | 
|---|
| 281 | } | 
|---|
| 282 | } | 
|---|
| 283 |  | 
|---|
| 284 | /* all right, set table fields and exit successfully */ | 
|---|
| 285 | { | 
|---|
| 286 | TT_Post_20  table = &face->postscript_names.names.format_20; | 
|---|
| 287 |  | 
|---|
| 288 |  | 
|---|
| 289 | table->num_glyphs    = (FT_UShort)num_glyphs; | 
|---|
| 290 | table->num_names     = (FT_UShort)num_names; | 
|---|
| 291 | table->glyph_indices = glyph_indices; | 
|---|
| 292 | table->glyph_names   = name_strings; | 
|---|
| 293 | } | 
|---|
| 294 | return FT_Err_Ok; | 
|---|
| 295 |  | 
|---|
| 296 | Fail1: | 
|---|
| 297 | { | 
|---|
| 298 | FT_UShort  n; | 
|---|
| 299 |  | 
|---|
| 300 |  | 
|---|
| 301 | for ( n = 0; n < num_names; n++ ) | 
|---|
| 302 | FT_FREE( name_strings[n] ); | 
|---|
| 303 | } | 
|---|
| 304 |  | 
|---|
| 305 | Fail: | 
|---|
| 306 | FT_FREE( name_strings ); | 
|---|
| 307 | FT_FREE( glyph_indices ); | 
|---|
| 308 |  | 
|---|
| 309 | Exit: | 
|---|
| 310 | return error; | 
|---|
| 311 | } | 
|---|
| 312 |  | 
|---|
| 313 |  | 
|---|
| 314 | static FT_Error | 
|---|
| 315 | load_format_25( TT_Face    face, | 
|---|
| 316 | FT_Stream  stream, | 
|---|
| 317 | FT_ULong   post_limit ) | 
|---|
| 318 | { | 
|---|
| 319 | FT_Memory  memory = stream->memory; | 
|---|
| 320 | FT_Error   error; | 
|---|
| 321 |  | 
|---|
| 322 | FT_Int     num_glyphs; | 
|---|
| 323 | FT_Char*   offset_table = NULL; | 
|---|
| 324 |  | 
|---|
| 325 | FT_UNUSED( post_limit ); | 
|---|
| 326 |  | 
|---|
| 327 |  | 
|---|
| 328 | if ( FT_READ_USHORT( num_glyphs ) ) | 
|---|
| 329 | goto Exit; | 
|---|
| 330 |  | 
|---|
| 331 | /* check the number of glyphs */ | 
|---|
| 332 | if ( num_glyphs > face->max_profile.numGlyphs || | 
|---|
| 333 | num_glyphs > 258                         || | 
|---|
| 334 | num_glyphs < 1                           ) | 
|---|
| 335 | { | 
|---|
| 336 | error = FT_THROW( Invalid_File_Format ); | 
|---|
| 337 | goto Exit; | 
|---|
| 338 | } | 
|---|
| 339 |  | 
|---|
| 340 | if ( FT_NEW_ARRAY( offset_table, num_glyphs )   || | 
|---|
| 341 | FT_STREAM_READ( offset_table, num_glyphs ) ) | 
|---|
| 342 | goto Fail; | 
|---|
| 343 |  | 
|---|
| 344 | /* now check the offset table */ | 
|---|
| 345 | { | 
|---|
| 346 | FT_Int  n; | 
|---|
| 347 |  | 
|---|
| 348 |  | 
|---|
| 349 | for ( n = 0; n < num_glyphs; n++ ) | 
|---|
| 350 | { | 
|---|
| 351 | FT_Long  idx = (FT_Long)n + offset_table[n]; | 
|---|
| 352 |  | 
|---|
| 353 |  | 
|---|
| 354 | if ( idx < 0 || idx > num_glyphs ) | 
|---|
| 355 | { | 
|---|
| 356 | error = FT_THROW( Invalid_File_Format ); | 
|---|
| 357 | goto Fail; | 
|---|
| 358 | } | 
|---|
| 359 | } | 
|---|
| 360 | } | 
|---|
| 361 |  | 
|---|
| 362 | /* OK, set table fields and exit successfully */ | 
|---|
| 363 | { | 
|---|
| 364 | TT_Post_25  table = &face->postscript_names.names.format_25; | 
|---|
| 365 |  | 
|---|
| 366 |  | 
|---|
| 367 | table->num_glyphs = (FT_UShort)num_glyphs; | 
|---|
| 368 | table->offsets    = offset_table; | 
|---|
| 369 | } | 
|---|
| 370 |  | 
|---|
| 371 | return FT_Err_Ok; | 
|---|
| 372 |  | 
|---|
| 373 | Fail: | 
|---|
| 374 | FT_FREE( offset_table ); | 
|---|
| 375 |  | 
|---|
| 376 | Exit: | 
|---|
| 377 | return error; | 
|---|
| 378 | } | 
|---|
| 379 |  | 
|---|
| 380 |  | 
|---|
| 381 | static FT_Error | 
|---|
| 382 | load_post_names( TT_Face  face ) | 
|---|
| 383 | { | 
|---|
| 384 | FT_Stream  stream; | 
|---|
| 385 | FT_Error   error; | 
|---|
| 386 | FT_Fixed   format; | 
|---|
| 387 | FT_ULong   post_len; | 
|---|
| 388 | FT_ULong   post_limit; | 
|---|
| 389 |  | 
|---|
| 390 |  | 
|---|
| 391 | /* get a stream for the face's resource */ | 
|---|
| 392 | stream = face->root.stream; | 
|---|
| 393 |  | 
|---|
| 394 | /* seek to the beginning of the PS names table */ | 
|---|
| 395 | error = face->goto_table( face, TTAG_post, stream, &post_len ); | 
|---|
| 396 | if ( error ) | 
|---|
| 397 | goto Exit; | 
|---|
| 398 |  | 
|---|
| 399 | post_limit = FT_STREAM_POS() + post_len; | 
|---|
| 400 |  | 
|---|
| 401 | format = face->postscript.FormatType; | 
|---|
| 402 |  | 
|---|
| 403 | /* go to beginning of subtable */ | 
|---|
| 404 | if ( FT_STREAM_SKIP( 32 ) ) | 
|---|
| 405 | goto Exit; | 
|---|
| 406 |  | 
|---|
| 407 | /* now read postscript table */ | 
|---|
| 408 | if ( format == 0x00020000L ) | 
|---|
| 409 | error = load_format_20( face, stream, post_limit ); | 
|---|
| 410 | else if ( format == 0x00025000L ) | 
|---|
| 411 | error = load_format_25( face, stream, post_limit ); | 
|---|
| 412 | else | 
|---|
| 413 | error = FT_THROW( Invalid_File_Format ); | 
|---|
| 414 |  | 
|---|
| 415 | face->postscript_names.loaded = 1; | 
|---|
| 416 |  | 
|---|
| 417 | Exit: | 
|---|
| 418 | return error; | 
|---|
| 419 | } | 
|---|
| 420 |  | 
|---|
| 421 |  | 
|---|
| 422 | FT_LOCAL_DEF( void ) | 
|---|
| 423 | tt_face_free_ps_names( TT_Face  face ) | 
|---|
| 424 | { | 
|---|
| 425 | FT_Memory      memory = face->root.memory; | 
|---|
| 426 | TT_Post_Names  names  = &face->postscript_names; | 
|---|
| 427 | FT_Fixed       format; | 
|---|
| 428 |  | 
|---|
| 429 |  | 
|---|
| 430 | if ( names->loaded ) | 
|---|
| 431 | { | 
|---|
| 432 | format = face->postscript.FormatType; | 
|---|
| 433 |  | 
|---|
| 434 | if ( format == 0x00020000L ) | 
|---|
| 435 | { | 
|---|
| 436 | TT_Post_20  table = &names->names.format_20; | 
|---|
| 437 | FT_UShort   n; | 
|---|
| 438 |  | 
|---|
| 439 |  | 
|---|
| 440 | FT_FREE( table->glyph_indices ); | 
|---|
| 441 | table->num_glyphs = 0; | 
|---|
| 442 |  | 
|---|
| 443 | for ( n = 0; n < table->num_names; n++ ) | 
|---|
| 444 | FT_FREE( table->glyph_names[n] ); | 
|---|
| 445 |  | 
|---|
| 446 | FT_FREE( table->glyph_names ); | 
|---|
| 447 | table->num_names = 0; | 
|---|
| 448 | } | 
|---|
| 449 | else if ( format == 0x00025000L ) | 
|---|
| 450 | { | 
|---|
| 451 | TT_Post_25  table = &names->names.format_25; | 
|---|
| 452 |  | 
|---|
| 453 |  | 
|---|
| 454 | FT_FREE( table->offsets ); | 
|---|
| 455 | table->num_glyphs = 0; | 
|---|
| 456 | } | 
|---|
| 457 | } | 
|---|
| 458 | names->loaded = 0; | 
|---|
| 459 | } | 
|---|
| 460 |  | 
|---|
| 461 |  | 
|---|
| 462 | /************************************************************************** | 
|---|
| 463 | * | 
|---|
| 464 | * @Function: | 
|---|
| 465 | *   tt_face_get_ps_name | 
|---|
| 466 | * | 
|---|
| 467 | * @Description: | 
|---|
| 468 | *   Get the PostScript glyph name of a glyph. | 
|---|
| 469 | * | 
|---|
| 470 | * @Input: | 
|---|
| 471 | *   face :: | 
|---|
| 472 | *     A handle to the parent face. | 
|---|
| 473 | * | 
|---|
| 474 | *   idx :: | 
|---|
| 475 | *     The glyph index. | 
|---|
| 476 | * | 
|---|
| 477 | * @InOut: | 
|---|
| 478 | *   PSname :: | 
|---|
| 479 | *     The address of a string pointer.  Undefined in case of | 
|---|
| 480 | *     error, otherwise it is a pointer to the glyph name. | 
|---|
| 481 | * | 
|---|
| 482 | *     You must not modify the returned string! | 
|---|
| 483 | * | 
|---|
| 484 | * @Output: | 
|---|
| 485 | *   FreeType error code.  0 means success. | 
|---|
| 486 | */ | 
|---|
| 487 | FT_LOCAL_DEF( FT_Error ) | 
|---|
| 488 | tt_face_get_ps_name( TT_Face      face, | 
|---|
| 489 | FT_UInt      idx, | 
|---|
| 490 | FT_String**  PSname ) | 
|---|
| 491 | { | 
|---|
| 492 | FT_Error       error; | 
|---|
| 493 | TT_Post_Names  names; | 
|---|
| 494 | FT_Fixed       format; | 
|---|
| 495 |  | 
|---|
| 496 | #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES | 
|---|
| 497 | FT_Service_PsCMaps  psnames; | 
|---|
| 498 | #endif | 
|---|
| 499 |  | 
|---|
| 500 |  | 
|---|
| 501 | if ( !face ) | 
|---|
| 502 | return FT_THROW( Invalid_Face_Handle ); | 
|---|
| 503 |  | 
|---|
| 504 | if ( idx >= (FT_UInt)face->max_profile.numGlyphs ) | 
|---|
| 505 | return FT_THROW( Invalid_Glyph_Index ); | 
|---|
| 506 |  | 
|---|
| 507 | #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES | 
|---|
| 508 | psnames = (FT_Service_PsCMaps)face->psnames; | 
|---|
| 509 | if ( !psnames ) | 
|---|
| 510 | return FT_THROW( Unimplemented_Feature ); | 
|---|
| 511 | #endif | 
|---|
| 512 |  | 
|---|
| 513 | names = &face->postscript_names; | 
|---|
| 514 |  | 
|---|
| 515 | /* `.notdef' by default */ | 
|---|
| 516 | *PSname = MAC_NAME( 0 ); | 
|---|
| 517 |  | 
|---|
| 518 | format = face->postscript.FormatType; | 
|---|
| 519 |  | 
|---|
| 520 | if ( format == 0x00010000L ) | 
|---|
| 521 | { | 
|---|
| 522 | if ( idx < 258 )                    /* paranoid checking */ | 
|---|
| 523 | *PSname = MAC_NAME( idx ); | 
|---|
| 524 | } | 
|---|
| 525 | else if ( format == 0x00020000L ) | 
|---|
| 526 | { | 
|---|
| 527 | TT_Post_20  table = &names->names.format_20; | 
|---|
| 528 |  | 
|---|
| 529 |  | 
|---|
| 530 | if ( !names->loaded ) | 
|---|
| 531 | { | 
|---|
| 532 | error = load_post_names( face ); | 
|---|
| 533 | if ( error ) | 
|---|
| 534 | goto End; | 
|---|
| 535 | } | 
|---|
| 536 |  | 
|---|
| 537 | if ( idx < (FT_UInt)table->num_glyphs ) | 
|---|
| 538 | { | 
|---|
| 539 | FT_UShort  name_index = table->glyph_indices[idx]; | 
|---|
| 540 |  | 
|---|
| 541 |  | 
|---|
| 542 | if ( name_index < 258 ) | 
|---|
| 543 | *PSname = MAC_NAME( name_index ); | 
|---|
| 544 | else | 
|---|
| 545 | *PSname = (FT_String*)table->glyph_names[name_index - 258]; | 
|---|
| 546 | } | 
|---|
| 547 | } | 
|---|
| 548 | else if ( format == 0x00025000L ) | 
|---|
| 549 | { | 
|---|
| 550 | TT_Post_25  table = &names->names.format_25; | 
|---|
| 551 |  | 
|---|
| 552 |  | 
|---|
| 553 | if ( !names->loaded ) | 
|---|
| 554 | { | 
|---|
| 555 | error = load_post_names( face ); | 
|---|
| 556 | if ( error ) | 
|---|
| 557 | goto End; | 
|---|
| 558 | } | 
|---|
| 559 |  | 
|---|
| 560 | if ( idx < (FT_UInt)table->num_glyphs )    /* paranoid checking */ | 
|---|
| 561 | *PSname = MAC_NAME( (FT_Int)idx + table->offsets[idx] ); | 
|---|
| 562 | } | 
|---|
| 563 |  | 
|---|
| 564 | /* nothing to do for format == 0x00030000L */ | 
|---|
| 565 |  | 
|---|
| 566 | End: | 
|---|
| 567 | return FT_Err_Ok; | 
|---|
| 568 | } | 
|---|
| 569 |  | 
|---|
| 570 | #else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ | 
|---|
| 571 |  | 
|---|
| 572 | /* ANSI C doesn't like empty source files */ | 
|---|
| 573 | typedef int  _tt_post_dummy; | 
|---|
| 574 |  | 
|---|
| 575 | #endif /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ | 
|---|
| 576 |  | 
|---|
| 577 |  | 
|---|
| 578 | /* END */ | 
|---|
| 579 |  | 
|---|