1
/***************************************************************************/
5
/* Postcript name table processing for TrueType and OpenType fonts */
8
/* Copyright 1996-2001, 2002, 2003 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_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 ) tt_post_default_names[x]
67
/* the 258 default Mac PS glyph names */
69
static const 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 */
359
if ( format == 0x00020000L )
360
error = load_format_20( face, stream );
361
else if ( format == 0x00028000L )
362
error = load_format_25( face, stream );
364
error = SFNT_Err_Invalid_File_Format;
366
face->postscript_names.loaded = 1;
374
tt_face_free_ps_names( TT_Face face )
376
FT_Memory memory = face->root.memory;
377
TT_Post_Names names = &face->postscript_names;
383
format = face->postscript.FormatType;
385
if ( format == 0x00020000L )
387
TT_Post_20 table = &names->names.format_20;
391
FT_FREE( table->glyph_indices );
392
table->num_glyphs = 0;
394
for ( n = 0; n < table->num_names; n++ )
395
FT_FREE( table->glyph_names[n] );
397
FT_FREE( table->glyph_names );
398
table->num_names = 0;
400
else if ( format == 0x00028000L )
402
TT_Post_25 table = &names->names.format_25;
405
FT_FREE( table->offsets );
406
table->num_glyphs = 0;
413
/*************************************************************************/
416
/* tt_face_get_ps_name */
419
/* Gets the PostScript glyph name of a glyph. */
422
/* face :: A handle to the parent face. */
424
/* 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->root.num_glyphs )
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 */