1 /***************************************************************************/
5 /* Postcript name table processing for TrueType and OpenType fonts */
8 /* Copyright 1996-2001, 2002 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
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_INTERNAL_POSTSCRIPT_NAMES_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 ) TT_Post_Default_Names[x]
67 /* the 258 default Mac PS glyph names */
69 FT_String
* 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
,
159 FT_Memory memory
= stream
->memory
;
165 FT_UShort
* glyph_indices
= 0;
166 FT_Char
** name_strings
= 0;
169 if ( FT_READ_USHORT( num_glyphs
) )
172 /* UNDOCUMENTED! The number of glyphs in this table can be smaller */
173 /* than the value in the maxp table (cf. cyberbit.ttf). */
175 /* There already exist fonts which have more than 32768 glyph names */
176 /* in this table, so the test for this threshold has been dropped. */
178 if ( num_glyphs
> face
->root
.num_glyphs
)
180 error
= SFNT_Err_Invalid_File_Format
;
184 /* load the indices */
189 if ( FT_NEW_ARRAY ( glyph_indices
, num_glyphs
) ||
190 FT_FRAME_ENTER( num_glyphs
* 2L ) )
193 for ( n
= 0; n
< num_glyphs
; n
++ )
194 glyph_indices
[n
] = FT_GET_USHORT();
199 /* compute number of names stored in table */
206 for ( n
= 0; n
< num_glyphs
; n
++ )
211 idx
= glyph_indices
[n
];
215 if ( idx
> num_names
)
216 num_names
= (FT_UShort
)idx
;
221 /* now load the name strings */
226 if ( FT_NEW_ARRAY( name_strings
, num_names
) )
229 for ( n
= 0; n
< num_names
; n
++ )
234 if ( FT_READ_BYTE ( len
) ||
235 FT_NEW_ARRAY( name_strings
[n
], len
+ 1 ) ||
236 FT_STREAM_READ ( name_strings
[n
], len
) )
239 name_strings
[n
][len
] = '\0';
243 /* all right, set table fields and exit successfuly */
245 TT_Post_20 table
= &face
->postscript_names
.names
.format_20
;
248 table
->num_glyphs
= (FT_UShort
)num_glyphs
;
249 table
->num_names
= (FT_UShort
)num_names
;
250 table
->glyph_indices
= glyph_indices
;
251 table
->glyph_names
= name_strings
;
260 for ( n
= 0; n
< num_names
; n
++ )
261 FT_FREE( name_strings
[n
] );
265 FT_FREE( name_strings
);
266 FT_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 ( FT_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 ( FT_ALLOC( offset_table
, num_glyphs
) ||
296 FT_STREAM_READ( offset_table
, num_glyphs
) )
299 /* now check the offset table */
304 for ( n
= 0; n
< num_glyphs
; n
++ )
306 FT_Long idx
= (FT_Long
)n
+ offset_table
[n
];
309 if ( idx
< 0 || idx
> 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 FT_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 ( FT_STREAM_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 FT_FREE( table
->glyph_indices
);
398 table
->num_glyphs
= 0;
400 for ( n
= 0; n
< table
->num_names
; n
++ )
401 FT_FREE( table
->glyph_names
[n
] );
403 FT_FREE( table
->glyph_names
);
404 table
->num_names
= 0;
410 TT_Post_25 table
= &names
->names
.format_25
;
413 FT_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 /* idx :: 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
,
452 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
453 PSNames_Service psnames
;
458 return SFNT_Err_Invalid_Face_Handle
;
460 if ( idx
>= (FT_UInt
)face
->root
.num_glyphs
)
461 return SFNT_Err_Invalid_Glyph_Index
;
463 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
464 psnames
= (PSNames_Service
)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 ( idx
< 258 ) /* paranoid checking */
478 *PSname
= MAC_NAME( idx
);
483 TT_Post_20 table
= &names
->names
.format_20
;
486 if ( !names
->loaded
)
488 error
= Load_Post_Names( face
);
493 if ( idx
< (FT_UInt
)table
->num_glyphs
)
495 FT_UShort name_index
= table
->glyph_indices
[idx
];
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 ( idx
< (FT_UInt
)table
->num_glyphs
) /* paranoid checking */
520 idx
+= table
->offsets
[idx
];
521 *PSname
= MAC_NAME( idx
);
527 break; /* nothing to do */