1 /***************************************************************************/
5 /* Postcript name table processing for TrueType and OpenType fonts */
8 /* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 by */
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
17 /***************************************************************************/
19 /*************************************************************************/
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 */
25 /*************************************************************************/
29 #include FT_INTERNAL_DEBUG_H
30 #include FT_INTERNAL_STREAM_H
31 #include FT_TRUETYPE_TAGS_H
37 /*************************************************************************/
39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
40 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
41 /* messages during execution. */
44 #define FT_COMPONENT trace_ttpost
47 /* If this configuration macro is defined, we rely on the `PSNames' */
48 /* module to grab the glyph names. */
50 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
53 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
55 #define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) )
58 #else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
61 /* Otherwise, we ignore the `PSNames' module, and provide our own */
62 /* table of Mac names. Thus, it is possible to build a version of */
63 /* FreeType without the Type 1 driver & PSNames module. */
65 #define MAC_NAME( x ) ( (FT_String*)tt_post_default_names[x] )
67 /* the 258 default Mac PS glyph names */
69 static const FT_String* const tt_post_default_names[258] =
72 ".notdef", ".null", "CR", "space", "exclam",
73 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
75 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
76 "comma", "hyphen", "period", "slash", "zero",
78 "one", "two", "three", "four", "five",
79 "six", "seven", "eight", "nine", "colon",
81 "semicolon", "less", "equal", "greater", "question",
82 "at", "A", "B", "C", "D",
84 "E", "F", "G", "H", "I",
85 "J", "K", "L", "M", "N",
87 "O", "P", "Q", "R", "S",
88 "T", "U", "V", "W", "X",
90 "Y", "Z", "bracketleft", "backslash", "bracketright",
91 "asciicircum", "underscore", "grave", "a", "b",
93 "c", "d", "e", "f", "g",
94 "h", "i", "j", "k", "l",
96 "m", "n", "o", "p", "q",
97 "r", "s", "t", "u", "v",
99 "w", "x", "y", "z", "braceleft",
100 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
102 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
103 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
105 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
106 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
108 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
109 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
111 "dagger", "degree", "cent", "sterling", "section",
112 "bullet", "paragraph", "germandbls", "registered", "copyright",
114 "trademark", "acute", "dieresis", "notequal", "AE",
115 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
117 "yen", "mu", "partialdiff", "summation", "product",
118 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
120 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
121 "radical", "florin", "approxequal", "Delta", "guillemotleft",
123 "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
124 "Otilde", "OE", "oe", "endash", "emdash",
126 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
127 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
129 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
130 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
132 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
133 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
135 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
136 "dotlessi", "circumflex", "tilde", "macron", "breve",
138 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
139 "caron", "Lslash", "lslash", "Scaron", "scaron",
141 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
142 "Yacute", "yacute", "Thorn", "thorn", "minus",
144 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
145 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
147 "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
148 "Ccaron", "ccaron", "dmacron",
152 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
156 load_format_20( TT_Face face,
160 FT_Memory memory = stream->memory;
166 FT_UShort* glyph_indices = 0;
167 FT_Char** name_strings = 0;
170 if ( FT_READ_USHORT( num_glyphs ) )
173 /* UNDOCUMENTED! The number of glyphs in this table can be smaller */
174 /* than the value in the maxp table (cf. cyberbit.ttf). */
176 /* There already exist fonts which have more than 32768 glyph names */
177 /* in this table, so the test for this threshold has been dropped. */
179 if ( num_glyphs > face->max_profile.numGlyphs )
181 error = SFNT_Err_Invalid_File_Format;
185 /* load the indices */
190 if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) ||
191 FT_FRAME_ENTER( num_glyphs * 2L ) )
194 for ( n = 0; n < num_glyphs; n++ )
195 glyph_indices[n] = FT_GET_USHORT();
200 /* compute number of names stored in table */
207 for ( n = 0; n < num_glyphs; n++ )
212 idx = glyph_indices[n];
216 if ( idx > num_names )
217 num_names = (FT_UShort)idx;
222 /* now load the name strings */
227 if ( FT_NEW_ARRAY( name_strings, num_names ) )
230 for ( n = 0; n < num_names; n++ )
235 if ( FT_STREAM_POS() >= post_limit )
239 FT_TRACE6(( "load_format_20: %d byte left in post table\n",
240 post_limit - FT_STREAM_POS() ));
242 if ( FT_READ_BYTE( len ) )
246 if ( (FT_Int)len > post_limit ||
247 FT_STREAM_POS() > post_limit - (FT_Int)len )
249 FT_ERROR(( "load_format_20:"
250 " exceeding string length (%d),"
251 " truncating at end of post table (%d byte left)\n",
252 len, post_limit - FT_STREAM_POS() ));
253 len = FT_MAX( 0, post_limit - FT_STREAM_POS() );
256 if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
257 FT_STREAM_READ( name_strings[n], len ) )
260 name_strings[n][len] = '\0';
265 FT_ERROR(( "load_format_20:"
266 " all entries in post table are already parsed,"
267 " using NULL names for gid %d - %d\n",
269 for ( ; n < num_names; n++ )
270 if ( FT_NEW_ARRAY( name_strings[n], 1 ) )
273 name_strings[n][0] = '\0';
277 /* all right, set table fields and exit successfully */
279 TT_Post_20 table = &face->postscript_names.names.format_20;
282 table->num_glyphs = (FT_UShort)num_glyphs;
283 table->num_names = (FT_UShort)num_names;
284 table->glyph_indices = glyph_indices;
285 table->glyph_names = name_strings;
294 for ( n = 0; n < num_names; n++ )
295 FT_FREE( name_strings[n] );
299 FT_FREE( name_strings );
300 FT_FREE( glyph_indices );
308 load_format_25( TT_Face face,
312 FT_Memory memory = stream->memory;
316 FT_Char* offset_table = 0;
318 FT_UNUSED( post_limit );
321 /* UNDOCUMENTED! This value appears only in the Apple TT specs. */
322 if ( FT_READ_USHORT( num_glyphs ) )
325 /* check the number of glyphs */
326 if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 )
328 error = SFNT_Err_Invalid_File_Format;
332 if ( FT_NEW_ARRAY( offset_table, num_glyphs ) ||
333 FT_STREAM_READ( offset_table, num_glyphs ) )
336 /* now check the offset table */
341 for ( n = 0; n < num_glyphs; n++ )
343 FT_Long idx = (FT_Long)n + offset_table[n];
346 if ( idx < 0 || idx > num_glyphs )
348 error = SFNT_Err_Invalid_File_Format;
354 /* OK, set table fields and exit successfully */
356 TT_Post_25 table = &face->postscript_names.names.format_25;
359 table->num_glyphs = (FT_UShort)num_glyphs;
360 table->offsets = offset_table;
366 FT_FREE( offset_table );
374 load_post_names( TT_Face face )
383 /* get a stream for the face's resource */
384 stream = face->root.stream;
386 /* seek to the beginning of the PS names table */
387 error = face->goto_table( face, TTAG_post, stream, &post_len );
391 post_limit = FT_STREAM_POS() + post_len;
393 format = face->postscript.FormatType;
395 /* go to beginning of subtable */
396 if ( FT_STREAM_SKIP( 32 ) )
399 /* now read postscript table */
400 if ( format == 0x00020000L )
401 error = load_format_20( face, stream, post_limit );
402 else if ( format == 0x00028000L )
403 error = load_format_25( face, stream, post_limit );
405 error = SFNT_Err_Invalid_File_Format;
407 face->postscript_names.loaded = 1;
415 tt_face_free_ps_names( TT_Face face )
417 FT_Memory memory = face->root.memory;
418 TT_Post_Names names = &face->postscript_names;
424 format = face->postscript.FormatType;
426 if ( format == 0x00020000L )
428 TT_Post_20 table = &names->names.format_20;
432 FT_FREE( table->glyph_indices );
433 table->num_glyphs = 0;
435 for ( n = 0; n < table->num_names; n++ )
436 FT_FREE( table->glyph_names[n] );
438 FT_FREE( table->glyph_names );
439 table->num_names = 0;
441 else if ( format == 0x00028000L )
443 TT_Post_25 table = &names->names.format_25;
446 FT_FREE( table->offsets );
447 table->num_glyphs = 0;
454 /*************************************************************************/
457 /* tt_face_get_ps_name */
460 /* Get the PostScript glyph name of a glyph. */
463 /* face :: A handle to the parent face. */
465 /* idx :: The glyph index. */
468 /* PSname :: The address of a string pointer. Will be NULL in case */
469 /* of error, otherwise it is a pointer to the glyph name. */
471 /* You must not modify the returned string! */
474 /* FreeType error code. 0 means success. */
476 FT_LOCAL_DEF( FT_Error )
477 tt_face_get_ps_name( TT_Face face,
485 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
486 FT_Service_PsCMaps psnames;
491 return SFNT_Err_Invalid_Face_Handle;
493 if ( idx >= (FT_UInt)face->max_profile.numGlyphs )
494 return SFNT_Err_Invalid_Glyph_Index;
496 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
497 psnames = (FT_Service_PsCMaps)face->psnames;
499 return SFNT_Err_Unimplemented_Feature;
502 names = &face->postscript_names;
504 /* `.notdef' by default */
505 *PSname = MAC_NAME( 0 );
507 format = face->postscript.FormatType;
509 if ( format == 0x00010000L )
511 if ( idx < 258 ) /* paranoid checking */
512 *PSname = MAC_NAME( idx );
514 else if ( format == 0x00020000L )
516 TT_Post_20 table = &names->names.format_20;
519 if ( !names->loaded )
521 error = load_post_names( face );
526 if ( idx < (FT_UInt)table->num_glyphs )
528 FT_UShort name_index = table->glyph_indices[idx];
531 if ( name_index < 258 )
532 *PSname = MAC_NAME( name_index );
534 *PSname = (FT_String*)table->glyph_names[name_index - 258];
537 else if ( format == 0x00028000L )
539 TT_Post_25 table = &names->names.format_25;
542 if ( !names->loaded )
544 error = load_post_names( face );
549 if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */
551 idx += table->offsets[idx];
552 *PSname = MAC_NAME( idx );
556 /* nothing to do for format == 0x00030000L */