]> git.saurik.com Git - wxWidgets.git/blame - src/freetype/sfnt/ttpost.c
fixed serious bug in wxFont::operator== (ignored weight)
[wxWidgets.git] / src / freetype / sfnt / ttpost.c
CommitLineData
cabec872
RR
1/***************************************************************************/
2/* */
3/* ttpost.c */
4/* */
5/* Postcript name table processing for TrueType and OpenType fonts */
6/* (body). */
7/* */
8/* Copyright 1996-2000 by */
9/* David Turner, Robert Wilhelm, and Werner Lemberg. */
10/* */
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. */
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
27
28#include <freetype/internal/ftstream.h>
29#include <freetype/internal/tterrors.h>
30#include <freetype/tttags.h>
31
32
33#ifdef FT_FLAT_COMPILE
34
35#include "ttpost.h"
36#include "ttload.h"
37
38#else
39
40#include <sfnt/ttpost.h>
41#include <sfnt/ttload.h>
42
43#endif
44
45
46 /*************************************************************************/
47 /* */
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. */
51 /* */
52#undef FT_COMPONENT
53#define FT_COMPONENT trace_ttpost
54
55
56 /* If this configuration macro is defined, we rely on the `PSNames' */
57 /* module to grab the glyph names. */
58
59#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
60
61
62#include <freetype/internal/psnames.h>
63
64#define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) )
65
66
67#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
68
69
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. */
73
74#define MAC_NAME( x ) TT_Post_Default_Names[x]
75
76 /* the 258 default Mac PS glyph names */
77
78 FT_String* TT_Post_Default_Names[258] =
79 {
80 /* 0 */
81 ".notdef", ".null", "CR", "space", "exclam",
82 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
83 /* 10 */
84 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
85 "comma", "hyphen", "period", "slash", "zero",
86 /* 20 */
87 "one", "two", "three", "four", "five",
88 "six", "seven", "eight", "nine", "colon",
89 /* 30 */
90 "semicolon", "less", "equal", "greater", "question",
91 "at", "A", "B", "C", "D",
92 /* 40 */
93 "E", "F", "G", "H", "I",
94 "J", "K", "L", "M", "N",
95 /* 50 */
96 "O", "P", "Q", "R", "S",
97 "T", "U", "V", "W", "X",
98 /* 60 */
99 "Y", "Z", "bracketleft", "backslash", "bracketright",
100 "asciicircum", "underscore", "grave", "a", "b",
101 /* 70 */
102 "c", "d", "e", "f", "g",
103 "h", "i", "j", "k", "l",
104 /* 80 */
105 "m", "n", "o", "p", "q",
106 "r", "s", "t", "u", "v",
107 /* 90 */
108 "w", "x", "y", "z", "braceleft",
109 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
110 /* 100 */
111 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
112 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
113 /* 110 */
114 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
115 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
116 /* 120 */
117 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
118 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
119 /* 130 */
120 "dagger", "degree", "cent", "sterling", "section",
121 "bullet", "paragraph", "germandbls", "registered", "copyright",
122 /* 140 */
123 "trademark", "acute", "dieresis", "notequal", "AE",
124 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
125 /* 150 */
126 "yen", "mu", "partialdiff", "summation", "product",
127 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
128 /* 160 */
129 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
130 "radical", "florin", "approxequal", "Delta", "guillemotleft",
131 /* 170 */
132 "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
133 "Otilde", "OE", "oe", "endash", "emdash",
134 /* 180 */
135 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
136 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
137 /* 190 */
138 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
139 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
140 /* 200 */
141 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
142 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
143 /* 210 */
144 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
145 "dotlessi", "circumflex", "tilde", "macron", "breve",
146 /* 220 */
147 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
148 "caron", "Lslash", "lslash", "Scaron", "scaron",
149 /* 230 */
150 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
151 "Yacute", "yacute", "Thorn", "thorn", "minus",
152 /* 240 */
153 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
154 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
155 /* 250 */
156 "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
157 "Ccaron", "ccaron", "dmacron",
158 };
159
160
161#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
162
163
164 static
165 FT_Error Load_Format_20( TT_Face face,
166 FT_Stream stream )
167 {
168 FT_Memory memory = stream->memory;
169 FT_Error error;
170
171 FT_Int num_glyphs;
172 FT_Int num_names;
173
174 FT_UShort* glyph_indices = 0;
175 FT_Char** name_strings = 0;
176
177
178 if ( READ_UShort( num_glyphs ) )
179 goto Exit;
180
181 /* UNDOCUMENTED! The number of glyphs in this table can be smaller */
182 /* than the value in the maxp table (cf. cyberbit.ttf). */
183
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. */
186
187 if ( num_glyphs > face->root.num_glyphs )
188 {
189 error = TT_Err_Invalid_File_Format;
190 goto Exit;
191 }
192
193 /* load the indices */
194 {
195 FT_Int n;
196
197
198 if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, FT_UShort ) ||
199 ACCESS_Frame( num_glyphs * 2L ) )
200 goto Fail;
201
202 for ( n = 0; n < num_glyphs; n++ )
203 glyph_indices[n] = GET_UShort();
204
205 FORGET_Frame();
206 }
207
208 /* compute number of names stored in table */
209 {
210 FT_Int n;
211
212
213 num_names = 0;
214
215 for ( n = 0; n < num_glyphs; n++ )
216 {
217 FT_Int index;
218
219
220 index = glyph_indices[n];
221 if ( index >= 258 )
222 {
223 index -= 257;
224 if ( index > num_names )
225 num_names = index;
226 }
227 }
228 }
229
230 /* now load the name strings */
231 {
232 FT_Int n;
233
234
235 if ( ALLOC_ARRAY( name_strings, num_names, FT_Char* ) )
236 goto Fail;
237
238 for ( n = 0; n < num_names; n++ )
239 {
240 FT_UInt len;
241
242
243 if ( READ_Byte ( len ) ||
244 ALLOC_ARRAY( name_strings[n], len + 1, FT_Char ) ||
245 FILE_Read ( name_strings[n], len ) )
246 goto Fail1;
247
248 name_strings[n][len] = '\0';
249 }
250 }
251
252 /* all right, set table fields and exit successfuly */
253 {
254 TT_Post_20* table = &face->postscript_names.names.format_20;
255
256
257 table->num_glyphs = num_glyphs;
258 table->num_names = num_names;
259 table->glyph_indices = glyph_indices;
260 table->glyph_names = name_strings;
261 }
262 return TT_Err_Ok;
263
264
265 Fail1:
266 {
267 FT_Int n;
268
269
270 for ( n = 0; n < num_names; n++ )
271 FREE( name_strings[n] );
272 }
273
274 Fail:
275 FREE( name_strings );
276 FREE( glyph_indices );
277
278 Exit:
279 return error;
280 }
281
282
283 static
284 FT_Error Load_Format_25( TT_Face face,
285 FT_Stream stream )
286 {
287 FT_Memory memory = stream->memory;
288 FT_Error error;
289
290 FT_Int num_glyphs;
291 FT_Char* offset_table = 0;
292
293
294 /* UNDOCUMENTED! This value appears only in the Apple TT specs. */
295 if ( READ_UShort( num_glyphs ) )
296 goto Exit;
297
298 /* check the number of glyphs */
299 if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 )
300 {
301 error = TT_Err_Invalid_File_Format;
302 goto Exit;
303 }
304
305 if ( ALLOC ( offset_table, num_glyphs ) ||
306 FILE_Read( offset_table, num_glyphs ) )
307 goto Fail;
308
309 /* now check the offset table */
310 {
311 FT_Int n;
312
313
314 for ( n = 0; n < num_glyphs; n++ )
315 {
316 FT_Long index = (FT_Long)n + offset_table[n];
317
318
319 if ( index < 0 || index > num_glyphs )
320 {
321 error = TT_Err_Invalid_File_Format;
322 goto Fail;
323 }
324 }
325 }
326
327 /* OK, set table fields and exit successfuly */
328 {
329 TT_Post_25* table = &face->postscript_names.names.format_25;
330
331
332 table->num_glyphs = num_glyphs;
333 table->offsets = offset_table;
334 }
335
336 return TT_Err_Ok;
337
338 Fail:
339 FREE( offset_table );
340
341 Exit:
342 return error;
343 }
344
345
346 static
347 FT_Error Load_Post_Names( TT_Face face )
348 {
349 FT_Stream stream;
350 FT_Error error;
351
352 /* get a stream for the face's resource */
353 stream = face->root.stream;
354
355 /* seek to the beginning of the PS names table */
356 error = face->goto_table( face, TTAG_post, stream, 0 );
357 if ( error )
358 goto Exit;
359
360 /* now read postscript table */
361 switch ( face->postscript.FormatType )
362 {
363 case 0x00020000L:
364 error = Load_Format_20( face, stream );
365 break;
366
367 case 0x00028000L:
368 error = Load_Format_25( face, stream );
369 break;
370
371 default:
372 error = TT_Err_Invalid_File_Format;
373 }
374
375 face->postscript_names.loaded = 1;
376
377 Exit:
378 return error;
379 }
380
381
382 LOCAL_FUNC
383 void TT_Free_Post_Names( TT_Face face )
384 {
385 FT_Memory memory = face->root.memory;
386 TT_Post_Names* names = &face->postscript_names;
387
388
389 if ( names->loaded )
390 {
391 switch ( face->postscript.FormatType )
392 {
393 case 0x00020000L:
394 {
395 TT_Post_20* table = &names->names.format_20;
396 FT_UInt n;
397
398
399 FREE( table->glyph_indices );
400 table->num_glyphs = 0;
401
402 for ( n = 0; n < table->num_names; n++ )
403 FREE( table->glyph_names[n] );
404
405 FREE( table->glyph_names );
406 table->num_names = 0;
407 }
408 break;
409
410 case 0x00028000L:
411 {
412 TT_Post_25* table = &names->names.format_25;
413
414
415 FREE( table->offsets );
416 table->num_glyphs = 0;
417 }
418 break;
419 }
420 }
421 names->loaded = 0;
422 }
423
424
425 /*************************************************************************/
426 /* */
427 /* <Function> */
428 /* TT_Get_PS_Name */
429 /* */
430 /* <Description> */
431 /* Gets the PostScript glyph name of a glyph. */
432 /* */
433 /* <Input> */
434 /* face :: A handle to the parent face. */
435 /* */
436 /* index :: The glyph index. */
437 /* */
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. */
440 /* */
441 /* You must not modify the returned string! */
442 /* */
443 /* <Output> */
444 /* FreeType error code. 0 means success. */
445 /* */
446 LOCAL_FUNC
447 FT_Error TT_Get_PS_Name( TT_Face face,
448 FT_UInt index,
449 FT_String** PSname )
450 {
451 FT_Error error;
452 TT_Post_Names* names;
453
454#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
455 PSNames_Interface* psnames;
456#endif
457
458
459 if ( !face )
460 return TT_Err_Invalid_Face_Handle;
461
462 if ( index >= (FT_UInt)face->root.num_glyphs )
463 return TT_Err_Invalid_Glyph_Index;
464
465#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
466 psnames = (PSNames_Interface*)face->psnames;
467 if ( !psnames )
468 return TT_Err_Unimplemented_Feature;
469#endif
470
471 names = &face->postscript_names;
472
473 /* `.notdef' by default */
474 *PSname = MAC_NAME( 0 );
475
476 switch ( face->postscript.FormatType )
477 {
478 case 0x00010000L:
479 if ( index < 258 ) /* paranoid checking */
480 *PSname = MAC_NAME( index );
481 break;
482
483 case 0x00020000L:
484 {
485 TT_Post_20* table = &names->names.format_20;
486
487
488 if ( !names->loaded )
489 {
490 error = Load_Post_Names( face );
491 if ( error )
492 break;
493 }
494
495 if ( index < table->num_glyphs )
496 {
497 FT_UShort name_index = table->glyph_indices[index];
498
499
500 if ( name_index < 258 )
501 *PSname = MAC_NAME( name_index );
502 else
503 *PSname = (FT_String*)table->glyph_names[name_index - 258];
504 }
505 }
506 break;
507
508 case 0x00028000L:
509 {
510 TT_Post_25* table = &names->names.format_25;
511
512
513 if ( !names->loaded )
514 {
515 error = Load_Post_Names( face );
516 if ( error )
517 break;
518 }
519
520 if ( index < table->num_glyphs ) /* paranoid checking */
521 {
522 index += table->offsets[index];
523 *PSname = MAC_NAME( index );
524 }
525 }
526 break;
527
528 case 0x00030000L:
529 break; /* nothing to do */
530 }
531
532 return TT_Err_Ok;
533 }
534
535
536/* END */