1 /***************************************************************************/
5 /* Postcript name table processing for TrueType and OpenType fonts */
8 /* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2009 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 FT_SERVICE_POSTSCRIPT_CMAPS_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 ) ( (FT_String*)tt_post_default_names[x] )
66 /* the 258 default Mac PS glyph names */
68 static const FT_String
* const 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 ( FT_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
->max_profile
.numGlyphs
)
179 error
= SFNT_Err_Invalid_File_Format
;
183 /* load the indices */
188 if ( FT_NEW_ARRAY ( glyph_indices
, num_glyphs
) ||
189 FT_FRAME_ENTER( num_glyphs
* 2L ) )
192 for ( n
= 0; n
< num_glyphs
; n
++ )
193 glyph_indices
[n
] = FT_GET_USHORT();
198 /* compute number of names stored in table */
205 for ( n
= 0; n
< num_glyphs
; n
++ )
210 idx
= glyph_indices
[n
];
214 if ( idx
> num_names
)
215 num_names
= (FT_UShort
)idx
;
220 /* now load the name strings */
225 if ( FT_NEW_ARRAY( name_strings
, num_names
) )
228 for ( n
= 0; n
< num_names
; n
++ )
233 if ( FT_READ_BYTE ( len
) ||
234 FT_NEW_ARRAY( name_strings
[n
], len
+ 1 ) ||
235 FT_STREAM_READ ( name_strings
[n
], len
) )
238 name_strings
[n
][len
] = '\0';
242 /* all right, set table fields and exit successfully */
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
;
259 for ( n
= 0; n
< num_names
; n
++ )
260 FT_FREE( name_strings
[n
] );
264 FT_FREE( name_strings
);
265 FT_FREE( glyph_indices
);
273 load_format_25( TT_Face face
,
276 FT_Memory memory
= stream
->memory
;
280 FT_Char
* offset_table
= 0;
283 /* UNDOCUMENTED! This value appears only in the Apple TT specs. */
284 if ( FT_READ_USHORT( num_glyphs
) )
287 /* check the number of glyphs */
288 if ( num_glyphs
> face
->max_profile
.numGlyphs
|| num_glyphs
> 258 )
290 error
= SFNT_Err_Invalid_File_Format
;
294 if ( FT_NEW_ARRAY( offset_table
, num_glyphs
) ||
295 FT_STREAM_READ( offset_table
, num_glyphs
) )
298 /* now check the offset table */
303 for ( n
= 0; n
< num_glyphs
; n
++ )
305 FT_Long idx
= (FT_Long
)n
+ offset_table
[n
];
308 if ( idx
< 0 || idx
> num_glyphs
)
310 error
= SFNT_Err_Invalid_File_Format
;
316 /* OK, set table fields and exit successfully */
318 TT_Post_25 table
= &face
->postscript_names
.names
.format_25
;
321 table
->num_glyphs
= (FT_UShort
)num_glyphs
;
322 table
->offsets
= offset_table
;
328 FT_FREE( offset_table
);
336 load_post_names( TT_Face face
)
343 /* get a stream for the face's resource */
344 stream
= face
->root
.stream
;
346 /* seek to the beginning of the PS names table */
347 error
= face
->goto_table( face
, TTAG_post
, stream
, 0 );
351 format
= face
->postscript
.FormatType
;
353 /* go to beginning of subtable */
354 if ( FT_STREAM_SKIP( 32 ) )
357 /* now read postscript table */
358 if ( format
== 0x00020000L
)
359 error
= load_format_20( face
, stream
);
360 else if ( format
== 0x00028000L
)
361 error
= load_format_25( face
, stream
);
363 error
= SFNT_Err_Invalid_File_Format
;
365 face
->postscript_names
.loaded
= 1;
373 tt_face_free_ps_names( TT_Face face
)
375 FT_Memory memory
= face
->root
.memory
;
376 TT_Post_Names names
= &face
->postscript_names
;
382 format
= face
->postscript
.FormatType
;
384 if ( format
== 0x00020000L
)
386 TT_Post_20 table
= &names
->names
.format_20
;
390 FT_FREE( table
->glyph_indices
);
391 table
->num_glyphs
= 0;
393 for ( n
= 0; n
< table
->num_names
; n
++ )
394 FT_FREE( table
->glyph_names
[n
] );
396 FT_FREE( table
->glyph_names
);
397 table
->num_names
= 0;
399 else if ( format
== 0x00028000L
)
401 TT_Post_25 table
= &names
->names
.format_25
;
404 FT_FREE( table
->offsets
);
405 table
->num_glyphs
= 0;
412 /*************************************************************************/
415 /* tt_face_get_ps_name */
418 /* Get the PostScript glyph name of a glyph. */
421 /* face :: A handle to the parent face. */
423 /* idx :: The glyph index. */
426 /* PSname :: The address of a string pointer. Will be NULL in case */
427 /* of error, otherwise it is a pointer to the glyph name. */
429 /* You must not modify the returned string! */
432 /* FreeType error code. 0 means success. */
434 FT_LOCAL_DEF( FT_Error
)
435 tt_face_get_ps_name( TT_Face face
,
443 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
444 FT_Service_PsCMaps psnames
;
449 return SFNT_Err_Invalid_Face_Handle
;
451 if ( idx
>= (FT_UInt
)face
->max_profile
.numGlyphs
)
452 return SFNT_Err_Invalid_Glyph_Index
;
454 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
455 psnames
= (FT_Service_PsCMaps
)face
->psnames
;
457 return SFNT_Err_Unimplemented_Feature
;
460 names
= &face
->postscript_names
;
462 /* `.notdef' by default */
463 *PSname
= MAC_NAME( 0 );
465 format
= face
->postscript
.FormatType
;
467 if ( format
== 0x00010000L
)
469 if ( idx
< 258 ) /* paranoid checking */
470 *PSname
= MAC_NAME( idx
);
472 else if ( format
== 0x00020000L
)
474 TT_Post_20 table
= &names
->names
.format_20
;
477 if ( !names
->loaded
)
479 error
= load_post_names( face
);
484 if ( idx
< (FT_UInt
)table
->num_glyphs
)
486 FT_UShort name_index
= table
->glyph_indices
[idx
];
489 if ( name_index
< 258 )
490 *PSname
= MAC_NAME( name_index
);
492 *PSname
= (FT_String
*)table
->glyph_names
[name_index
- 258];
495 else if ( format
== 0x00028000L
)
497 TT_Post_25 table
= &names
->names
.format_25
;
500 if ( !names
->loaded
)
502 error
= load_post_names( face
);
507 if ( idx
< (FT_UInt
)table
->num_glyphs
) /* paranoid checking */
509 idx
+= table
->offsets
[idx
];
510 *PSname
= MAC_NAME( idx
);
514 /* nothing to do for format == 0x00030000L */