Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
ttpost.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ttpost.c */
4 /* */
5 /* Postcript name table processing for TrueType and OpenType fonts */
6 /* (body). */
7 /* */
8 /* Copyright 1996-2003, 2006-2010, 2013 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,
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 = FT_THROW( 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  {
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 FT_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 = FT_THROW( 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 = FT_THROW( Invalid_File_Format );
349  goto Fail;
350  }
351  }
352  }
353 
354  /* OK, set table fields and exit successfully */
355  {
357 
358 
359  table->num_glyphs = (FT_UShort)num_glyphs;
360  table->offsets = offset_table;
361  }
362 
363  return FT_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  {
377  FT_Error error;
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 = FT_THROW( Invalid_File_Format );
406 
407  face->postscript_names.loaded = 1;
408 
409  Exit:
410  return error;
411  }
412 
413 
414  FT_LOCAL_DEF( void )
416  {
417  FT_Memory memory = face->root.memory;
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  /* */
478  FT_UInt idx,
479  FT_String** PSname )
480  {
481  FT_Error error;
484 
485 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
486  FT_Service_PsCMaps psnames;
487 #endif
488 
489 
490  if ( !face )
491  return FT_THROW( Invalid_Face_Handle );
492 
493  if ( idx >= (FT_UInt)face->max_profile.numGlyphs )
494  return FT_THROW( Invalid_Glyph_Index );
495 
496 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
497  psnames = (FT_Service_PsCMaps)face->psnames;
498  if ( !psnames )
499  return FT_THROW( 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 FT_Err_Ok;
560  }
561 
562 
563 /* END */
int FT_Error
Definition: fttypes.h:296
GLuint GLuint stream
signed long FT_Long
Definition: fttypes.h:238
tt_face_free_ps_names(TT_Face face)
Definition: ttpost.c:415
unsigned long FT_ULong
Definition: fttypes.h:249
FT_UShort num_glyphs
Definition: tttypes.h:769
FT_Char * offsets
Definition: tttypes.h:795
FT_Bool loaded
Definition: tttypes.h:817
union TT_Post_NamesRec_::@1 names
signed int FT_Int
Definition: fttypes.h:216
return FT_THROW(Missing_Property)
TT_Post_25Rec format_25
Definition: tttypes.h:822
#define FT_UNUSED(arg)
Definition: ftconfig.h:76
signed char FT_Char
Definition: fttypes.h:139
#define FT_READ_BYTE(var)
Definition: ftstream.h:306
FT_UShort * glyph_indices
Definition: tttypes.h:771
return FT_Err_Ok
Definition: ftbbox.c:645
#define FT_READ_USHORT(var)
Definition: ftstream.h:309
GLuint GLuint * names
FT_UShort numGlyphs
Definition: tttables.h:531
TT_Loader_GotoTableFunc goto_table
Definition: tttypes.h:1288
tt_face_get_ps_name(TT_Face face, FT_UInt idx, FT_String **PSname)
Definition: ttpost.c:477
GLenum GLuint GLint GLenum face
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
FT_Memory memory
Definition: ftsystem.h:332
TT_Post_20Rec format_20
Definition: tttypes.h:821
#define FT_GET_USHORT()
Definition: ftstream.h:289
#define FT_FREE(ptr)
Definition: ftmemory.h:286
#define FT_STREAM_SKIP(distance)
Definition: ftstream.h:492
TT_Postscript postscript
Definition: tttypes.h:1283
GLenum GLsizei len
TT_MaxProfile max_profile
Definition: tttypes.h:1271
FT_UInt idx
Definition: cffcmap.c:127
FT_Error error
Definition: cffdrivr.c:411
char FT_String
Definition: fttypes.h:183
Definition: tttypes.h:792
#define FT_MAX(a, b)
Definition: ftobjs.h:71
GLdouble n
TT_Post_NamesRec postscript_names
Definition: tttypes.h:1332
FT_Char ** glyph_names
Definition: tttypes.h:772
void * psnames
Definition: tttypes.h:1302
Definition: tttypes.h:815
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
FT_FaceRec root
Definition: tttypes.h:1260
#define FT_FRAME_EXIT()
Definition: ftstream.h:514
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:290
if(!abbox) return FT_THROW(Invalid_Argument)
#define FT_TRACE6(varformat)
Definition: ftdebug.h:163
#define FT_STREAM_POS()
Definition: ftstream.h:486
signed long FT_Fixed
Definition: fttypes.h:284
unsigned int FT_UInt
Definition: fttypes.h:227
FT_UShort num_names
Definition: tttypes.h:770
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:510
FT_UShort num_glyphs
Definition: tttypes.h:794
unsigned short FT_UShort
Definition: fttypes.h:205
GLenum GLsizei GLenum GLenum const GLvoid * table
FT_Stream stream
Definition: freetype.h:964
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:495
#define MAC_NAME(x)
Definition: ttpost.c:65
Definition: tttypes.h:767
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:236
FT_Memory memory
Definition: freetype.h:963
#define TTAG_post
Definition: tttags.h:86
FT_Fixed FormatType
Definition: tttables.h:416