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