blob: 9055da50e7f68cb0a04e693dc25154683716af05 [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
3/* ttpost.c */
4/* */
5/* Postscript names table processing (body). */
6/* */
7/* Copyright 1996-1999 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used */
11/* modified and distributed under the terms of the FreeType project */
12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
18
19 /*************************************************************************/
20 /* */
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 */
23 /* them. */
24 /* */
25 /*************************************************************************/
26
David Turnerefce08d2000-05-11 18:23:52 +000027#include <freetype/internal/ftstream.h>
28#include <freetype/internal/tterrors.h>
29#include <freetype/tttags.h>
David Turnerd2b1f351999-12-16 23:11:37 +000030
31#include <ttpost.h>
David Turnerd2b1f351999-12-16 23:11:37 +000032#include <ttload.h>
David Turnerd2b1f351999-12-16 23:11:37 +000033
David Turner74336552000-02-10 19:14:48 +000034/* When this configuration macro is defined, we rely on the "psnames" */
35/* module to grab the glyph names.. */
36#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
David Turnerefce08d2000-05-11 18:23:52 +000037#include <freetype/internal/psnames.h>
David Turner74336552000-02-10 19:14:48 +000038#define MAC_NAME(x) ((TT_String*)psnames->macintosh_name(x))
39
40#else
41
42/* Otherwise, we ignore the "psnames" module, then provide our own */
43/* table of Mac names.. Thus, it is possible to build a version of */
44/* FreeType without the Type 1 driver & PSNames module */
45
46#define MAC_NAME(x) TT_Post_Default_Names[x]
47
David Turnerd2b1f351999-12-16 23:11:37 +000048 /* the 258 default Mac PS glyph names */
49
David Turner63cb46d2000-02-22 13:34:26 +000050 FT_String* TT_Post_Default_Names[258] =
David Turnerd2b1f351999-12-16 23:11:37 +000051 {
52 /* 0 */
David Turner74336552000-02-10 19:14:48 +000053 ".notdef", ".null", "CR", "space", "exclam",
54 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
David Turnerd2b1f351999-12-16 23:11:37 +000055 /* 10 */
David Turner74336552000-02-10 19:14:48 +000056 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
57 "comma", "hyphen", "period", "slash", "zero",
David Turnerd2b1f351999-12-16 23:11:37 +000058 /* 20 */
David Turner74336552000-02-10 19:14:48 +000059 "one", "two", "three", "four", "five",
60 "six", "seven", "eight", "nine", "colon",
David Turnerd2b1f351999-12-16 23:11:37 +000061 /* 30 */
David Turner74336552000-02-10 19:14:48 +000062 "semicolon", "less", "equal", "greater", "question",
63 "at", "A", "B", "C", "D",
David Turnerd2b1f351999-12-16 23:11:37 +000064 /* 40 */
David Turner74336552000-02-10 19:14:48 +000065 "E", "F", "G", "H", "I",
66 "J", "K", "L", "M", "N",
David Turnerd2b1f351999-12-16 23:11:37 +000067 /* 50 */
David Turner74336552000-02-10 19:14:48 +000068 "O", "P", "Q", "R", "S",
69 "T", "U", "V", "W", "X",
David Turnerd2b1f351999-12-16 23:11:37 +000070 /* 60 */
David Turner74336552000-02-10 19:14:48 +000071 "Y", "Z", "bracketleft", "backslash", "bracketright",
72 "asciicircum", "underscore", "grave", "a", "b",
David Turnerd2b1f351999-12-16 23:11:37 +000073 /* 70 */
David Turner74336552000-02-10 19:14:48 +000074 "c", "d", "e", "f", "g",
75 "h", "i", "j", "k", "l",
David Turnerd2b1f351999-12-16 23:11:37 +000076 /* 80 */
David Turner74336552000-02-10 19:14:48 +000077 "m", "n", "o", "p", "q",
78 "r", "s", "t", "u", "v",
David Turnerd2b1f351999-12-16 23:11:37 +000079 /* 90 */
David Turner74336552000-02-10 19:14:48 +000080 "w", "x", "y", "z", "braceleft",
81 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
David Turnerd2b1f351999-12-16 23:11:37 +000082 /* 100 */
David Turner74336552000-02-10 19:14:48 +000083 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
84 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
David Turnerd2b1f351999-12-16 23:11:37 +000085 /* 110 */
David Turner74336552000-02-10 19:14:48 +000086 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
87 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
David Turnerd2b1f351999-12-16 23:11:37 +000088 /* 120 */
David Turner74336552000-02-10 19:14:48 +000089 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
90 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
David Turnerd2b1f351999-12-16 23:11:37 +000091 /* 130 */
David Turner74336552000-02-10 19:14:48 +000092 "dagger", "degree", "cent", "sterling", "section",
93 "bullet", "paragraph", "germandbls", "registered", "copyright",
David Turnerd2b1f351999-12-16 23:11:37 +000094 /* 140 */
David Turner74336552000-02-10 19:14:48 +000095 "trademark", "acute", "dieresis", "notequal", "AE",
96 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
David Turnerd2b1f351999-12-16 23:11:37 +000097 /* 150 */
David Turner74336552000-02-10 19:14:48 +000098 "yen", "mu", "partialdiff", "summation", "product",
99 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
David Turnerd2b1f351999-12-16 23:11:37 +0000100 /* 160 */
David Turner74336552000-02-10 19:14:48 +0000101 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
102 "radical", "florin", "approxequal", "Delta", "guillemotleft",
David Turnerd2b1f351999-12-16 23:11:37 +0000103 /* 170 */
David Turner74336552000-02-10 19:14:48 +0000104 "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
105 "Otilde", "OE", "oe", "endash", "emdash",
David Turnerd2b1f351999-12-16 23:11:37 +0000106 /* 180 */
David Turner74336552000-02-10 19:14:48 +0000107 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
108 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
David Turnerd2b1f351999-12-16 23:11:37 +0000109 /* 190 */
David Turner74336552000-02-10 19:14:48 +0000110 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
111 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
David Turnerd2b1f351999-12-16 23:11:37 +0000112 /* 200 */
David Turner74336552000-02-10 19:14:48 +0000113 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
114 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
David Turnerd2b1f351999-12-16 23:11:37 +0000115 /* 210 */
David Turner74336552000-02-10 19:14:48 +0000116 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
117 "dotlessi", "circumflex", "tilde", "macron", "breve",
David Turnerd2b1f351999-12-16 23:11:37 +0000118 /* 220 */
David Turner74336552000-02-10 19:14:48 +0000119 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
120 "caron", "Lslash", "lslash", "Scaron", "scaron",
David Turnerd2b1f351999-12-16 23:11:37 +0000121 /* 230 */
David Turner74336552000-02-10 19:14:48 +0000122 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
123 "Yacute", "yacute", "Thorn", "thorn", "minus",
David Turnerd2b1f351999-12-16 23:11:37 +0000124 /* 240 */
David Turner74336552000-02-10 19:14:48 +0000125 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
126 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
David Turnerd2b1f351999-12-16 23:11:37 +0000127 /* 250 */
David Turner74336552000-02-10 19:14:48 +0000128 "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
129 "Ccaron", "ccaron", "dmacron",
David Turnerd2b1f351999-12-16 23:11:37 +0000130 };
David Turner74336552000-02-10 19:14:48 +0000131#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000132
133
134 static
135 TT_Error Load_Format_20( TT_Face face,
136 FT_Stream stream )
137 {
138 FT_Memory memory = stream->memory;
139 TT_Error error;
140
141 TT_Int num_glyphs;
142 TT_Int num_names;
143
144 TT_UShort* glyph_indices = 0;
145 TT_Char** name_strings = 0;
146
147
148 if ( READ_UShort( num_glyphs ) )
149 goto Exit;
150
151 /* UNDOCUMENTED! The number of glyphs in this table can be smaller */
152 /* than the value in the maxp table (cf. cyberbit.ttf). */
153
154 /* There already exist fonts which have more than 32768 glyph names */
155 /* in this table, so the test for this threshold has been dropped. */
156
157 if ( num_glyphs > face->root.num_glyphs )
158 {
159 error = TT_Err_Invalid_File_Format;
160 goto Exit;
161 }
162
163 /* load the indices */
164 {
165 TT_Int n;
166
167 if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, TT_UShort ) ||
168 ACCESS_Frame( num_glyphs * 2L ) )
169 goto Fail;
170
171 for ( n = 0; n < num_glyphs; n++ )
172 glyph_indices[n] = GET_UShort();
173
174 FORGET_Frame();
175 }
176
177 /* compute number of names stored in table */
178 {
179 TT_Int n;
180
181 num_names = 0;
182
183 for ( n = 0; n < num_glyphs; n++ )
184 {
185 TT_Int index;
186
187 index = glyph_indices[n];
188 if ( index >= 258 )
189 {
190 index -= 257;
191 if ( index > num_names )
192 num_names = index;
193 }
194 }
195 }
196
197 /* now load the name strings */
198 {
199 TT_Int n;
200
201 if ( ALLOC_ARRAY( name_strings, num_names, TT_Char* ) )
202 goto Fail;
203
204 for ( n = 0; n < num_names; n++ )
205 {
206 TT_UInt len;
207
208 if ( READ_Byte ( len ) ||
209 ALLOC_ARRAY( name_strings[n], len+1, TT_Char ) ||
210 FILE_Read ( name_strings[n], len ) )
211 goto Fail1;
212
213 name_strings[n][len] = '\0';
214 }
215 }
216
217 /* all right, set table fields and exit successfuly */
218 {
219 TT_Post_20* table = &face->postscript_names.names.format_20;
220
221 table->num_glyphs = num_glyphs;
222 table->num_names = num_names;
223 table->glyph_indices = glyph_indices;
224 table->glyph_names = name_strings;
225 }
226 return TT_Err_Ok;
227
228
229 Fail1:
230 {
231 TT_Int n;
232
233 for ( n = 0; n < num_names; n++ )
234 FREE( name_strings[n] );
235 }
236
237 Fail:
238 FREE( name_strings );
239 FREE( glyph_indices );
240
241 Exit:
242 return error;
243 }
244
245
246 static
247 TT_Error Load_Format_25( TT_Face face,
248 FT_Stream stream )
249 {
250 FT_Memory memory = stream->memory;
251 TT_Error error;
252
253 TT_Int num_glyphs;
254 TT_Char* offset_table = 0;
255
256
257 /* UNDOCUMENTED! This value appears only in the Apple TT specs. */
258 if ( READ_UShort( num_glyphs ) )
259 goto Exit;
260
261 /* check the number of glyphs */
262 if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 )
263 {
264 error = TT_Err_Invalid_File_Format;
265 goto Exit;
266 }
267
268 if ( ALLOC ( offset_table, num_glyphs ) ||
269 FILE_Read( offset_table, num_glyphs ) )
270 goto Fail;
271
272 /* now check the offset table */
273 {
274 TT_Int n;
275
276
277 for ( n = 0; n < num_glyphs; n++ )
278 {
279 TT_Long index = (TT_Long)n + offset_table[n];
280
281
282 if ( index < 0 || index > num_glyphs )
283 {
284 error = TT_Err_Invalid_File_Format;
285 goto Fail;
286 }
287 }
288 }
289
290 /* OK, set table fields and exit successfuly */
291 {
292 TT_Post_25* table = &face->postscript_names.names.format_25;
293
294
295 table->num_glyphs = num_glyphs;
296 table->offsets = offset_table;
297 }
298
299 return TT_Err_Ok;
300
301 Fail:
302 FREE( offset_table );
303
304 Exit:
305 return error;
306 }
307
308
309 static
310 TT_Error Load_Post_Names( TT_Face face )
311 {
312 FT_Stream stream;
313 TT_Error error;
314
315 /* get a stream for the face's resource */
316 stream = face->root.stream;
317
318 /* seek to the beginning of the PS names table */
319 error = face->goto_table( face, TTAG_post, stream, 0 );
320 if (error) goto Exit;
321
322 /* now read postscript table */
323 switch ( face->postscript.FormatType )
324 {
325 case 0x00020000:
326 error = Load_Format_20( face, stream );
327 break;
328
329 case 0x00028000:
330 error = Load_Format_25( face, stream );
331 break;
332
333 default:
334 error = TT_Err_Invalid_File_Format;
335 }
336
337 face->postscript_names.loaded = 1;
338
339 Exit:
340 return error;
341 }
342
343
344 LOCAL_FUNC
345 void TT_Free_Post_Names( TT_Face face )
346 {
347 FT_Memory memory = face->root.memory;
348 TT_Post_Names* names = &face->postscript_names;
349
350
351 if ( names->loaded )
352 {
353 switch ( face->postscript.FormatType )
354 {
355 case 0x00020000:
356 {
357 TT_Post_20* table = &names->names.format_20;
358 TT_UInt n;
359
360
361 FREE( table->glyph_indices );
362 table->num_glyphs = 0;
363
364 for ( n = 0; n < table->num_names; n++ )
365 FREE( table->glyph_names[n] );
366
367 FREE( table->glyph_names );
368 table->num_names = 0;
369 }
370 break;
371
372 case 0x00028000:
373 {
374 TT_Post_25* table = &names->names.format_25;
375
376
377 FREE( table->offsets );
378 table->num_glyphs = 0;
379 }
380 break;
381 }
382 }
383 names->loaded = 0;
384 }
385
386
387 /*************************************************************************/
388 /* */
389 /* <Function> */
390 /* TT_Get_PS_Name */
391 /* */
392 /* <Description> */
393 /* Gets the PostScript glyph name of a glyph. */
394 /* */
395 /* <Input> */
396 /* index :: The glyph index. */
397 /* */
398 /* PSname :: The address of a string pointer. Will be NULL in case */
399 /* of error, otherwise it is a pointer to the glyph name. */
400 /* */
401 /* You must not modify the returned string! */
402 /* */
403 /* <Output> */
404 /* TrueType error code. 0 means success. */
405 /* */
406 EXPORT_FUNC
407 TT_Error TT_Get_PS_Name( TT_Face face,
408 TT_UInt index,
409 TT_String** PSname )
410 {
David Turner74336552000-02-10 19:14:48 +0000411 TT_Error error;
412 TT_Post_Names* names;
David Turner63cb46d2000-02-22 13:34:26 +0000413#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
David Turner74336552000-02-10 19:14:48 +0000414 PSNames_Interface* psnames;
David Turner63cb46d2000-02-22 13:34:26 +0000415#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000416 if ( !face )
417 return TT_Err_Invalid_Face_Handle;
418
419 if ( index >= (TT_UInt)face->root.num_glyphs )
420 return TT_Err_Invalid_Glyph_Index;
421
David Turner63cb46d2000-02-22 13:34:26 +0000422#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
David Turner74336552000-02-10 19:14:48 +0000423 psnames = (PSNames_Interface*)face->psnames;
424 if (!psnames)
425 return TT_Err_Unimplemented_Feature;
David Turner63cb46d2000-02-22 13:34:26 +0000426#endif
427
David Turnerd2b1f351999-12-16 23:11:37 +0000428 names = &face->postscript_names;
429
430 /* `.notdef' by default */
David Turner74336552000-02-10 19:14:48 +0000431 *PSname = MAC_NAME(0);
David Turnerd2b1f351999-12-16 23:11:37 +0000432
433 switch ( face->postscript.FormatType )
434 {
435 case 0x00010000:
436 if ( index < 258 ) /* paranoid checking */
David Turner74336552000-02-10 19:14:48 +0000437 *PSname = MAC_NAME(index);
David Turnerd2b1f351999-12-16 23:11:37 +0000438 break;
439
440 case 0x00020000:
441 {
442 TT_Post_20* table = &names->names.format_20;
443
444
445 if ( !names->loaded )
446 {
447 error = Load_Post_Names( face );
448 if ( error )
449 break;
450 }
451
452 if ( index < table->num_glyphs )
453 {
454 TT_UShort name_index = table->glyph_indices[index];
455
456
457 if ( name_index < 258 )
David Turner74336552000-02-10 19:14:48 +0000458 *PSname = MAC_NAME(name_index);
David Turnerd2b1f351999-12-16 23:11:37 +0000459 else
460 *PSname = (TT_String*)table->glyph_names[name_index - 258];
461 }
462 }
463 break;
464
465 case 0x00028000:
466 {
467 TT_Post_25* table = &names->names.format_25;
468
469
470 if ( !names->loaded )
471 {
472 error = Load_Post_Names( face );
473 if ( error )
474 break;
475 }
476
477 if ( index < table->num_glyphs ) /* paranoid checking */
478 {
479 index += table->offsets[index];
David Turner74336552000-02-10 19:14:48 +0000480 *PSname = MAC_NAME(index);
David Turnerd2b1f351999-12-16 23:11:37 +0000481 }
482 }
483 break;
484
485 case 0x00030000:
486 break; /* nothing to do */
487 }
488
489 return TT_Err_Ok;
490 }
491
492
493/* END */