1 /***************************************************************************/
5 /* Postcript name table processing for TrueType and OpenType fonts */
8 /* Copyright 1996-2000 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 /*************************************************************************/
28 #include <freetype/internal/ftstream.h>
29 #include <freetype/internal/tterrors.h>
30 #include <freetype/tttags.h>
33 #ifdef FT_FLAT_COMPILE
40 #include <sfnt/ttpost.h>
41 #include <sfnt/ttload.h>
46 /*************************************************************************/
48 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
49 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
50 /* messages during execution. */
53 #define FT_COMPONENT trace_ttpost
56 /* If this configuration macro is defined, we rely on the `PSNames' */
57 /* module to grab the glyph names. */
59 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
62 #include <freetype/internal/psnames.h>
64 #define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) )
67 #else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
70 /* Otherwise, we ignore the `PSNames' module, and provide our own */
71 /* table of Mac names. Thus, it is possible to build a version of */
72 /* FreeType without the Type 1 driver & PSNames module. */
74 #define MAC_NAME( x ) TT_Post_Default_Names[x]
76 /* the 258 default Mac PS glyph names */
78 FT_String
* TT_Post_Default_Names
[258] =
81 ".notdef", ".null", "CR", "space", "exclam",
82 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
84 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
85 "comma", "hyphen", "period", "slash", "zero",
87 "one", "two", "three", "four", "five",
88 "six", "seven", "eight", "nine", "colon",
90 "semicolon", "less", "equal", "greater", "question",
91 "at", "A", "B", "C", "D",
93 "E", "F", "G", "H", "I",
94 "J", "K", "L", "M", "N",
96 "O", "P", "Q", "R", "S",
97 "T", "U", "V", "W", "X",
99 "Y", "Z", "bracketleft", "backslash", "bracketright",
100 "asciicircum", "underscore", "grave", "a", "b",
102 "c", "d", "e", "f", "g",
103 "h", "i", "j", "k", "l",
105 "m", "n", "o", "p", "q",
106 "r", "s", "t", "u", "v",
108 "w", "x", "y", "z", "braceleft",
109 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
111 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
112 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
114 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
115 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
117 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
118 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
120 "dagger", "degree", "cent", "sterling", "section",
121 "bullet", "paragraph", "germandbls", "registered", "copyright",
123 "trademark", "acute", "dieresis", "notequal", "AE",
124 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
126 "yen", "mu", "partialdiff", "summation", "product",
127 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
129 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
130 "radical", "florin", "approxequal", "Delta", "guillemotleft",
132 "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
133 "Otilde", "OE", "oe", "endash", "emdash",
135 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
136 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
138 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
139 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
141 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
142 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
144 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
145 "dotlessi", "circumflex", "tilde", "macron", "breve",
147 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
148 "caron", "Lslash", "lslash", "Scaron", "scaron",
150 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
151 "Yacute", "yacute", "Thorn", "thorn", "minus",
153 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
154 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
156 "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
157 "Ccaron", "ccaron", "dmacron",
161 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
165 FT_Error
Load_Format_20( TT_Face face
,
168 FT_Memory memory
= stream
->memory
;
174 FT_UShort
* glyph_indices
= 0;
175 FT_Char
** name_strings
= 0;
178 if ( READ_UShort( num_glyphs
) )
181 /* UNDOCUMENTED! The number of glyphs in this table can be smaller */
182 /* than the value in the maxp table (cf. cyberbit.ttf). */
184 /* There already exist fonts which have more than 32768 glyph names */
185 /* in this table, so the test for this threshold has been dropped. */
187 if ( num_glyphs
> face
->root
.num_glyphs
)
189 error
= TT_Err_Invalid_File_Format
;
193 /* load the indices */
198 if ( ALLOC_ARRAY ( glyph_indices
, num_glyphs
, FT_UShort
) ||
199 ACCESS_Frame( num_glyphs
* 2L ) )
202 for ( n
= 0; n
< num_glyphs
; n
++ )
203 glyph_indices
[n
] = GET_UShort();
208 /* compute number of names stored in table */
215 for ( n
= 0; n
< num_glyphs
; n
++ )
220 index
= glyph_indices
[n
];
224 if ( index
> num_names
)
230 /* now load the name strings */
235 if ( ALLOC_ARRAY( name_strings
, num_names
, FT_Char
* ) )
238 for ( n
= 0; n
< num_names
; n
++ )
243 if ( READ_Byte ( len
) ||
244 ALLOC_ARRAY( name_strings
[n
], len
+ 1, FT_Char
) ||
245 FILE_Read ( name_strings
[n
], len
) )
248 name_strings
[n
][len
] = '\0';
252 /* all right, set table fields and exit successfuly */
254 TT_Post_20
* table
= &face
->postscript_names
.names
.format_20
;
257 table
->num_glyphs
= num_glyphs
;
258 table
->num_names
= num_names
;
259 table
->glyph_indices
= glyph_indices
;
260 table
->glyph_names
= name_strings
;
270 for ( n
= 0; n
< num_names
; n
++ )
271 FREE( name_strings
[n
] );
275 FREE( name_strings
);
276 FREE( glyph_indices
);
284 FT_Error
Load_Format_25( TT_Face face
,
287 FT_Memory memory
= stream
->memory
;
291 FT_Char
* offset_table
= 0;
294 /* UNDOCUMENTED! This value appears only in the Apple TT specs. */
295 if ( READ_UShort( num_glyphs
) )
298 /* check the number of glyphs */
299 if ( num_glyphs
> face
->root
.num_glyphs
|| num_glyphs
> 258 )
301 error
= TT_Err_Invalid_File_Format
;
305 if ( ALLOC ( offset_table
, num_glyphs
) ||
306 FILE_Read( offset_table
, num_glyphs
) )
309 /* now check the offset table */
314 for ( n
= 0; n
< num_glyphs
; n
++ )
316 FT_Long index
= (FT_Long
)n
+ offset_table
[n
];
319 if ( index
< 0 || index
> num_glyphs
)
321 error
= TT_Err_Invalid_File_Format
;
327 /* OK, set table fields and exit successfuly */
329 TT_Post_25
* table
= &face
->postscript_names
.names
.format_25
;
332 table
->num_glyphs
= num_glyphs
;
333 table
->offsets
= offset_table
;
339 FREE( offset_table
);
347 FT_Error
Load_Post_Names( TT_Face face
)
352 /* get a stream for the face's resource */
353 stream
= face
->root
.stream
;
355 /* seek to the beginning of the PS names table */
356 error
= face
->goto_table( face
, TTAG_post
, stream
, 0 );
360 /* now read postscript table */
361 switch ( face
->postscript
.FormatType
)
364 error
= Load_Format_20( face
, stream
);
368 error
= Load_Format_25( face
, stream
);
372 error
= TT_Err_Invalid_File_Format
;
375 face
->postscript_names
.loaded
= 1;
383 void TT_Free_Post_Names( TT_Face face
)
385 FT_Memory memory
= face
->root
.memory
;
386 TT_Post_Names
* names
= &face
->postscript_names
;
391 switch ( face
->postscript
.FormatType
)
395 TT_Post_20
* table
= &names
->names
.format_20
;
399 FREE( table
->glyph_indices
);
400 table
->num_glyphs
= 0;
402 for ( n
= 0; n
< table
->num_names
; n
++ )
403 FREE( table
->glyph_names
[n
] );
405 FREE( table
->glyph_names
);
406 table
->num_names
= 0;
412 TT_Post_25
* table
= &names
->names
.format_25
;
415 FREE( table
->offsets
);
416 table
->num_glyphs
= 0;
425 /*************************************************************************/
431 /* Gets the PostScript glyph name of a glyph. */
434 /* face :: A handle to the parent face. */
436 /* index :: The glyph index. */
438 /* PSname :: The address of a string pointer. Will be NULL in case */
439 /* of error, otherwise it is a pointer to the glyph name. */
441 /* You must not modify the returned string! */
444 /* FreeType error code. 0 means success. */
447 FT_Error
TT_Get_PS_Name( TT_Face face
,
452 TT_Post_Names
* names
;
454 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
455 PSNames_Interface
* psnames
;
460 return TT_Err_Invalid_Face_Handle
;
462 if ( index
>= (FT_UInt
)face
->root
.num_glyphs
)
463 return TT_Err_Invalid_Glyph_Index
;
465 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
466 psnames
= (PSNames_Interface
*)face
->psnames
;
468 return TT_Err_Unimplemented_Feature
;
471 names
= &face
->postscript_names
;
473 /* `.notdef' by default */
474 *PSname
= MAC_NAME( 0 );
476 switch ( face
->postscript
.FormatType
)
479 if ( index
< 258 ) /* paranoid checking */
480 *PSname
= MAC_NAME( index
);
485 TT_Post_20
* table
= &names
->names
.format_20
;
488 if ( !names
->loaded
)
490 error
= Load_Post_Names( face
);
495 if ( index
< table
->num_glyphs
)
497 FT_UShort name_index
= table
->glyph_indices
[index
];
500 if ( name_index
< 258 )
501 *PSname
= MAC_NAME( name_index
);
503 *PSname
= (FT_String
*)table
->glyph_names
[name_index
- 258];
510 TT_Post_25
* table
= &names
->names
.format_25
;
513 if ( !names
->loaded
)
515 error
= Load_Post_Names( face
);
520 if ( index
< table
->num_glyphs
) /* paranoid checking */
522 index
+= table
->offsets
[index
];
523 *PSname
= MAC_NAME( index
);
529 break; /* nothing to do */