1 /***************************************************************************/
5 /* Postcript name table processing for TrueType and OpenType fonts */
8 /* Copyright 1996-2001 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_STREAM_H
30 #include FT_TRUETYPE_TAGS_H
36 /*************************************************************************/
38 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
39 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
40 /* messages during execution. */
43 #define FT_COMPONENT trace_ttpost
46 /* If this configuration macro is defined, we rely on the `PSNames' */
47 /* module to grab the glyph names. */
49 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
52 #include <freetype/internal/psnames.h>
54 #define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) )
57 #else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
60 /* Otherwise, we ignore the `PSNames' module, and provide our own */
61 /* table of Mac names. Thus, it is possible to build a version of */
62 /* FreeType without the Type 1 driver & PSNames module. */
64 #define MAC_NAME( x ) TT_Post_Default_Names[x]
66 /* the 258 default Mac PS glyph names */
68 FT_String* TT_Post_Default_Names[258] =
71 ".notdef", ".null", "CR", "space", "exclam",
72 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
74 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
75 "comma", "hyphen", "period", "slash", "zero",
77 "one", "two", "three", "four", "five",
78 "six", "seven", "eight", "nine", "colon",
80 "semicolon", "less", "equal", "greater", "question",
81 "at", "A", "B", "C", "D",
83 "E", "F", "G", "H", "I",
84 "J", "K", "L", "M", "N",
86 "O", "P", "Q", "R", "S",
87 "T", "U", "V", "W", "X",
89 "Y", "Z", "bracketleft", "backslash", "bracketright",
90 "asciicircum", "underscore", "grave", "a", "b",
92 "c", "d", "e", "f", "g",
93 "h", "i", "j", "k", "l",
95 "m", "n", "o", "p", "q",
96 "r", "s", "t", "u", "v",
98 "w", "x", "y", "z", "braceleft",
99 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
101 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
102 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
104 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
105 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
107 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
108 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
110 "dagger", "degree", "cent", "sterling", "section",
111 "bullet", "paragraph", "germandbls", "registered", "copyright",
113 "trademark", "acute", "dieresis", "notequal", "AE",
114 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
116 "yen", "mu", "partialdiff", "summation", "product",
117 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
119 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
120 "radical", "florin", "approxequal", "Delta", "guillemotleft",
122 "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
123 "Otilde", "OE", "oe", "endash", "emdash",
125 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
126 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
128 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
129 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
131 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
132 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
134 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
135 "dotlessi", "circumflex", "tilde", "macron", "breve",
137 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
138 "caron", "Lslash", "lslash", "Scaron", "scaron",
140 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
141 "Yacute", "yacute", "Thorn", "thorn", "minus",
143 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
144 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
146 "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
147 "Ccaron", "ccaron", "dmacron",
151 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
155 Load_Format_20( TT_Face face,
158 FT_Memory memory = stream->memory;
164 FT_UShort* glyph_indices = 0;
165 FT_Char** name_strings = 0;
168 if ( READ_UShort( num_glyphs ) )
171 /* UNDOCUMENTED! The number of glyphs in this table can be smaller */
172 /* than the value in the maxp table (cf. cyberbit.ttf). */
174 /* There already exist fonts which have more than 32768 glyph names */
175 /* in this table, so the test for this threshold has been dropped. */
177 if ( num_glyphs > face->root.num_glyphs )
179 error = SFNT_Err_Invalid_File_Format;
183 /* load the indices */
188 if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, FT_UShort ) ||
189 ACCESS_Frame( num_glyphs * 2L ) )
192 for ( n = 0; n < num_glyphs; n++ )
193 glyph_indices[n] = GET_UShort();
198 /* compute number of names stored in table */
205 for ( n = 0; n < num_glyphs; n++ )
210 index = glyph_indices[n];
214 if ( index > num_names )
215 num_names = (FT_UShort)index;
220 /* now load the name strings */
225 if ( ALLOC_ARRAY( name_strings, num_names, FT_Char* ) )
228 for ( n = 0; n < num_names; n++ )
233 if ( READ_Byte ( len ) ||
234 ALLOC_ARRAY( name_strings[n], len + 1, FT_Char ) ||
235 FILE_Read ( name_strings[n], len ) )
238 name_strings[n][len] = '\0';
242 /* all right, set table fields and exit successfuly */
244 TT_Post_20* table = &face->postscript_names.names.format_20;
247 table->num_glyphs = (FT_UShort)num_glyphs;
248 table->num_names = (FT_UShort)num_names;
249 table->glyph_indices = glyph_indices;
250 table->glyph_names = name_strings;
260 for ( n = 0; n < num_names; n++ )
261 FREE( name_strings[n] );
265 FREE( name_strings );
266 FREE( glyph_indices );
274 Load_Format_25( TT_Face face,
277 FT_Memory memory = stream->memory;
281 FT_Char* offset_table = 0;
284 /* UNDOCUMENTED! This value appears only in the Apple TT specs. */
285 if ( READ_UShort( num_glyphs ) )
288 /* check the number of glyphs */
289 if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 )
291 error = SFNT_Err_Invalid_File_Format;
295 if ( ALLOC ( offset_table, num_glyphs ) ||
296 FILE_Read( offset_table, num_glyphs ) )
299 /* now check the offset table */
304 for ( n = 0; n < num_glyphs; n++ )
306 FT_Long index = (FT_Long)n + offset_table[n];
309 if ( index < 0 || index > num_glyphs )
311 error = SFNT_Err_Invalid_File_Format;
317 /* OK, set table fields and exit successfuly */
319 TT_Post_25* table = &face->postscript_names.names.format_25;
322 table->num_glyphs = (FT_UShort)num_glyphs;
323 table->offsets = offset_table;
329 FREE( offset_table );
337 Load_Post_Names( TT_Face face )
344 /* get a stream for the face's resource */
345 stream = face->root.stream;
347 /* seek to the beginning of the PS names table */
348 error = face->goto_table( face, TTAG_post, stream, 0 );
352 format = face->postscript.FormatType;
354 /* go to beginning of subtable */
355 if ( FILE_Skip( 32 ) )
358 /* now read postscript table */
362 error = Load_Format_20( face, stream );
366 error = Load_Format_25( face, stream );
370 error = SFNT_Err_Invalid_File_Format;
373 face->postscript_names.loaded = 1;
381 TT_Free_Post_Names( TT_Face face )
383 FT_Memory memory = face->root.memory;
384 TT_Post_Names* names = &face->postscript_names;
389 switch ( face->postscript.FormatType )
393 TT_Post_20* table = &names->names.format_20;
397 FREE( table->glyph_indices );
398 table->num_glyphs = 0;
400 for ( n = 0; n < table->num_names; n++ )
401 FREE( table->glyph_names[n] );
403 FREE( table->glyph_names );
404 table->num_names = 0;
410 TT_Post_25* table = &names->names.format_25;
413 FREE( table->offsets );
414 table->num_glyphs = 0;
423 /*************************************************************************/
429 /* Gets the PostScript glyph name of a glyph. */
432 /* face :: A handle to the parent face. */
434 /* index :: The glyph index. */
436 /* PSname :: The address of a string pointer. Will be NULL in case */
437 /* of error, otherwise it is a pointer to the glyph name. */
439 /* You must not modify the returned string! */
442 /* FreeType error code. 0 means success. */
444 FT_LOCAL_DEF FT_Error
445 TT_Get_PS_Name( TT_Face face,
450 TT_Post_Names* names;
452 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
453 PSNames_Interface* psnames;
458 return SFNT_Err_Invalid_Face_Handle;
460 if ( index >= (FT_UInt)face->root.num_glyphs )
461 return SFNT_Err_Invalid_Glyph_Index;
463 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
464 psnames = (PSNames_Interface*)face->psnames;
466 return SFNT_Err_Unimplemented_Feature;
469 names = &face->postscript_names;
471 /* `.notdef' by default */
472 *PSname = MAC_NAME( 0 );
474 switch ( face->postscript.FormatType )
477 if ( index < 258 ) /* paranoid checking */
478 *PSname = MAC_NAME( index );
483 TT_Post_20* table = &names->names.format_20;
486 if ( !names->loaded )
488 error = Load_Post_Names( face );
493 if ( index < (FT_UInt)table->num_glyphs )
495 FT_UShort name_index = table->glyph_indices[index];
498 if ( name_index < 258 )
499 *PSname = MAC_NAME( name_index );
501 *PSname = (FT_String*)table->glyph_names[name_index - 258];
508 TT_Post_25* table = &names->names.format_25;
511 if ( !names->loaded )
513 error = Load_Post_Names( face );
518 if ( index < (FT_UInt)table->num_glyphs ) /* paranoid checking */
520 index += table->offsets[index];
521 *PSname = MAC_NAME( index );
527 break; /* nothing to do */