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]
t42parse.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* t42parse.c */
4 /* */
5 /* Type 42 font parser (body). */
6 /* */
7 /* Copyright 2002-2013 by */
8 /* Roberto Alameda. */
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 #include "t42parse.h"
20 #include "t42error.h"
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_INTERNAL_POSTSCRIPT_AUX_H
24 
25 
26  /*************************************************************************/
27  /* */
28  /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
29  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
30  /* messages during execution. */
31  /* */
32 #undef FT_COMPONENT
33 #define FT_COMPONENT trace_t42
34 
35 
36  static void
37  t42_parse_font_matrix( T42_Face face,
38  T42_Loader loader );
39  static void
40  t42_parse_encoding( T42_Face face,
41  T42_Loader loader );
42 
43  static void
44  t42_parse_charstrings( T42_Face face,
45  T42_Loader loader );
46 
47  static void
48  t42_parse_sfnts( T42_Face face,
49  T42_Loader loader );
50 
51 
52  /* as Type42 fonts have no Private dict, */
53  /* we set the last argument of T1_FIELD_XXX to 0 */
54  static const
55  T1_FieldRec t42_keywords[] =
56  {
57 
58 #undef FT_STRUCTURE
59 #define FT_STRUCTURE T1_FontInfo
60 #undef T1CODE
61 #define T1CODE T1_FIELD_LOCATION_FONT_INFO
62 
63  T1_FIELD_STRING( "version", version, 0 )
64  T1_FIELD_STRING( "Notice", notice, 0 )
65  T1_FIELD_STRING( "FullName", full_name, 0 )
66  T1_FIELD_STRING( "FamilyName", family_name, 0 )
67  T1_FIELD_STRING( "Weight", weight, 0 )
68  T1_FIELD_NUM ( "ItalicAngle", italic_angle, 0 )
69  T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch, 0 )
70  T1_FIELD_NUM ( "UnderlinePosition", underline_position, 0 )
71  T1_FIELD_NUM ( "UnderlineThickness", underline_thickness, 0 )
72 
73 #undef FT_STRUCTURE
74 #define FT_STRUCTURE PS_FontExtraRec
75 #undef T1CODE
76 #define T1CODE T1_FIELD_LOCATION_FONT_EXTRA
77 
78  T1_FIELD_NUM ( "FSType", fs_type, 0 )
79 
80 #undef FT_STRUCTURE
81 #define FT_STRUCTURE T1_FontRec
82 #undef T1CODE
83 #define T1CODE T1_FIELD_LOCATION_FONT_DICT
84 
85  T1_FIELD_KEY ( "FontName", font_name, 0 )
86  T1_FIELD_NUM ( "PaintType", paint_type, 0 )
87  T1_FIELD_NUM ( "FontType", font_type, 0 )
88  T1_FIELD_FIXED( "StrokeWidth", stroke_width, 0 )
89 
90 #undef FT_STRUCTURE
91 #define FT_STRUCTURE FT_BBox
92 #undef T1CODE
93 #define T1CODE T1_FIELD_LOCATION_BBOX
94 
95  T1_FIELD_BBOX("FontBBox", xMin, 0 )
96 
97  T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix, 0 )
98  T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding, 0 )
99  T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings, 0 )
100  T1_FIELD_CALLBACK( "sfnts", t42_parse_sfnts, 0 )
101 
102  { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
103  };
104 
105 
106 #define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )
107 #define T1_Done_Table( p ) \
108  do \
109  { \
110  if ( (p)->funcs.done ) \
111  (p)->funcs.done( p ); \
112  } while ( 0 )
113 #define T1_Release_Table( p ) \
114  do \
115  { \
116  if ( (p)->funcs.release ) \
117  (p)->funcs.release( p ); \
118  } while ( 0 )
119 
120 #define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
121 #define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root )
122 
123 #define T1_ToInt( p ) \
124  (p)->root.funcs.to_int( &(p)->root )
125 #define T1_ToBytes( p, b, m, n, d ) \
126  (p)->root.funcs.to_bytes( &(p)->root, b, m, n, d )
127 
128 #define T1_ToFixedArray( p, m, f, t ) \
129  (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
130 #define T1_ToToken( p, t ) \
131  (p)->root.funcs.to_token( &(p)->root, t )
132 
133 #define T1_Load_Field( p, f, o, m, pf ) \
134  (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
135 #define T1_Load_Field_Table( p, f, o, m, pf ) \
136  (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
137 
138 
139  /********************* Parsing Functions ******************/
140 
144  FT_Memory memory,
145  PSAux_Service psaux )
146  {
148  FT_Long size;
149 
150 
151  psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
152 
153  parser->stream = stream;
154  parser->base_len = 0;
155  parser->base_dict = 0;
156  parser->in_memory = 0;
157 
158  /*******************************************************************/
159  /* */
160  /* Here a short summary of what is going on: */
161  /* */
162  /* When creating a new Type 42 parser, we try to locate and load */
163  /* the base dictionary, loading the whole font into memory. */
164  /* */
165  /* When `loading' the base dictionary, we only set up pointers */
166  /* in the case of a memory-based stream. Otherwise, we allocate */
167  /* and load the base dictionary in it. */
168  /* */
169  /* parser->in_memory is set if we have a memory stream. */
170  /* */
171 
172  if ( FT_STREAM_SEEK( 0L ) ||
173  FT_FRAME_ENTER( 17 ) )
174  goto Exit;
175 
176  if ( ft_memcmp( stream->cursor, "%!PS-TrueTypeFont", 17 ) != 0 )
177  {
178  FT_TRACE2(( " not a Type42 font\n" ));
179  error = FT_THROW( Unknown_File_Format );
180  }
181 
182  FT_FRAME_EXIT();
183 
184  if ( error || FT_STREAM_SEEK( 0 ) )
185  goto Exit;
186 
187  size = stream->size;
188 
189  /* now, try to load `size' bytes of the `base' dictionary we */
190  /* found previously */
191 
192  /* if it is a memory-based resource, set up pointers */
193  if ( !stream->read )
194  {
195  parser->base_dict = (FT_Byte*)stream->base + stream->pos;
196  parser->base_len = size;
197  parser->in_memory = 1;
198 
199  /* check that the `size' field is valid */
200  if ( FT_STREAM_SKIP( size ) )
201  goto Exit;
202  }
203  else
204  {
205  /* read segment in memory */
206  if ( FT_ALLOC( parser->base_dict, size ) ||
207  FT_STREAM_READ( parser->base_dict, size ) )
208  goto Exit;
209 
210  parser->base_len = size;
211  }
212 
213  parser->root.base = parser->base_dict;
214  parser->root.cursor = parser->base_dict;
215  parser->root.limit = parser->root.cursor + parser->base_len;
216 
217  Exit:
218  if ( error && !parser->in_memory )
219  FT_FREE( parser->base_dict );
220 
221  return error;
222  }
223 
224 
225  FT_LOCAL_DEF( void )
227  {
228  FT_Memory memory = parser->root.memory;
229 
230 
231  /* free the base dictionary only when we have a disk stream */
232  if ( !parser->in_memory )
233  FT_FREE( parser->base_dict );
234 
235  parser->root.funcs.done( &parser->root );
236  }
237 
238 
239  static int
240  t42_is_space( FT_Byte c )
241  {
242  return ( c == ' ' || c == '\t' ||
243  c == '\r' || c == '\n' || c == '\f' ||
244  c == '\0' );
245  }
246 
247 
248  static void
249  t42_parse_font_matrix( T42_Face face,
250  T42_Loader loader )
251  {
252  T42_Parser parser = &loader->parser;
253  FT_Matrix* matrix = &face->type1.font_matrix;
254  FT_Vector* offset = &face->type1.font_offset;
255  FT_Face root = (FT_Face)&face->root;
256  FT_Fixed temp[6];
257  FT_Fixed temp_scale;
258 
259 
260  (void)T1_ToFixedArray( parser, 6, temp, 3 );
261 
262  temp_scale = FT_ABS( temp[3] );
263 
264  /* Set Units per EM based on FontMatrix values. We set the value to */
265  /* 1000 / temp_scale, because temp_scale was already multiplied by */
266  /* 1000 (in t1_tofixed, from psobjs.c). */
267 
268  root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );
269 
270  /* we need to scale the values by 1.0/temp_scale */
271  if ( temp_scale != 0x10000L )
272  {
273  temp[0] = FT_DivFix( temp[0], temp_scale );
274  temp[1] = FT_DivFix( temp[1], temp_scale );
275  temp[2] = FT_DivFix( temp[2], temp_scale );
276  temp[4] = FT_DivFix( temp[4], temp_scale );
277  temp[5] = FT_DivFix( temp[5], temp_scale );
278  temp[3] = 0x10000L;
279  }
280 
281  matrix->xx = temp[0];
282  matrix->yx = temp[1];
283  matrix->xy = temp[2];
284  matrix->yy = temp[3];
285 
286  /* note that the offsets must be expressed in integer font units */
287  offset->x = temp[4] >> 16;
288  offset->y = temp[5] >> 16;
289  }
290 
291 
292  static void
293  t42_parse_encoding( T42_Face face,
294  T42_Loader loader )
295  {
296  T42_Parser parser = &loader->parser;
297  FT_Byte* cur;
298  FT_Byte* limit = parser->root.limit;
299 
300  PSAux_Service psaux = (PSAux_Service)face->psaux;
301 
302 
303  T1_Skip_Spaces( parser );
304  cur = parser->root.cursor;
305  if ( cur >= limit )
306  {
307  FT_ERROR(( "t42_parse_encoding: out of bounds\n" ));
308  parser->root.error = FT_THROW( Invalid_File_Format );
309  return;
310  }
311 
312  /* if we have a number or `[', the encoding is an array, */
313  /* and we must load it now */
314  if ( ft_isdigit( *cur ) || *cur == '[' )
315  {
316  T1_Encoding encode = &face->type1.encoding;
317  FT_UInt count, n;
318  PS_Table char_table = &loader->encoding_table;
319  FT_Memory memory = parser->root.memory;
320  FT_Error error;
321  FT_Bool only_immediates = 0;
322 
323 
324  /* read the number of entries in the encoding; should be 256 */
325  if ( *cur == '[' )
326  {
327  count = 256;
328  only_immediates = 1;
329  parser->root.cursor++;
330  }
331  else
332  count = (FT_UInt)T1_ToInt( parser );
333 
334  T1_Skip_Spaces( parser );
335  if ( parser->root.cursor >= limit )
336  return;
337 
338  /* we use a T1_Table to store our charnames */
339  loader->num_chars = encode->num_chars = count;
340  if ( FT_NEW_ARRAY( encode->char_index, count ) ||
341  FT_NEW_ARRAY( encode->char_name, count ) ||
343  char_table, count, memory ) ) )
344  {
345  parser->root.error = error;
346  return;
347  }
348 
349  /* We need to `zero' out encoding_table.elements */
350  for ( n = 0; n < count; n++ )
351  {
352  char* notdef = (char *)".notdef";
353 
354 
355  T1_Add_Table( char_table, n, notdef, 8 );
356  }
357 
358  /* Now we need to read records of the form */
359  /* */
360  /* ... charcode /charname ... */
361  /* */
362  /* for each entry in our table. */
363  /* */
364  /* We simply look for a number followed by an immediate */
365  /* name. Note that this ignores correctly the sequence */
366  /* that is often seen in type42 fonts: */
367  /* */
368  /* 0 1 255 { 1 index exch /.notdef put } for dup */
369  /* */
370  /* used to clean the encoding array before anything else. */
371  /* */
372  /* Alternatively, if the array is directly given as */
373  /* */
374  /* /Encoding [ ... ] */
375  /* */
376  /* we only read immediates. */
377 
378  n = 0;
379  T1_Skip_Spaces( parser );
380 
381  while ( parser->root.cursor < limit )
382  {
383  cur = parser->root.cursor;
384 
385  /* we stop when we encounter `def' or `]' */
386  if ( *cur == 'd' && cur + 3 < limit )
387  {
388  if ( cur[1] == 'e' &&
389  cur[2] == 'f' &&
390  t42_is_space( cur[3] ) )
391  {
392  FT_TRACE6(( "encoding end\n" ));
393  cur += 3;
394  break;
395  }
396  }
397  if ( *cur == ']' )
398  {
399  FT_TRACE6(( "encoding end\n" ));
400  cur++;
401  break;
402  }
403 
404  /* check whether we have found an entry */
405  if ( ft_isdigit( *cur ) || only_immediates )
406  {
407  FT_Int charcode;
408 
409 
410  if ( only_immediates )
411  charcode = n;
412  else
413  {
414  charcode = (FT_Int)T1_ToInt( parser );
415  T1_Skip_Spaces( parser );
416  }
417 
418  cur = parser->root.cursor;
419 
420  if ( *cur == '/' && cur + 2 < limit && n < count )
421  {
422  FT_PtrDist len;
423 
424 
425  cur++;
426 
427  parser->root.cursor = cur;
428  T1_Skip_PS_Token( parser );
429  if ( parser->root.error )
430  return;
431 
432  len = parser->root.cursor - cur;
433 
434  parser->root.error = T1_Add_Table( char_table, charcode,
435  cur, len + 1 );
436  if ( parser->root.error )
437  return;
438  char_table->elements[charcode][len] = '\0';
439 
440  n++;
441  }
442  }
443  else
444  {
445  T1_Skip_PS_Token( parser );
446  if ( parser->root.error )
447  return;
448  }
449 
450  T1_Skip_Spaces( parser );
451  }
452 
453  face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
454  parser->root.cursor = cur;
455  }
456 
457  /* Otherwise, we should have either `StandardEncoding', */
458  /* `ExpertEncoding', or `ISOLatin1Encoding' */
459  else
460  {
461  if ( cur + 17 < limit &&
462  ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
463  face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
464 
465  else if ( cur + 15 < limit &&
466  ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
467  face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
468 
469  else if ( cur + 18 < limit &&
470  ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
471  face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
472 
473  else
474  {
475  FT_ERROR(( "t42_parse_encoding: invalid token\n" ));
476  parser->root.error = FT_THROW( Invalid_File_Format );
477  }
478  }
479  }
480 
481 
482  typedef enum T42_Load_Status_
483  {
487 
488  } T42_Load_Status;
489 
490 
491  static void
492  t42_parse_sfnts( T42_Face face,
493  T42_Loader loader )
494  {
495  T42_Parser parser = &loader->parser;
496  FT_Memory memory = parser->root.memory;
497  FT_Byte* cur;
498  FT_Byte* limit = parser->root.limit;
499  FT_Error error;
500  FT_Int num_tables = 0;
501  FT_ULong count, ttf_size = 0;
502 
503  FT_Long n, string_size, old_string_size, real_size;
504  FT_Byte* string_buf = NULL;
505  FT_Bool allocated = 0;
506 
507  T42_Load_Status status;
508 
509 
510  /* The format is */
511  /* */
512  /* /sfnts [ <hexstring> <hexstring> ... ] def */
513  /* */
514  /* or */
515  /* */
516  /* /sfnts [ */
517  /* <num_bin_bytes> RD <binary data> */
518  /* <num_bin_bytes> RD <binary data> */
519  /* ... */
520  /* ] def */
521  /* */
522  /* with exactly one space after the `RD' token. */
523 
524  T1_Skip_Spaces( parser );
525 
526  if ( parser->root.cursor >= limit || *parser->root.cursor++ != '[' )
527  {
528  FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector\n" ));
529  error = FT_THROW( Invalid_File_Format );
530  goto Fail;
531  }
532 
533  T1_Skip_Spaces( parser );
534  status = BEFORE_START;
535  string_size = 0;
536  old_string_size = 0;
537  count = 0;
538 
539  while ( parser->root.cursor < limit )
540  {
541  cur = parser->root.cursor;
542 
543  if ( *cur == ']' )
544  {
545  parser->root.cursor++;
546  goto Exit;
547  }
548 
549  else if ( *cur == '<' )
550  {
551  T1_Skip_PS_Token( parser );
552  if ( parser->root.error )
553  goto Exit;
554 
555  /* don't include delimiters */
556  string_size = (FT_Long)( ( parser->root.cursor - cur - 2 + 1 ) / 2 );
557  if ( FT_REALLOC( string_buf, old_string_size, string_size ) )
558  goto Fail;
559 
560  allocated = 1;
561 
562  parser->root.cursor = cur;
563  (void)T1_ToBytes( parser, string_buf, string_size, &real_size, 1 );
564  old_string_size = string_size;
565  string_size = real_size;
566  }
567 
568  else if ( ft_isdigit( *cur ) )
569  {
570  if ( allocated )
571  {
572  FT_ERROR(( "t42_parse_sfnts: "
573  "can't handle mixed binary and hex strings\n" ));
574  error = FT_THROW( Invalid_File_Format );
575  goto Fail;
576  }
577 
578  string_size = T1_ToInt( parser );
579  if ( string_size < 0 )
580  {
581  FT_ERROR(( "t42_parse_sfnts: invalid string size\n" ));
582  error = FT_THROW( Invalid_File_Format );
583  goto Fail;
584  }
585 
586  T1_Skip_PS_Token( parser ); /* `RD' */
587  if ( parser->root.error )
588  return;
589 
590  string_buf = parser->root.cursor + 1; /* one space after `RD' */
591 
592  if ( limit - parser->root.cursor < string_size )
593  {
594  FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));
595  error = FT_THROW( Invalid_File_Format );
596  goto Fail;
597  }
598  else
599  parser->root.cursor += string_size + 1;
600  }
601 
602  if ( !string_buf )
603  {
604  FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array\n" ));
605  error = FT_THROW( Invalid_File_Format );
606  goto Fail;
607  }
608 
609  /* A string can have a trailing zero (odd) byte for padding. */
610  /* Ignore it. */
611  if ( ( string_size & 1 ) && string_buf[string_size - 1] == 0 )
612  string_size--;
613 
614  if ( !string_size )
615  {
616  FT_ERROR(( "t42_parse_sfnts: invalid string\n" ));
617  error = FT_THROW( Invalid_File_Format );
618  goto Fail;
619  }
620 
621  for ( n = 0; n < string_size; n++ )
622  {
623  switch ( status )
624  {
625  case BEFORE_START:
626  /* load offset table, 12 bytes */
627  if ( count < 12 )
628  {
629  face->ttf_data[count++] = string_buf[n];
630  continue;
631  }
632  else
633  {
634  num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
635  status = BEFORE_TABLE_DIR;
636  ttf_size = 12 + 16 * num_tables;
637 
638  if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
639  goto Fail;
640  }
641  /* fall through */
642 
643  case BEFORE_TABLE_DIR:
644  /* the offset table is read; read the table directory */
645  if ( count < ttf_size )
646  {
647  face->ttf_data[count++] = string_buf[n];
648  continue;
649  }
650  else
651  {
652  int i;
653  FT_ULong len;
654 
655 
656  for ( i = 0; i < num_tables; i++ )
657  {
658  FT_Byte* p = face->ttf_data + 12 + 16 * i + 12;
659 
660 
661  len = FT_PEEK_ULONG( p );
662 
663  /* Pad to a 4-byte boundary length */
664  ttf_size += ( len + 3 ) & ~3;
665  }
666 
667  status = OTHER_TABLES;
668  face->ttf_size = ttf_size;
669 
670  /* there are no more than 256 tables, so no size check here */
671  if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
672  ttf_size + 1 ) )
673  goto Fail;
674  }
675  /* fall through */
676 
677  case OTHER_TABLES:
678  /* all other tables are just copied */
679  if ( count >= ttf_size )
680  {
681  FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));
682  error = FT_THROW( Invalid_File_Format );
683  goto Fail;
684  }
685  face->ttf_data[count++] = string_buf[n];
686  }
687  }
688 
689  T1_Skip_Spaces( parser );
690  }
691 
692  /* if control reaches this point, the format was not valid */
693  error = FT_THROW( Invalid_File_Format );
694 
695  Fail:
696  parser->root.error = error;
697 
698  Exit:
699  if ( allocated )
700  FT_FREE( string_buf );
701  }
702 
703 
704  static void
705  t42_parse_charstrings( T42_Face face,
706  T42_Loader loader )
707  {
708  T42_Parser parser = &loader->parser;
709  PS_Table code_table = &loader->charstrings;
710  PS_Table name_table = &loader->glyph_names;
711  PS_Table swap_table = &loader->swap_table;
712  FT_Memory memory = parser->root.memory;
713  FT_Error error;
714 
715  PSAux_Service psaux = (PSAux_Service)face->psaux;
716 
717  FT_Byte* cur;
718  FT_Byte* limit = parser->root.limit;
719  FT_UInt n;
720  FT_UInt notdef_index = 0;
721  FT_Byte notdef_found = 0;
722 
723 
724  T1_Skip_Spaces( parser );
725 
726  if ( parser->root.cursor >= limit )
727  {
728  FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
729  error = FT_THROW( Invalid_File_Format );
730  goto Fail;
731  }
732 
733  if ( ft_isdigit( *parser->root.cursor ) )
734  {
735  loader->num_glyphs = (FT_UInt)T1_ToInt( parser );
736  if ( parser->root.error )
737  return;
738  }
739  else if ( *parser->root.cursor == '<' )
740  {
741  /* We have `<< ... >>'. Count the number of `/' in the dictionary */
742  /* to get its size. */
743  FT_UInt count = 0;
744 
745 
746  T1_Skip_PS_Token( parser );
747  if ( parser->root.error )
748  return;
749  T1_Skip_Spaces( parser );
750  cur = parser->root.cursor;
751 
752  while ( parser->root.cursor < limit )
753  {
754  if ( *parser->root.cursor == '/' )
755  count++;
756  else if ( *parser->root.cursor == '>' )
757  {
758  loader->num_glyphs = count;
759  parser->root.cursor = cur; /* rewind */
760  break;
761  }
762  T1_Skip_PS_Token( parser );
763  if ( parser->root.error )
764  return;
765  T1_Skip_Spaces( parser );
766  }
767  }
768  else
769  {
770  FT_ERROR(( "t42_parse_charstrings: invalid token\n" ));
771  error = FT_THROW( Invalid_File_Format );
772  goto Fail;
773  }
774 
775  if ( parser->root.cursor >= limit )
776  {
777  FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
778  error = FT_THROW( Invalid_File_Format );
779  goto Fail;
780  }
781 
782  /* initialize tables */
783 
784  error = psaux->ps_table_funcs->init( code_table,
785  loader->num_glyphs,
786  memory );
787  if ( error )
788  goto Fail;
789 
790  error = psaux->ps_table_funcs->init( name_table,
791  loader->num_glyphs,
792  memory );
793  if ( error )
794  goto Fail;
795 
796  /* Initialize table for swapping index notdef_index and */
797  /* index 0 names and codes (if necessary). */
798 
799  error = psaux->ps_table_funcs->init( swap_table, 4, memory );
800  if ( error )
801  goto Fail;
802 
803  n = 0;
804 
805  for (;;)
806  {
807  /* The format is simple: */
808  /* `/glyphname' + index [+ def] */
809 
810  T1_Skip_Spaces( parser );
811 
812  cur = parser->root.cursor;
813  if ( cur >= limit )
814  break;
815 
816  /* We stop when we find an `end' keyword or '>' */
817  if ( *cur == 'e' &&
818  cur + 3 < limit &&
819  cur[1] == 'n' &&
820  cur[2] == 'd' &&
821  t42_is_space( cur[3] ) )
822  break;
823  if ( *cur == '>' )
824  break;
825 
826  T1_Skip_PS_Token( parser );
827  if ( parser->root.error )
828  return;
829 
830  if ( *cur == '/' )
831  {
832  FT_PtrDist len;
833 
834 
835  if ( cur + 1 >= limit )
836  {
837  FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
838  error = FT_THROW( Invalid_File_Format );
839  goto Fail;
840  }
841 
842  cur++; /* skip `/' */
843  len = parser->root.cursor - cur;
844 
845  error = T1_Add_Table( name_table, n, cur, len + 1 );
846  if ( error )
847  goto Fail;
848 
849  /* add a trailing zero to the name table */
850  name_table->elements[n][len] = '\0';
851 
852  /* record index of /.notdef */
853  if ( *cur == '.' &&
854  ft_strcmp( ".notdef",
855  (const char*)(name_table->elements[n]) ) == 0 )
856  {
857  notdef_index = n;
858  notdef_found = 1;
859  }
860 
861  T1_Skip_Spaces( parser );
862 
863  cur = parser->root.cursor;
864 
865  (void)T1_ToInt( parser );
866  if ( parser->root.cursor >= limit )
867  {
868  FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
869  error = FT_THROW( Invalid_File_Format );
870  goto Fail;
871  }
872 
873  len = parser->root.cursor - cur;
874 
875  error = T1_Add_Table( code_table, n, cur, len + 1 );
876  if ( error )
877  goto Fail;
878 
879  code_table->elements[n][len] = '\0';
880 
881  n++;
882  if ( n >= loader->num_glyphs )
883  break;
884  }
885  }
886 
887  loader->num_glyphs = n;
888 
889  if ( !notdef_found )
890  {
891  FT_ERROR(( "t42_parse_charstrings: no /.notdef glyph\n" ));
892  error = FT_THROW( Invalid_File_Format );
893  goto Fail;
894  }
895 
896  /* if /.notdef does not occupy index 0, do our magic. */
897  if ( ft_strcmp( (const char*)".notdef",
898  (const char*)name_table->elements[0] ) )
899  {
900  /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
901  /* name and code entries to swap_table. Then place notdef_index */
902  /* name and code entries into swap_table. Then swap name and code */
903  /* entries at indices notdef_index and 0 using values stored in */
904  /* swap_table. */
905 
906  /* Index 0 name */
907  error = T1_Add_Table( swap_table, 0,
908  name_table->elements[0],
909  name_table->lengths [0] );
910  if ( error )
911  goto Fail;
912 
913  /* Index 0 code */
914  error = T1_Add_Table( swap_table, 1,
915  code_table->elements[0],
916  code_table->lengths [0] );
917  if ( error )
918  goto Fail;
919 
920  /* Index notdef_index name */
921  error = T1_Add_Table( swap_table, 2,
922  name_table->elements[notdef_index],
923  name_table->lengths [notdef_index] );
924  if ( error )
925  goto Fail;
926 
927  /* Index notdef_index code */
928  error = T1_Add_Table( swap_table, 3,
929  code_table->elements[notdef_index],
930  code_table->lengths [notdef_index] );
931  if ( error )
932  goto Fail;
933 
934  error = T1_Add_Table( name_table, notdef_index,
935  swap_table->elements[0],
936  swap_table->lengths [0] );
937  if ( error )
938  goto Fail;
939 
940  error = T1_Add_Table( code_table, notdef_index,
941  swap_table->elements[1],
942  swap_table->lengths [1] );
943  if ( error )
944  goto Fail;
945 
946  error = T1_Add_Table( name_table, 0,
947  swap_table->elements[2],
948  swap_table->lengths [2] );
949  if ( error )
950  goto Fail;
951 
952  error = T1_Add_Table( code_table, 0,
953  swap_table->elements[3],
954  swap_table->lengths [3] );
955  if ( error )
956  goto Fail;
957 
958  }
959 
960  return;
961 
962  Fail:
963  parser->root.error = error;
964  }
965 
966 
967  static FT_Error
968  t42_load_keyword( T42_Face face,
969  T42_Loader loader,
970  T1_Field field )
971  {
972  FT_Error error;
973  void* dummy_object;
974  void** objects;
975  FT_UInt max_objects = 0;
976 
977 
978  /* if the keyword has a dedicated callback, call it */
979  if ( field->type == T1_FIELD_TYPE_CALLBACK )
980  {
981  field->reader( (FT_Face)face, loader );
982  error = loader->parser.root.error;
983  goto Exit;
984  }
985 
986  /* now the keyword is either a simple field or a table of fields; */
987  /* we are now going to take care of it */
988 
989  switch ( field->location )
990  {
992  dummy_object = &face->type1.font_info;
993  break;
994 
996  dummy_object = &face->type1.font_extra;
997  break;
998 
1000  dummy_object = &face->type1.font_bbox;
1001  break;
1002 
1003  default:
1004  dummy_object = &face->type1;
1005  }
1006 
1007  objects = &dummy_object;
1008 
1009  if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
1010  field->type == T1_FIELD_TYPE_FIXED_ARRAY )
1011  error = T1_Load_Field_Table( &loader->parser, field,
1012  objects, max_objects, 0 );
1013  else
1014  error = T1_Load_Field( &loader->parser, field,
1015  objects, max_objects, 0 );
1016 
1017  Exit:
1018  return error;
1019  }
1020 
1021 
1024  T42_Loader loader,
1025  FT_Byte* base,
1026  FT_Long size )
1027  {
1028  T42_Parser parser = &loader->parser;
1029  FT_Byte* limit;
1030  FT_Int n_keywords = (FT_Int)( sizeof ( t42_keywords ) /
1031  sizeof ( t42_keywords[0] ) );
1032 
1033 
1034  parser->root.cursor = base;
1035  parser->root.limit = base + size;
1036  parser->root.error = FT_Err_Ok;
1037 
1038  limit = parser->root.limit;
1039 
1040  T1_Skip_Spaces( parser );
1041 
1042  while ( parser->root.cursor < limit )
1043  {
1044  FT_Byte* cur;
1045 
1046 
1047  cur = parser->root.cursor;
1048 
1049  /* look for `FontDirectory' which causes problems for some fonts */
1050  if ( *cur == 'F' && cur + 25 < limit &&
1051  ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
1052  {
1053  FT_Byte* cur2;
1054 
1055 
1056  /* skip the `FontDirectory' keyword */
1057  T1_Skip_PS_Token( parser );
1058  T1_Skip_Spaces ( parser );
1059  cur = cur2 = parser->root.cursor;
1060 
1061  /* look up the `known' keyword */
1062  while ( cur < limit )
1063  {
1064  if ( *cur == 'k' && cur + 5 < limit &&
1065  ft_strncmp( (char*)cur, "known", 5 ) == 0 )
1066  break;
1067 
1068  T1_Skip_PS_Token( parser );
1069  if ( parser->root.error )
1070  goto Exit;
1071  T1_Skip_Spaces ( parser );
1072  cur = parser->root.cursor;
1073  }
1074 
1075  if ( cur < limit )
1076  {
1077  T1_TokenRec token;
1078 
1079 
1080  /* skip the `known' keyword and the token following it */
1081  T1_Skip_PS_Token( parser );
1082  T1_ToToken( parser, &token );
1083 
1084  /* if the last token was an array, skip it! */
1085  if ( token.type == T1_TOKEN_TYPE_ARRAY )
1086  cur2 = parser->root.cursor;
1087  }
1088  parser->root.cursor = cur2;
1089  }
1090 
1091  /* look for immediates */
1092  else if ( *cur == '/' && cur + 2 < limit )
1093  {
1094  FT_PtrDist len;
1095 
1096 
1097  cur++;
1098 
1099  parser->root.cursor = cur;
1100  T1_Skip_PS_Token( parser );
1101  if ( parser->root.error )
1102  goto Exit;
1103 
1104  len = parser->root.cursor - cur;
1105 
1106  if ( len > 0 && len < 22 && parser->root.cursor < limit )
1107  {
1108  int i;
1109 
1110 
1111  /* now compare the immediate name to the keyword table */
1112 
1113  /* loop through all known keywords */
1114  for ( i = 0; i < n_keywords; i++ )
1115  {
1116  T1_Field keyword = (T1_Field)&t42_keywords[i];
1117  FT_Byte *name = (FT_Byte*)keyword->ident;
1118 
1119 
1120  if ( !name )
1121  continue;
1122 
1123  if ( cur[0] == name[0] &&
1124  len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
1125  ft_memcmp( cur, name, len ) == 0 )
1126  {
1127  /* we found it -- run the parsing callback! */
1128  parser->root.error = t42_load_keyword( face,
1129  loader,
1130  keyword );
1131  if ( parser->root.error )
1132  return parser->root.error;
1133  break;
1134  }
1135  }
1136  }
1137  }
1138  else
1139  {
1140  T1_Skip_PS_Token( parser );
1141  if ( parser->root.error )
1142  goto Exit;
1143  }
1144 
1145  T1_Skip_Spaces( parser );
1146  }
1147 
1148  Exit:
1149  return parser->root.error;
1150  }
1151 
1152 
1153  FT_LOCAL_DEF( void )
1155  T42_Face face )
1156  {
1157  FT_UNUSED( face );
1158 
1159  FT_MEM_ZERO( loader, sizeof ( *loader ) );
1160  loader->num_glyphs = 0;
1161  loader->num_chars = 0;
1162 
1163  /* initialize the tables -- simply set their `init' field to 0 */
1164  loader->encoding_table.init = 0;
1165  loader->charstrings.init = 0;
1166  loader->glyph_names.init = 0;
1167  }
1168 
1169 
1170  FT_LOCAL_DEF( void )
1172  {
1173  T42_Parser parser = &loader->parser;
1174 
1175 
1176  /* finalize tables */
1177  T1_Release_Table( &loader->encoding_table );
1178  T1_Release_Table( &loader->charstrings );
1179  T1_Release_Table( &loader->glyph_names );
1180  T1_Release_Table( &loader->swap_table );
1181 
1182  /* finalize parser */
1183  t42_parser_done( parser );
1184  }
1185 
1186 
1187 /* END */
FT_UShort units_per_EM
Definition: freetype.h:945
const char * keyword
Definition: cdjpeg.h:149
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:260
int FT_Error
Definition: fttypes.h:296
FT_DivFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:586
GLuint GLuint stream
ft_ptrdiff_t FT_PtrDist
Definition: fttypes.h:333
#define T1_Add_Table(p, i, o, l)
Definition: t42parse.c:106
signed long FT_Long
Definition: fttypes.h:238
#define ft_strncmp
Definition: ftstdlib.h:88
unsigned long FT_ULong
Definition: fttypes.h:249
GLfloat GLfloat p
PS_TableRec charstrings
Definition: t42parse.h:51
t42_parser_done(T42_Parser parser)
Definition: t42parse.c:226
#define FT_MEM_ZERO(dest, count)
Definition: ftmemory.h:208
#define NULL
Definition: ftobjs.h:61
#define T1_Skip_PS_Token(p)
Definition: t42parse.c:121
FT_Fixed xy
Definition: fttypes.h:383
signed int FT_Int
Definition: fttypes.h:216
t42_parser_init(T42_Parser parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux)
Definition: t42parse.c:142
T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT underline_position
Definition: t1tokens.h:40
#define FT_ABS(a)
Definition: ftobjs.h:73
enum T42_Load_Status_ T42_Load_Status
return FT_THROW(Missing_Property)
#define T1_ToToken(p, t)
Definition: t42parse.c:130
PS_TableRec glyph_names
Definition: t42parse.h:50
#define FT_UNUSED(arg)
Definition: ftconfig.h:76
FT_BEGIN_HEADER struct T1_EncodingRecRec_ * T1_Encoding
T1_FIELD_DICT_PRIVATE T1_FIELD_DICT_PRIVATE T1_FIELD_DICT_PRIVATE T1_FIELD_DICT_PRIVATE T1_FIELD_DICT_PRIVATE T1_FIELD_DICT_PRIVATE T1_FIELD_DICT_PRIVATE T1_FIELD_DICT_PRIVATE T1_FIELD_FIXED("ExpansionFactor", expansion_factor, T1_FIELD_DICT_PRIVATE) T1_FIELD_BOOL("ForceBold"
const PS_Table_FuncsRec * ps_table_funcs
Definition: psaux.h:801
return FT_Err_Ok
Definition: ftbbox.c:645
#define T1_ToFixedArray(p, m, f, t)
Definition: t42parse.c:128
typedef void(APIENTRY *GLDEBUGPROCARB)(GLenum source
png_uint_32 i
Definition: png.h:2640
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:104
#define T1_Skip_Spaces(p)
Definition: t42parse.c:120
FT_BEGIN_HEADER struct T42_FaceRec_ * T42_Face
GLenum GLuint GLint GLenum face
#define ft_isdigit(x)
Definition: ftobjs.h:98
FT_UInt num_chars
Definition: t42parse.h:45
T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT T1_FIELD_BOOL("isFixedPitch", is_fixed_pitch, T1_FIELD_DICT_FONTDICT) T1_FIELD_NUM("UnderlinePosition"
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
unsigned char FT_Byte
Definition: fttypes.h:150
#define FT_PEEK_ULONG(p)
Definition: ftstream.h:179
#define FT_FREE(ptr)
Definition: ftmemory.h:286
PS_TableRec swap_table
Definition: t42parse.h:52
#define FT_STREAM_SKIP(distance)
Definition: ftstream.h:492
struct T1_FieldRec_ * T1_Field
Definition: psaux.h:150
GLenum GLsizei len
FT_Memory memory
Definition: psaux.h:132
#define T1_FIELD_NUM(_ident, _fname, _dict)
Definition: psaux.h:292
#define T1_FIELD_KEY(_ident, _fname, _dict)
Definition: psaux.h:305
FT_Error error
Definition: cffdrivr.c:411
#define T1_Release_Table(p)
Definition: t42parse.c:113
FT_Pos x
Definition: ftimage.h:77
#define T1_FIELD_CALLBACK(_ident, _name, _dict)
Definition: psaux.h:328
FT_Pos y
Definition: ftimage.h:78
struct PSAux_ServiceRec_ * PSAux_Service
FT_UInt num_glyphs
Definition: t42parse.h:49
GLdouble n
#define FT_TRACE2(varformat)
Definition: ftdebug.h:159
struct FT_FaceRec_ * FT_Face
Definition: freetype.h:403
T42_Load_Status_
Definition: t42parse.c:482
const GLubyte * c
local int root
Definition: enough.c:171
int const char * version
Definition: zlib.h:813
PS_TableRec encoding_table
Definition: t42parse.h:46
#define T1_ToBytes(p, b, m, n, d)
Definition: t42parse.c:125
GLintptr offset
#define T1_Load_Field_Table(p, f, o, m, pf)
Definition: t42parse.c:135
T1_FieldType type
Definition: psaux.h:228
const char * ident
Definition: psaux.h:226
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
FT_Fixed xx
Definition: fttypes.h:383
#define FT_FRAME_EXIT()
Definition: ftstream.h:514
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:290
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:489
GLuint const GLchar * name
if(!abbox) return FT_THROW(Invalid_Argument)
typedefFT_BEGIN_HEADER struct PS_TableRec_ * PS_Table
Definition: psaux.h:42
#define FT_TRACE6(varformat)
Definition: ftdebug.h:163
FT_Fixed yx
Definition: fttypes.h:384
t42_parse_dict(T42_Face face, T42_Loader loader, FT_Byte *base, FT_Long size)
Definition: t42parse.c:1023
FT_BEGIN_HEADER struct T42_ParserRec_ * T42_Parser
signed long FT_Fixed
Definition: fttypes.h:284
notice
Definition: t1tokens.h:26
#define FT_REALLOC(ptr, cursz, newsz)
Definition: ftmemory.h:263
#define FT_SET_ERROR(expression)
Definition: ftmemory.h:42
#define ft_memcmp
Definition: ftstdlib.h:80
t42_loader_done(T42_Loader loader)
Definition: t42parse.c:1171
T1_Field_ParseFunc reader
Definition: psaux.h:229
unsigned int FT_UInt
Definition: fttypes.h:227
#define T1_Load_Field(p, f, o, m, pf)
Definition: t42parse.c:133
T1_FieldLocation location
Definition: psaux.h:227
GLuint GLuint GLsizei count
#define T1_ToInt(p)
Definition: t42parse.c:123
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:510
FT_Fixed yy
Definition: fttypes.h:384
T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT italic_angle
Definition: t1tokens.h:36
bbox xMin
Definition: ftbbox.c:589
FT_Error(* init)(PS_Table table, FT_Int count, FT_Memory memory)
Definition: psaux.h:66
T1_FIELD_DICT_FONTDICT family_name
Definition: t1tokens.h:30
T1_TokenType type
Definition: psaux.h:173
t42_loader_init(T42_Loader loader, T42_Face face)
Definition: t42parse.c:1154
unsigned short FT_UShort
Definition: fttypes.h:205
T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT fs_type
Definition: t1tokens.h:50
GLuint GLuint GLfloat weight
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:495
GLsizeiptr size
GLuint GLenum matrix
#define ft_strlen
Definition: ftstdlib.h:87
T42_ParserRec parser
Definition: t42parse.h:43
GLint limit
#define T1_FIELD_BBOX(_ident, _fname, _dict)
Definition: psaux.h:308
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:236
#define T1_FIELD_STRING(_ident, _fname, _dict)
Definition: psaux.h:302
#define ft_strcmp
Definition: ftstdlib.h:85