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