zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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-2012 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
38  T42_Loader loader );
39  static void
41  T42_Loader loader );
42 
43  static void
45  T42_Loader loader );
46 
47  static void
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
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  {
147  FT_Error error = T42_Err_Ok;
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 = T42_Err_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
241  {
242  return ( c == ' ' || c == '\t' ||
243  c == '\r' || c == '\n' || c == '\f' ||
244  c == '\0' );
245  }
246 
247 
248  static void
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 * 0x10000L,
269  temp_scale ) >> 16 );
270 
271  /* we need to scale the values by 1.0/temp_scale */
272  if ( temp_scale != 0x10000L )
273  {
274  temp[0] = FT_DivFix( temp[0], temp_scale );
275  temp[1] = FT_DivFix( temp[1], temp_scale );
276  temp[2] = FT_DivFix( temp[2], temp_scale );
277  temp[4] = FT_DivFix( temp[4], temp_scale );
278  temp[5] = FT_DivFix( temp[5], temp_scale );
279  temp[3] = 0x10000L;
280  }
281 
282  matrix->xx = temp[0];
283  matrix->yx = temp[1];
284  matrix->xy = temp[2];
285  matrix->yy = temp[3];
286 
287  /* note that the offsets must be expressed in integer font units */
288  offset->x = temp[4] >> 16;
289  offset->y = temp[5] >> 16;
290  }
291 
292 
293  static void
295  T42_Loader loader )
296  {
297  T42_Parser parser = &loader->parser;
298  FT_Byte* cur;
299  FT_Byte* limit = parser->root.limit;
300 
301  PSAux_Service psaux = (PSAux_Service)face->psaux;
302 
303 
304  T1_Skip_Spaces( parser );
305  cur = parser->root.cursor;
306  if ( cur >= limit )
307  {
308  FT_ERROR(( "t42_parse_encoding: out of bounds\n" ));
309  parser->root.error = T42_Err_Invalid_File_Format;
310  return;
311  }
312 
313  /* if we have a number or `[', the encoding is an array, */
314  /* and we must load it now */
315  if ( ft_isdigit( *cur ) || *cur == '[' )
316  {
317  T1_Encoding encode = &face->type1.encoding;
318  FT_UInt count, n;
319  PS_Table char_table = &loader->encoding_table;
320  FT_Memory memory = parser->root.memory;
321  FT_Error error;
322  FT_Bool only_immediates = 0;
323 
324 
325  /* read the number of entries in the encoding; should be 256 */
326  if ( *cur == '[' )
327  {
328  count = 256;
329  only_immediates = 1;
330  parser->root.cursor++;
331  }
332  else
333  count = (FT_UInt)T1_ToInt( parser );
334 
335  T1_Skip_Spaces( parser );
336  if ( parser->root.cursor >= limit )
337  return;
338 
339  /* we use a T1_Table to store our charnames */
340  loader->num_chars = encode->num_chars = count;
341  if ( FT_NEW_ARRAY( encode->char_index, count ) ||
342  FT_NEW_ARRAY( encode->char_name, count ) ||
344  char_table, count, memory ) ) )
345  {
346  parser->root.error = error;
347  return;
348  }
349 
350  /* We need to `zero' out encoding_table.elements */
351  for ( n = 0; n < count; n++ )
352  {
353  char* notdef = (char *)".notdef";
354 
355 
356  T1_Add_Table( char_table, n, notdef, 8 );
357  }
358 
359  /* Now we need to read records of the form */
360  /* */
361  /* ... charcode /charname ... */
362  /* */
363  /* for each entry in our table. */
364  /* */
365  /* We simply look for a number followed by an immediate */
366  /* name. Note that this ignores correctly the sequence */
367  /* that is often seen in type42 fonts: */
368  /* */
369  /* 0 1 255 { 1 index exch /.notdef put } for dup */
370  /* */
371  /* used to clean the encoding array before anything else. */
372  /* */
373  /* Alternatively, if the array is directly given as */
374  /* */
375  /* /Encoding [ ... ] */
376  /* */
377  /* we only read immediates. */
378 
379  n = 0;
380  T1_Skip_Spaces( parser );
381 
382  while ( parser->root.cursor < limit )
383  {
384  cur = parser->root.cursor;
385 
386  /* we stop when we encounter `def' or `]' */
387  if ( *cur == 'd' && cur + 3 < limit )
388  {
389  if ( cur[1] == 'e' &&
390  cur[2] == 'f' &&
391  t42_is_space( cur[3] ) )
392  {
393  FT_TRACE6(( "encoding end\n" ));
394  cur += 3;
395  break;
396  }
397  }
398  if ( *cur == ']' )
399  {
400  FT_TRACE6(( "encoding end\n" ));
401  cur++;
402  break;
403  }
404 
405  /* check whether we have found an entry */
406  if ( ft_isdigit( *cur ) || only_immediates )
407  {
408  FT_Int charcode;
409 
410 
411  if ( only_immediates )
412  charcode = n;
413  else
414  {
415  charcode = (FT_Int)T1_ToInt( parser );
416  T1_Skip_Spaces( parser );
417  }
418 
419  cur = parser->root.cursor;
420 
421  if ( *cur == '/' && cur + 2 < limit && n < count )
422  {
423  FT_PtrDist len;
424 
425 
426  cur++;
427 
428  parser->root.cursor = cur;
429  T1_Skip_PS_Token( parser );
430  if ( parser->root.error )
431  return;
432 
433  len = parser->root.cursor - cur;
434 
435  parser->root.error = T1_Add_Table( char_table, charcode,
436  cur, len + 1 );
437  if ( parser->root.error )
438  return;
439  char_table->elements[charcode][len] = '\0';
440 
441  n++;
442  }
443  }
444  else
445  {
446  T1_Skip_PS_Token( parser );
447  if ( parser->root.error )
448  return;
449  }
450 
451  T1_Skip_Spaces( parser );
452  }
453 
454  face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
455  parser->root.cursor = cur;
456  }
457 
458  /* Otherwise, we should have either `StandardEncoding', */
459  /* `ExpertEncoding', or `ISOLatin1Encoding' */
460  else
461  {
462  if ( cur + 17 < limit &&
463  ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
464  face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
465 
466  else if ( cur + 15 < limit &&
467  ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
468  face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
469 
470  else if ( cur + 18 < limit &&
471  ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
472  face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
473 
474  else
475  {
476  FT_ERROR(( "t42_parse_encoding: invalid token\n" ));
477  parser->root.error = T42_Err_Invalid_File_Format;
478  }
479  }
480  }
481 
482 
483  typedef enum T42_Load_Status_
484  {
488 
489  } T42_Load_Status;
490 
491 
492  static void
494  T42_Loader loader )
495  {
496  T42_Parser parser = &loader->parser;
497  FT_Memory memory = parser->root.memory;
498  FT_Byte* cur;
499  FT_Byte* limit = parser->root.limit;
500  FT_Error error;
501  FT_Int num_tables = 0;
502  FT_ULong count, ttf_size = 0;
503 
504  FT_Long n, string_size, old_string_size, real_size;
505  FT_Byte* string_buf = NULL;
506  FT_Bool allocated = 0;
507 
508  T42_Load_Status status;
509 
510 
511  /* The format is */
512  /* */
513  /* /sfnts [ <hexstring> <hexstring> ... ] def */
514  /* */
515  /* or */
516  /* */
517  /* /sfnts [ */
518  /* <num_bin_bytes> RD <binary data> */
519  /* <num_bin_bytes> RD <binary data> */
520  /* ... */
521  /* ] def */
522  /* */
523  /* with exactly one space after the `RD' token. */
524 
525  T1_Skip_Spaces( parser );
526 
527  if ( parser->root.cursor >= limit || *parser->root.cursor++ != '[' )
528  {
529  FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector\n" ));
530  error = T42_Err_Invalid_File_Format;
531  goto Fail;
532  }
533 
534  T1_Skip_Spaces( parser );
535  status = BEFORE_START;
536  string_size = 0;
537  old_string_size = 0;
538  count = 0;
539 
540  while ( parser->root.cursor < limit )
541  {
542  cur = parser->root.cursor;
543 
544  if ( *cur == ']' )
545  {
546  parser->root.cursor++;
547  goto Exit;
548  }
549 
550  else if ( *cur == '<' )
551  {
552  T1_Skip_PS_Token( parser );
553  if ( parser->root.error )
554  goto Exit;
555 
556  /* don't include delimiters */
557  string_size = (FT_Long)( ( parser->root.cursor - cur - 2 + 1 ) / 2 );
558  if ( FT_REALLOC( string_buf, old_string_size, string_size ) )
559  goto Fail;
560 
561  allocated = 1;
562 
563  parser->root.cursor = cur;
564  (void)T1_ToBytes( parser, string_buf, string_size, &real_size, 1 );
565  old_string_size = string_size;
566  string_size = real_size;
567  }
568 
569  else if ( ft_isdigit( *cur ) )
570  {
571  if ( allocated )
572  {
573  FT_ERROR(( "t42_parse_sfnts: "
574  "can't handle mixed binary and hex strings\n" ));
575  error = T42_Err_Invalid_File_Format;
576  goto Fail;
577  }
578 
579  string_size = T1_ToInt( parser );
580  if ( string_size < 0 )
581  {
582  FT_ERROR(( "t42_parse_sfnts: invalid string size\n" ));
583  error = T42_Err_Invalid_File_Format;
584  goto Fail;
585  }
586 
587  T1_Skip_PS_Token( parser ); /* `RD' */
588  if ( parser->root.error )
589  return;
590 
591  string_buf = parser->root.cursor + 1; /* one space after `RD' */
592 
593  if ( limit - parser->root.cursor < string_size )
594  {
595  FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));
596  error = T42_Err_Invalid_File_Format;
597  goto Fail;
598  }
599  else
600  parser->root.cursor += string_size + 1;
601  }
602 
603  if ( !string_buf )
604  {
605  FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array\n" ));
606  error = T42_Err_Invalid_File_Format;
607  goto Fail;
608  }
609 
610  /* A string can have a trailing zero (odd) byte for padding. */
611  /* Ignore it. */
612  if ( ( string_size & 1 ) && string_buf[string_size - 1] == 0 )
613  string_size--;
614 
615  if ( !string_size )
616  {
617  FT_ERROR(( "t42_parse_sfnts: invalid string\n" ));
618  error = T42_Err_Invalid_File_Format;
619  goto Fail;
620  }
621 
622  for ( n = 0; n < string_size; n++ )
623  {
624  switch ( status )
625  {
626  case BEFORE_START:
627  /* load offset table, 12 bytes */
628  if ( count < 12 )
629  {
630  face->ttf_data[count++] = string_buf[n];
631  continue;
632  }
633  else
634  {
635  num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
636  status = BEFORE_TABLE_DIR;
637  ttf_size = 12 + 16 * num_tables;
638 
639  if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
640  goto Fail;
641  }
642  /* fall through */
643 
644  case BEFORE_TABLE_DIR:
645  /* the offset table is read; read the table directory */
646  if ( count < ttf_size )
647  {
648  face->ttf_data[count++] = string_buf[n];
649  continue;
650  }
651  else
652  {
653  int i;
654  FT_ULong len;
655 
656 
657  for ( i = 0; i < num_tables; i++ )
658  {
659  FT_Byte* p = face->ttf_data + 12 + 16 * i + 12;
660 
661 
662  len = FT_PEEK_ULONG( p );
663 
664  /* Pad to a 4-byte boundary length */
665  ttf_size += ( len + 3 ) & ~3;
666  }
667 
668  status = OTHER_TABLES;
669  face->ttf_size = ttf_size;
670 
671  /* there are no more than 256 tables, so no size check here */
672  if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
673  ttf_size + 1 ) )
674  goto Fail;
675  }
676  /* fall through */
677 
678  case OTHER_TABLES:
679  /* all other tables are just copied */
680  if ( count >= ttf_size )
681  {
682  FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));
683  error = T42_Err_Invalid_File_Format;
684  goto Fail;
685  }
686  face->ttf_data[count++] = string_buf[n];
687  }
688  }
689 
690  T1_Skip_Spaces( parser );
691  }
692 
693  /* if control reaches this point, the format was not valid */
694  error = T42_Err_Invalid_File_Format;
695 
696  Fail:
697  parser->root.error = error;
698 
699  Exit:
700  if ( allocated )
701  FT_FREE( string_buf );
702  }
703 
704 
705  static void
707  T42_Loader loader )
708  {
709  T42_Parser parser = &loader->parser;
710  PS_Table code_table = &loader->charstrings;
711  PS_Table name_table = &loader->glyph_names;
712  PS_Table swap_table = &loader->swap_table;
713  FT_Memory memory = parser->root.memory;
714  FT_Error error;
715 
716  PSAux_Service psaux = (PSAux_Service)face->psaux;
717 
718  FT_Byte* cur;
719  FT_Byte* limit = parser->root.limit;
720  FT_UInt n;
721  FT_UInt notdef_index = 0;
722  FT_Byte notdef_found = 0;
723 
724 
725  T1_Skip_Spaces( parser );
726 
727  if ( parser->root.cursor >= limit )
728  {
729  FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
730  error = T42_Err_Invalid_File_Format;
731  goto Fail;
732  }
733 
734  if ( ft_isdigit( *parser->root.cursor ) )
735  {
736  loader->num_glyphs = (FT_UInt)T1_ToInt( parser );
737  if ( parser->root.error )
738  return;
739  }
740  else if ( *parser->root.cursor == '<' )
741  {
742  /* We have `<< ... >>'. Count the number of `/' in the dictionary */
743  /* to get its size. */
744  FT_UInt count = 0;
745 
746 
747  T1_Skip_PS_Token( parser );
748  if ( parser->root.error )
749  return;
750  T1_Skip_Spaces( parser );
751  cur = parser->root.cursor;
752 
753  while ( parser->root.cursor < limit )
754  {
755  if ( *parser->root.cursor == '/' )
756  count++;
757  else if ( *parser->root.cursor == '>' )
758  {
759  loader->num_glyphs = count;
760  parser->root.cursor = cur; /* rewind */
761  break;
762  }
763  T1_Skip_PS_Token( parser );
764  if ( parser->root.error )
765  return;
766  T1_Skip_Spaces( parser );
767  }
768  }
769  else
770  {
771  FT_ERROR(( "t42_parse_charstrings: invalid token\n" ));
772  error = T42_Err_Invalid_File_Format;
773  goto Fail;
774  }
775 
776  if ( parser->root.cursor >= limit )
777  {
778  FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
779  error = T42_Err_Invalid_File_Format;
780  goto Fail;
781  }
782 
783  /* initialize tables */
784 
785  error = psaux->ps_table_funcs->init( code_table,
786  loader->num_glyphs,
787  memory );
788  if ( error )
789  goto Fail;
790 
791  error = psaux->ps_table_funcs->init( name_table,
792  loader->num_glyphs,
793  memory );
794  if ( error )
795  goto Fail;
796 
797  /* Initialize table for swapping index notdef_index and */
798  /* index 0 names and codes (if necessary). */
799 
800  error = psaux->ps_table_funcs->init( swap_table, 4, memory );
801  if ( error )
802  goto Fail;
803 
804  n = 0;
805 
806  for (;;)
807  {
808  /* The format is simple: */
809  /* `/glyphname' + index [+ def] */
810 
811  T1_Skip_Spaces( parser );
812 
813  cur = parser->root.cursor;
814  if ( cur >= limit )
815  break;
816 
817  /* We stop when we find an `end' keyword or '>' */
818  if ( *cur == 'e' &&
819  cur + 3 < limit &&
820  cur[1] == 'n' &&
821  cur[2] == 'd' &&
822  t42_is_space( cur[3] ) )
823  break;
824  if ( *cur == '>' )
825  break;
826 
827  T1_Skip_PS_Token( parser );
828  if ( parser->root.error )
829  return;
830 
831  if ( *cur == '/' )
832  {
833  FT_PtrDist len;
834 
835 
836  if ( cur + 1 >= limit )
837  {
838  FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
839  error = T42_Err_Invalid_File_Format;
840  goto Fail;
841  }
842 
843  cur++; /* skip `/' */
844  len = parser->root.cursor - cur;
845 
846  error = T1_Add_Table( name_table, n, cur, len + 1 );
847  if ( error )
848  goto Fail;
849 
850  /* add a trailing zero to the name table */
851  name_table->elements[n][len] = '\0';
852 
853  /* record index of /.notdef */
854  if ( *cur == '.' &&
855  ft_strcmp( ".notdef",
856  (const char*)(name_table->elements[n]) ) == 0 )
857  {
858  notdef_index = n;
859  notdef_found = 1;
860  }
861 
862  T1_Skip_Spaces( parser );
863 
864  cur = parser->root.cursor;
865 
866  (void)T1_ToInt( parser );
867  if ( parser->root.cursor >= limit )
868  {
869  FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
870  error = T42_Err_Invalid_File_Format;
871  goto Fail;
872  }
873 
874  len = parser->root.cursor - cur;
875 
876  error = T1_Add_Table( code_table, n, cur, len + 1 );
877  if ( error )
878  goto Fail;
879 
880  code_table->elements[n][len] = '\0';
881 
882  n++;
883  if ( n >= loader->num_glyphs )
884  break;
885  }
886  }
887 
888  loader->num_glyphs = n;
889 
890  if ( !notdef_found )
891  {
892  FT_ERROR(( "t42_parse_charstrings: no /.notdef glyph\n" ));
893  error = T42_Err_Invalid_File_Format;
894  goto Fail;
895  }
896 
897  /* if /.notdef does not occupy index 0, do our magic. */
898  if ( ft_strcmp( (const char*)".notdef",
899  (const char*)name_table->elements[0] ) )
900  {
901  /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
902  /* name and code entries to swap_table. Then place notdef_index */
903  /* name and code entries into swap_table. Then swap name and code */
904  /* entries at indices notdef_index and 0 using values stored in */
905  /* swap_table. */
906 
907  /* Index 0 name */
908  error = T1_Add_Table( swap_table, 0,
909  name_table->elements[0],
910  name_table->lengths [0] );
911  if ( error )
912  goto Fail;
913 
914  /* Index 0 code */
915  error = T1_Add_Table( swap_table, 1,
916  code_table->elements[0],
917  code_table->lengths [0] );
918  if ( error )
919  goto Fail;
920 
921  /* Index notdef_index name */
922  error = T1_Add_Table( swap_table, 2,
923  name_table->elements[notdef_index],
924  name_table->lengths [notdef_index] );
925  if ( error )
926  goto Fail;
927 
928  /* Index notdef_index code */
929  error = T1_Add_Table( swap_table, 3,
930  code_table->elements[notdef_index],
931  code_table->lengths [notdef_index] );
932  if ( error )
933  goto Fail;
934 
935  error = T1_Add_Table( name_table, notdef_index,
936  swap_table->elements[0],
937  swap_table->lengths [0] );
938  if ( error )
939  goto Fail;
940 
941  error = T1_Add_Table( code_table, notdef_index,
942  swap_table->elements[1],
943  swap_table->lengths [1] );
944  if ( error )
945  goto Fail;
946 
947  error = T1_Add_Table( name_table, 0,
948  swap_table->elements[2],
949  swap_table->lengths [2] );
950  if ( error )
951  goto Fail;
952 
953  error = T1_Add_Table( code_table, 0,
954  swap_table->elements[3],
955  swap_table->lengths [3] );
956  if ( error )
957  goto Fail;
958 
959  }
960 
961  return;
962 
963  Fail:
964  parser->root.error = error;
965  }
966 
967 
968  static FT_Error
970  T42_Loader loader,
971  T1_Field field )
972  {
973  FT_Error error;
974  void* dummy_object;
975  void** objects;
976  FT_UInt max_objects = 0;
977 
978 
979  /* if the keyword has a dedicated callback, call it */
980  if ( field->type == T1_FIELD_TYPE_CALLBACK )
981  {
982  field->reader( (FT_Face)face, loader );
983  error = loader->parser.root.error;
984  goto Exit;
985  }
986 
987  /* now the keyword is either a simple field or a table of fields; */
988  /* we are now going to take care of it */
989 
990  switch ( field->location )
991  {
993  dummy_object = &face->type1.font_info;
994  break;
995 
997  dummy_object = &face->type1.font_extra;
998  break;
999 
1001  dummy_object = &face->type1.font_bbox;
1002  break;
1003 
1004  default:
1005  dummy_object = &face->type1;
1006  }
1007 
1008  objects = &dummy_object;
1009 
1010  if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
1011  field->type == T1_FIELD_TYPE_FIXED_ARRAY )
1012  error = T1_Load_Field_Table( &loader->parser, field,
1013  objects, max_objects, 0 );
1014  else
1015  error = T1_Load_Field( &loader->parser, field,
1016  objects, max_objects, 0 );
1017 
1018  Exit:
1019  return error;
1020  }
1021 
1022 
1025  T42_Loader loader,
1026  FT_Byte* base,
1027  FT_Long size )
1028  {
1029  T42_Parser parser = &loader->parser;
1030  FT_Byte* limit;
1031  FT_Int n_keywords = (FT_Int)( sizeof ( t42_keywords ) /
1032  sizeof ( t42_keywords[0] ) );
1033 
1034 
1035  parser->root.cursor = base;
1036  parser->root.limit = base + size;
1037  parser->root.error = T42_Err_Ok;
1038 
1039  limit = parser->root.limit;
1040 
1041  T1_Skip_Spaces( parser );
1042 
1043  while ( parser->root.cursor < limit )
1044  {
1045  FT_Byte* cur;
1046 
1047 
1048  cur = parser->root.cursor;
1049 
1050  /* look for `FontDirectory' which causes problems for some fonts */
1051  if ( *cur == 'F' && cur + 25 < limit &&
1052  ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
1053  {
1054  FT_Byte* cur2;
1055 
1056 
1057  /* skip the `FontDirectory' keyword */
1058  T1_Skip_PS_Token( parser );
1059  T1_Skip_Spaces ( parser );
1060  cur = cur2 = parser->root.cursor;
1061 
1062  /* look up the `known' keyword */
1063  while ( cur < limit )
1064  {
1065  if ( *cur == 'k' && cur + 5 < limit &&
1066  ft_strncmp( (char*)cur, "known", 5 ) == 0 )
1067  break;
1068 
1069  T1_Skip_PS_Token( parser );
1070  if ( parser->root.error )
1071  goto Exit;
1072  T1_Skip_Spaces ( parser );
1073  cur = parser->root.cursor;
1074  }
1075 
1076  if ( cur < limit )
1077  {
1078  T1_TokenRec token;
1079 
1080 
1081  /* skip the `known' keyword and the token following it */
1082  T1_Skip_PS_Token( parser );
1083  T1_ToToken( parser, &token );
1084 
1085  /* if the last token was an array, skip it! */
1086  if ( token.type == T1_TOKEN_TYPE_ARRAY )
1087  cur2 = parser->root.cursor;
1088  }
1089  parser->root.cursor = cur2;
1090  }
1091 
1092  /* look for immediates */
1093  else if ( *cur == '/' && cur + 2 < limit )
1094  {
1095  FT_PtrDist len;
1096 
1097 
1098  cur++;
1099 
1100  parser->root.cursor = cur;
1101  T1_Skip_PS_Token( parser );
1102  if ( parser->root.error )
1103  goto Exit;
1104 
1105  len = parser->root.cursor - cur;
1106 
1107  if ( len > 0 && len < 22 && parser->root.cursor < limit )
1108  {
1109  int i;
1110 
1111 
1112  /* now compare the immediate name to the keyword table */
1113 
1114  /* loop through all known keywords */
1115  for ( i = 0; i < n_keywords; i++ )
1116  {
1117  T1_Field keyword = (T1_Field)&t42_keywords[i];
1118  FT_Byte *name = (FT_Byte*)keyword->ident;
1119 
1120 
1121  if ( !name )
1122  continue;
1123 
1124  if ( cur[0] == name[0] &&
1125  len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
1126  ft_memcmp( cur, name, len ) == 0 )
1127  {
1128  /* we found it -- run the parsing callback! */
1129  parser->root.error = t42_load_keyword( face,
1130  loader,
1131  keyword );
1132  if ( parser->root.error )
1133  return parser->root.error;
1134  break;
1135  }
1136  }
1137  }
1138  }
1139  else
1140  {
1141  T1_Skip_PS_Token( parser );
1142  if ( parser->root.error )
1143  goto Exit;
1144  }
1145 
1146  T1_Skip_Spaces( parser );
1147  }
1148 
1149  Exit:
1150  return parser->root.error;
1151  }
1152 
1153 
1154  FT_LOCAL_DEF( void )
1156  T42_Face face )
1157  {
1158  FT_UNUSED( face );
1159 
1160  FT_MEM_ZERO( loader, sizeof ( *loader ) );
1161  loader->num_glyphs = 0;
1162  loader->num_chars = 0;
1163 
1164  /* initialize the tables -- simply set their `init' field to 0 */
1165  loader->encoding_table.init = 0;
1166  loader->charstrings.init = 0;
1167  loader->glyph_names.init = 0;
1168  }
1169 
1170 
1171  FT_LOCAL_DEF( void )
1173  {
1174  T42_Parser parser = &loader->parser;
1175 
1176 
1177  /* finalize tables */
1178  T1_Release_Table( &loader->encoding_table );
1179  T1_Release_Table( &loader->charstrings );
1180  T1_Release_Table( &loader->glyph_names );
1181  T1_Release_Table( &loader->swap_table );
1182 
1183  /* finalize parser */
1184  t42_parser_done( parser );
1185  }
1186 
1187 
1188 /* END */
FT_UShort units_per_EM
Definition: freetype.h:938
static void t42_parse_encoding(T42_Face face, T42_Loader loader)
Definition: t42parse.c:294
#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:536
ft_ptrdiff_t FT_PtrDist
Definition: fttypes.h:333
static const T1_FieldRec t42_keywords[]
Definition: t42parse.c:55
#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
PS_TableRec charstrings
Definition: t42parse.h:51
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
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
GLuint GLuint stream
Definition: glew.h:6573
GLclampd n
Definition: glew.h:7287
enum T42_Load_Status_ T42_Load_Status
#define T1_ToToken(p, t)
Definition: t42parse.c:130
PS_TableRec glyph_names
Definition: t42parse.h:50
FT_BEGIN_HEADER struct T1_EncodingRecRec_ * T1_Encoding
int const char * version
Definition: zlib.h:813
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:797
EGLImageKHR EGLint * name
Definition: eglext.h:284
#define T1_ToFixedArray(p, m, f, t)
Definition: t42parse.c:128
GLenum GLsizei len
Definition: glew.h:7035
GLuint GLuint GLfloat weight
Definition: glew.h:12401
if(!yyg->yy_init)
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
static void t42_parse_charstrings(T42_Face face, T42_Loader loader)
Definition: t42parse.c:706
#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
FT_Error(* init)(PS_Table table, FT_Int count, FT_Memory memory)
Definition: psaux.h:66
#define FT_PEEK_ULONG(p)
Definition: ftstream.h:186
#define FT_FREE(ptr)
Definition: ftmemory.h:286
PS_TableRec swap_table
Definition: t42parse.h:52
static int t42_is_space(FT_Byte c)
Definition: t42parse.c:240
#define FT_STREAM_SKIP(distance)
Definition: ftstream.h:499
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:467
struct T1_FieldRec_ * T1_Field
Definition: psaux.h:147
static FT_Error t42_load_keyword(T42_Face face, T42_Loader loader, T1_Field field)
Definition: t42parse.c:969
FT_Memory memory
Definition: psaux.h:129
#define T1_FIELD_NUM(_ident, _fname, _dict)
Definition: psaux.h:288
#define T1_FIELD_KEY(_ident, _fname, _dict)
Definition: psaux.h:301
FT_Error error
Definition: cffdrivr.c:407
#define T1_Release_Table(p)
Definition: t42parse.c:113
FT_Pos x
Definition: ftimage.h:77
GLint GLsizei count
Definition: gl2ext.h:1011
GLenum face
Definition: gl2ext.h:1490
GLfloat GLfloat p
Definition: glew.h:14938
#define T1_FIELD_CALLBACK(_ident, _name, _dict)
Definition: psaux.h:324
FT_Pos y
Definition: ftimage.h:78
const GLfloat * c
Definition: glew.h:14913
struct PSAux_ServiceRec_ * PSAux_Service
FT_UInt num_glyphs
Definition: t42parse.h:49
#define FT_TRACE2(varformat)
Definition: ftdebug.h:159
struct FT_FaceRec_ * FT_Face
Definition: freetype.h:399
T42_Load_Status_
Definition: t42parse.c:483
GLint limit
Definition: glew.h:11829
PS_TableRec encoding_table
Definition: t42parse.h:46
#define T1_ToBytes(p, b, m, n, d)
Definition: t42parse.c:125
static void t42_parse_sfnts(T42_Face face, T42_Loader loader)
Definition: t42parse.c:493
#define T1_Load_Field_Table(p, f, o, m, pf)
Definition: t42parse.c:135
GLuint GLenum matrix
Definition: glew.h:13408
T1_FieldType type
Definition: psaux.h:224
const char * ident
Definition: psaux.h:222
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:521
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:290
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:496
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:1024
FT_BEGIN_HEADER struct T42_ParserRec_ * T42_Parser
GLintptr offset
Definition: glew.h:1668
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:1172
T1_Field_ParseFunc reader
Definition: psaux.h:225
unsigned int FT_UInt
Definition: fttypes.h:227
#define T1_Load_Field(p, f, o, m, pf)
Definition: t42parse.c:133
static void t42_parse_font_matrix(T42_Face face, T42_Loader loader)
Definition: t42parse.c:249
T1_FieldLocation location
Definition: psaux.h:223
#define T1_ToInt(p)
Definition: t42parse.c:123
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:517
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:602
int i
Definition: pngrutil.c:1377
T1_FIELD_DICT_FONTDICT family_name
Definition: t1tokens.h:30
T1_TokenType type
Definition: psaux.h:170
t42_loader_init(T42_Loader loader, T42_Face face)
Definition: t42parse.c:1155
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
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:502
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define ft_strlen
Definition: ftstdlib.h:87
T42_ParserRec parser
Definition: t42parse.h:43
#define T1_FIELD_BBOX(_ident, _fname, _dict)
Definition: psaux.h:304
#define T1_FIELD_STRING(_ident, _fname, _dict)
Definition: psaux.h:298
#define ft_strcmp
Definition: ftstdlib.h:85
GLsizei size
Definition: gl2ext.h:1467