This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / subsys / win32k / freetype / src / type1z / z1load.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  z1load.c                                                               */
4 /*                                                                         */
5 /*    Experimental Type 1 font loader (body).                              */
6 /*                                                                         */
7 /*  Copyright 1996-2000 by                                                 */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
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   /*************************************************************************/
20   /*                                                                       */
21   /* This is the new and improved Type 1 data loader for FreeType 2.  The  */
22   /* old loader has several problems: it is slow, complex, difficult to    */
23   /* maintain, and contains incredible hacks to make it accept some        */
24   /* ill-formed Type 1 fonts without hiccup-ing.  Moreover, about 5% of    */
25   /* the Type 1 fonts on my machine still aren't loaded correctly by it.   */
26   /*                                                                       */
27   /* This version is much simpler, much faster and also easier to read and */
28   /* maintain by a great order of magnitude.  The idea behind it is to     */
29   /* _not_ try to read the Type 1 token stream with a state machine (i.e.  */
30   /* a Postscript-like interpreter) but rather to perform simple pattern   */
31   /* matching.                                                             */
32   /*                                                                       */
33   /* Indeed, nearly all data definitions follow a simple pattern like      */
34   /*                                                                       */
35   /*  ... /Field <data> ...                                                */
36   /*                                                                       */
37   /* where <data> can be a number, a boolean, a string, or an array of     */
38   /* numbers.  There are a few exceptions, namely the encoding, font name, */
39   /* charstrings, and subrs; they are handled with a special pattern       */
40   /* matching routine.                                                     */
41   /*                                                                       */
42   /* All other common cases are handled very simply.  The matching rules   */
43   /* are defined in the file `t1tokens.h' through the use of several       */
44   /* macros calls PARSE_XXX.                                               */
45   /*                                                                       */
46   /* This file is included twice here; the first time to generate parsing  */
47   /* callback functions, the second to generate a table of keywords (with  */
48   /* pointers to the associated callback).                                 */
49   /*                                                                       */
50   /* The function `parse_dict' simply scans *linearly* a given dictionary  */
51   /* (either the top-level or private one) and calls the appropriate       */
52   /* callback when it encounters an immediate keyword.                     */
53   /*                                                                       */
54   /* This is by far the fastest way one can find to parse and read all     */
55   /* data.                                                                 */
56   /*                                                                       */
57   /* This led to tremendous code size reduction.  Note that later, the     */
58   /* glyph loader will also be _greatly_ simplified, and the automatic     */
59   /* hinter will replace the clumsy `t1hinter'.                            */
60   /*                                                                       */
61   /*************************************************************************/
62
63
64 #include <freetype/internal/ftdebug.h>
65 #include <freetype/config/ftconfig.h>
66 #include <freetype/ftmm.h>
67
68 #include <freetype/internal/t1types.h>
69 #include <freetype/internal/t1errors.h>
70
71
72 #ifdef FT_FLAT_COMPILE
73
74 #include "z1load.h"
75
76 #else
77
78 #include <freetype/src/type1z/z1load.h>
79
80 #endif
81
82
83 #include <string.h>     /* for strncmp(), strcmp() */
84 #include <ctype.h>      /* for isalnum()           */
85
86
87   /*************************************************************************/
88   /*                                                                       */
89   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
90   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
91   /* messages during execution.                                            */
92   /*                                                                       */
93 #undef  FT_COMPONENT
94 #define FT_COMPONENT  trace_z1load
95
96
97 #ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
98
99
100   /*************************************************************************/
101   /*************************************************************************/
102   /*****                                                               *****/
103   /*****                    MULTIPLE MASTERS SUPPORT                   *****/
104   /*****                                                               *****/
105   /*************************************************************************/
106   /*************************************************************************/
107
108   static
109   FT_Error  t1_allocate_blend( T1_Face  face,
110                                FT_UInt  num_designs,
111                                FT_UInt  num_axis )
112   {
113     T1_Blend*  blend;
114     FT_Memory  memory = face->root.memory;
115     FT_Error   error  = 0;
116
117
118     blend = face->blend;
119     if ( !blend )
120     {
121       if ( ALLOC( blend, sizeof ( *blend ) ) )
122         goto Exit;
123
124       face->blend = blend;
125     }
126
127     /* allocate design data if needed */
128     if ( num_designs > 0 )
129     {
130       if ( blend->num_designs == 0 )
131       {
132         FT_UInt  nn;
133         
134
135         /* allocate the blend `private' and `font_info' dictionaries */
136         if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo )  ||
137              ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private )     ||
138              ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) )
139           goto Exit;
140
141         blend->default_weight_vector = blend->weight_vector + num_designs;
142
143         blend->font_infos[0] = &face->type1.font_info;
144         blend->privates  [0] = &face->type1.private_dict;
145         
146         for ( nn = 2; nn <= num_designs; nn++ )
147         {
148           blend->privates[nn]   = blend->privates  [nn - 1] + 1;
149           blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
150         }
151         
152         blend->num_designs   = num_designs;
153       }
154       else if ( blend->num_designs != num_designs )
155         goto Fail;
156     }
157
158     /* allocate axis data if needed */
159     if ( num_axis > 0 )
160     {
161       if ( blend->num_axis != 0 && blend->num_axis != num_axis )
162         goto Fail;
163
164       blend->num_axis = num_axis;
165     }
166
167     /* allocate the blend design pos table if needed */
168     num_designs = blend->num_designs;
169     num_axis    = blend->num_axis;
170     if ( num_designs && num_axis && blend->design_pos[0] == 0 )
171     {
172       FT_UInt  n;
173
174
175       if ( ALLOC_ARRAY( blend->design_pos[0],
176                         num_designs * num_axis, FT_Fixed ) )
177         goto Exit;
178
179       for ( n = 1; n < num_designs; n++ )
180         blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
181     }
182
183   Exit:
184     return error;
185
186   Fail:
187     error = -1;
188     goto Exit;
189   }
190
191
192   LOCAL_FUNC
193   FT_Error  Z1_Get_Multi_Master( T1_Face           face,
194                                  FT_Multi_Master*  master )
195   {
196     T1_Blend*  blend = face->blend;
197     FT_UInt    n;
198     FT_Error   error;
199
200
201     error = T1_Err_Invalid_Argument;
202
203     if ( blend )
204     {
205       master->num_axis    = blend->num_axis;
206       master->num_designs = blend->num_designs;
207
208       for ( n = 0; n < blend->num_axis; n++ )
209       {
210         FT_MM_Axis*    axis = master->axis + n;
211         T1_DesignMap*  map = blend->design_map + n;
212
213
214         axis->name    = blend->axis_names[n];
215         axis->minimum = map->design_points[0];
216         axis->maximum = map->design_points[map->num_points - 1];
217       }
218       error = 0;
219     }
220     return error;
221   }
222
223
224   LOCAL_FUNC
225   FT_Error  Z1_Set_MM_Blend( T1_Face    face,
226                              FT_UInt    num_coords,
227                              FT_Fixed*  coords )
228   {
229     T1_Blend*  blend = face->blend;
230     FT_Error   error;
231     FT_UInt    n, m;
232
233
234     error = T1_Err_Invalid_Argument;
235
236     if ( blend && blend->num_axis == num_coords )
237     {
238       /* recompute the weight vector from the blend coordinates */
239       error = FT_Err_Ok;
240
241       for ( n = 0; n < blend->num_designs; n++ )
242       {
243         FT_Fixed  result = 0x10000L;  /* 1.0 fixed */
244
245
246         for ( m = 0; m < blend->num_axis; m++ )
247         {
248           FT_Fixed  factor;
249
250
251           /* get current blend axis position */
252           factor = coords[m];
253           if ( factor < 0 )        factor = 0;
254           if ( factor > 0x10000L ) factor = 0x10000L;
255
256           if ( ( n & ( 1 << m ) ) == 0 )
257             factor = 0x10000L - factor;
258
259           result = FT_MulFix( result, factor );
260         }
261         blend->weight_vector[n] = result;
262       }
263
264       error = FT_Err_Ok;
265     }
266     return error;
267   }
268
269
270   LOCAL_FUNC
271   FT_Error  Z1_Set_MM_Design( T1_Face   face,
272                               FT_UInt   num_coords,
273                               FT_Long*  coords )
274   {
275     T1_Blend*  blend = face->blend;
276     FT_Error   error;
277     FT_UInt    n, p;
278
279
280     error = T1_Err_Invalid_Argument;
281     if ( blend && blend->num_axis == num_coords )
282     {
283       /* compute the blend coordinates through the blend design map */
284       FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
285
286
287       for ( n = 0; n < blend->num_axis; n++ )
288       {
289         FT_Long        design  = coords[n];
290         FT_Fixed       the_blend;
291         T1_DesignMap*  map     = blend->design_map + n;
292         FT_Fixed*      designs = map->design_points;
293         FT_Fixed*      blends  = map->blend_points;
294         FT_Int         before  = -1, after = -1;
295
296         for ( p = 0; p < map->num_points; p++ )
297         {
298           FT_Fixed  p_design = designs[p];
299
300
301           /* exact match ? */
302           if ( design == p_design )
303           {
304             the_blend = blends[p];
305             goto Found;
306           }
307
308           if ( design < p_design )
309           {
310             after = p;
311             break;
312           }
313
314           before = p;
315         }
316
317         /* now, interpolate if needed */
318         if ( before < 0 )
319           the_blend = blends[0];
320
321         else if ( after < 0 )
322           the_blend = blends[map->num_points - 1];
323
324         else
325           the_blend = FT_MulDiv( design         - designs[before],
326                                  blends [after] - blends [before],
327                                  designs[after] - designs[before] );
328
329       Found:
330         final_blends[n] = the_blend;
331       }
332
333       error = Z1_Set_MM_Blend( face, num_coords, final_blends );
334     }
335
336     return error;
337   }
338
339
340   LOCAL_FUNC
341   void  Z1_Done_Blend( T1_Face  face )
342   {
343     FT_Memory  memory = face->root.memory;
344     T1_Blend*  blend  = face->blend;
345
346
347     if ( blend )
348     {
349       FT_UInt  num_designs = blend->num_designs;
350       FT_UInt  num_axis    = blend->num_axis;
351       FT_UInt  n;
352
353
354       /* release design pos table */
355       FREE( blend->design_pos[0] );
356       for ( n = 1; n < num_designs; n++ )
357         blend->design_pos[n] = 0;
358
359       /* release blend `private' and `font info' dictionaries */
360       FREE( blend->privates[1] );
361       FREE( blend->font_infos[1] );
362
363       for ( n = 0; n < num_designs; n++ )
364       {
365         blend->privates  [n] = 0;
366         blend->font_infos[n] = 0;
367       }
368
369       /* release weight vectors */
370       FREE( blend->weight_vector );
371       blend->default_weight_vector = 0;
372
373       /* release axis names */
374       for ( n = 0; n < num_axis; n++ )
375         FREE( blend->axis_names[n] );
376
377       /* release design map */
378       for ( n = 0; n < num_axis; n++ )
379       {
380         T1_DesignMap*  dmap = blend->design_map + n;
381
382
383         FREE( dmap->design_points );
384         dmap->num_points = 0;
385       }
386
387       FREE( face->blend );
388     }
389   }
390
391
392   static
393   void  parse_blend_axis_types( T1_Face     face,
394                                 Z1_Loader*  loader )
395   {
396     Z1_Token_Rec  axis_tokens[ T1_MAX_MM_AXIS ];
397     FT_Int        n, num_axis;
398     FT_Error      error = 0;
399     T1_Blend*     blend;
400     FT_Memory     memory;
401
402
403     /* take an array of objects */
404     Z1_ToTokenArray( &loader->parser, axis_tokens,
405                      T1_MAX_MM_AXIS, &num_axis );
406     if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
407     {
408       FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
409                  num_axis ));
410       error = T1_Err_Invalid_File_Format;
411       goto Exit;
412     }
413
414     /* allocate blend if necessary */
415     error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
416     if ( error )
417       goto Exit;
418
419     blend  = face->blend;
420     memory = face->root.memory;
421
422     /* each token is an immediate containing the name of the axis */
423     for ( n = 0; n < num_axis; n++ )
424     {
425       Z1_Token_Rec*  token = axis_tokens + n;
426       FT_Byte*       name;
427       FT_Int         len;
428
429       /* skip first slash, if any */
430       if (token->start[0] == '/')
431         token->start++;
432
433       len = token->limit - token->start;
434       if ( len <= 0 )
435       {
436         error = T1_Err_Invalid_File_Format;
437         goto Exit;
438       }
439
440       if ( ALLOC( blend->axis_names[n], len + 1 ) )
441         goto Exit;
442
443       name = (FT_Byte*)blend->axis_names[n];
444       MEM_Copy( name, token->start, len );
445       name[len] = 0;
446     }
447
448   Exit:
449     loader->parser.error = error;
450   }
451
452
453   static
454   void  parse_blend_design_positions( T1_Face     face,
455                                       Z1_Loader*  loader )
456   {
457     Z1_Token_Rec  design_tokens[ T1_MAX_MM_DESIGNS ];
458     FT_Int        num_designs;
459     FT_Int        num_axis;
460     Z1_Parser*    parser = &loader->parser;
461
462     FT_Error      error = 0;
463     T1_Blend*     blend;
464
465
466     /* get the array of design tokens - compute number of designs */
467     Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
468     if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
469     {
470       FT_ERROR(( "parse_blend_design_positions:" ));
471       FT_ERROR(( " incorrect number of designs: %d\n",
472                  num_designs ));
473       error = T1_Err_Invalid_File_Format;
474       goto Exit;
475     }
476
477     {
478       FT_Byte*  old_cursor = parser->cursor;
479       FT_Byte*  old_limit  = parser->limit;
480       FT_UInt   n;
481
482
483       blend    = face->blend;
484       num_axis = 0;  /* make compiler happy */
485
486       for ( n = 0; n < (FT_UInt)num_designs; n++ )
487       {
488         Z1_Token_Rec   axis_tokens[ T1_MAX_MM_DESIGNS ];
489         Z1_Token_Rec*  token;
490         FT_Int         axis, n_axis;
491
492
493         /* read axis/coordinates tokens */
494         token = design_tokens + n;
495         parser->cursor = token->start - 1;
496         parser->limit  = token->limit + 1;
497         Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
498
499         if ( n == 0 )
500         {
501           num_axis = n_axis;
502           error = t1_allocate_blend( face, num_designs, num_axis );
503           if ( error )
504             goto Exit;
505           blend = face->blend;
506         }
507         else if ( n_axis != num_axis )
508         {
509           FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
510           error = T1_Err_Invalid_File_Format;
511           goto Exit;
512         }
513
514         /* now, read each axis token into the design position */
515         for ( axis = 0; axis < n_axis; axis++ )
516         {
517           Z1_Token_Rec*  token2 = axis_tokens + axis;
518
519
520           parser->cursor = token2->start;
521           parser->limit  = token2->limit;
522           blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 );
523         }
524       }
525
526       loader->parser.cursor = old_cursor;
527       loader->parser.limit  = old_limit;
528     }
529
530   Exit:
531     loader->parser.error = error;
532   }
533
534
535   static
536   void  parse_blend_design_map( T1_Face     face,
537                                 Z1_Loader*  loader )
538   {
539     FT_Error      error  = 0;
540     Z1_Parser*    parser = &loader->parser;
541     T1_Blend*     blend;
542     Z1_Token_Rec  axis_tokens[ T1_MAX_MM_AXIS ];
543     FT_Int        n, num_axis;
544     FT_Byte*      old_cursor;
545     FT_Byte*      old_limit;
546     FT_Memory     memory = face->root.memory;
547
548
549     Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
550     if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
551     {
552       FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
553                  num_axis ));
554       error = T1_Err_Invalid_File_Format;
555       goto Exit;
556     }
557     old_cursor = parser->cursor;
558     old_limit  = parser->limit;
559
560     error = t1_allocate_blend( face, 0, num_axis );
561     if ( error )
562       goto Exit;
563     blend = face->blend;
564
565     /* now, read each axis design map */
566     for ( n = 0; n < num_axis; n++ )
567     {
568       T1_DesignMap*   map = blend->design_map + n;
569       Z1_Token_Rec*   token;
570       FT_Int          p, num_points;
571
572
573       token = axis_tokens + n;
574       parser->cursor = token->start;
575       parser->limit  = token->limit;
576
577       /* count the number of map points */
578       {
579         FT_Byte*  p     = token->start;
580         FT_Byte*  limit = token->limit;
581
582
583         num_points = 0;
584         for ( ; p < limit; p++ )
585           if ( p[0] == '[' )
586             num_points++;
587       }
588       if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
589       {
590         FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
591         error = T1_Err_Invalid_File_Format;
592         goto Exit;
593       }
594
595       /* allocate design map data */
596       if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) )
597         goto Exit;
598       map->blend_points = map->design_points + num_points;
599       map->num_points   = (FT_Byte)num_points;
600
601       for ( p = 0; p < num_points; p++ )
602       {
603         map->design_points[p] = Z1_ToInt( parser );
604         map->blend_points [p] = Z1_ToFixed( parser, 0 );
605       }
606     }
607
608     parser->cursor = old_cursor;
609     parser->limit  = old_limit;
610
611   Exit:
612     parser->error = error;
613   }
614
615
616   static
617   void  parse_weight_vector( T1_Face     face,
618                              Z1_Loader*  loader )
619   {
620     FT_Error      error  = 0;
621     Z1_Parser*    parser = &loader->parser;
622     T1_Blend*     blend  = face->blend;
623     Z1_Token_Rec  master;
624     FT_UInt       n;
625     FT_Byte*      old_cursor;
626     FT_Byte*      old_limit;
627
628
629     if ( !blend || blend->num_designs == 0 )
630     {
631       FT_ERROR(( "parse_weight_vector: too early!\n" ));
632       error = T1_Err_Invalid_File_Format;
633       goto Exit;
634     }
635
636     Z1_ToToken( parser, &master );
637     if ( master.type != t1_token_array )
638     {
639       FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
640       error = T1_Err_Invalid_File_Format;
641       goto Exit;
642     }
643
644     old_cursor = parser->cursor;
645     old_limit  = parser->limit;
646
647     parser->cursor = master.start;
648     parser->limit  = master.limit;
649
650     for ( n = 0; n < blend->num_designs; n++ )
651     {
652       blend->default_weight_vector[n] =
653       blend->weight_vector[n]         = Z1_ToFixed( parser, 0 );
654     }
655
656     parser->cursor = old_cursor;
657     parser->limit  = old_limit;
658
659   Exit:
660     parser->error = error;
661   }
662
663
664   /* the keyword `/shareddict' appears in some multiple master fonts   */
665   /* with a lot of Postscript garbage behind it (that's completely out */
666   /* of spec!); we detect it and terminate the parsing                 */
667   /*                                                                   */
668   static
669   void  parse_shared_dict( T1_Face     face,
670                            Z1_Loader*  loader )
671   {
672     Z1_Parser*  parser = &loader->parser;
673
674     FT_UNUSED( face );
675
676
677     parser->cursor = parser->limit;
678     parser->error  = 0;
679   }
680
681 #endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */
682
683
684   /*************************************************************************/
685   /*************************************************************************/
686   /*****                                                               *****/
687   /*****                      TYPE 1 SYMBOL PARSING                    *****/
688   /*****                                                               *****/
689   /*************************************************************************/
690   /*************************************************************************/
691
692
693   /*************************************************************************/
694   /*                                                                       */
695   /* First of all, define the token field static variables.  This is a set */
696   /* of Z1_Field_Rec variables used later.                                 */
697   /*                                                                       */
698   /*************************************************************************/
699
700 #define Z1_NEW_STRING( _name, _field )              \
701           static                                    \
702           const Z1_Field_Rec  t1_field_ ## _field = \
703             Z1_FIELD_STRING( T1TYPE, _field );
704
705 #define Z1_NEW_BOOL( _name, _field )                \
706           static                                    \
707           const Z1_Field_Rec  t1_field_ ## _field = \
708             Z1_FIELD_BOOL( T1TYPE, _field );
709
710 #define Z1_NEW_NUM( _name, _field )                 \
711           static                                    \
712           const Z1_Field_Rec  t1_field_ ## _field = \
713             Z1_FIELD_NUM( T1TYPE, _field );
714
715 #define Z1_NEW_FIXED( _name, _field )                 \
716           static                                      \
717           const Z1_Field_Rec  t1_field_ ## _field =   \
718             Z1_FIELD_FIXED( T1TYPE, _field, _power );
719
720 #define Z1_NEW_NUM_TABLE( _name, _field, _max, _count )         \
721           static                                                \
722           const Z1_Field_Rec  t1_field_ ## _field =             \
723             Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max );
724
725 #define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count )         \
726           static                                                  \
727           const Z1_Field_Rec  t1_field_ ## _field =               \
728             Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max );
729
730 #define Z1_NEW_NUM_TABLE2( _name, _field, _max )         \
731           static                                         \
732           const Z1_Field_Rec  t1_field_ ## _field =      \
733             Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max );
734
735 #define Z1_NEW_FIXED_TABLE2( _name, _field, _max )         \
736           static                                           \
737           const Z1_Field_Rec  t1_field_ ## _field =        \
738             Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max );
739
740
741 #define Z1_FONTINFO_STRING( n, f )          Z1_NEW_STRING( n, f )
742 #define Z1_FONTINFO_NUM( n, f )             Z1_NEW_NUM( n, f )
743 #define Z1_FONTINFO_BOOL( n, f )            Z1_NEW_BOOL( n, f )
744 #define Z1_PRIVATE_NUM( n, f )              Z1_NEW_NUM( n, f )
745 #define Z1_PRIVATE_FIXED( n, f )            Z1_NEW_FIXED( n, f )
746 #define Z1_PRIVATE_NUM_TABLE( n, f, m, c )  Z1_NEW_NUM_TABLE( n, f, m, c )
747 #define Z1_PRIVATE_NUM_TABLE2( n, f, m )    Z1_NEW_NUM_TABLE2( n, f, m )
748 #define Z1_TOPDICT_NUM( n, f )              Z1_NEW_NUM( n, f )
749 #define Z1_TOPDICT_NUM_FIXED2( n, f, m )    Z1_NEW_FIXED_TABLE2( n, f, m )
750
751
752   /* including this file defines all field variables */
753 #ifdef FT_FLAT_COMPILE
754
755 #include "z1tokens.h"
756
757 #else
758
759 #include <freetype/src/type1z/z1tokens.h>
760
761 #endif
762
763
764   /*************************************************************************/
765   /*                                                                       */
766   /* Second, define the keyword variables.  This is a set of Z1_KeyWord    */
767   /* structures used to model the way each keyword is `loaded'.            */
768   /*                                                                       */
769   /*************************************************************************/
770
771   typedef void  (*Z1_Parse_Func)( T1_Face     face,
772                                   Z1_Loader*  loader );
773
774
775   typedef enum  Z1_KeyWord_Type_
776   {
777     t1_keyword_callback = 0,
778     t1_keyword_field,
779     t1_keyword_field_table
780
781   } Z1_KeyWord_Type;
782
783
784   typedef enum  Z1_KeyWord_Location_
785   {
786     t1_keyword_type1 = 0,
787     t1_keyword_font_info,
788     t1_keyword_private
789
790   } Z1_KeyWord_Location;
791
792
793   typedef struct  Z1_KeyWord_
794   {
795     const char*          name;
796     Z1_KeyWord_Type      type;
797     Z1_KeyWord_Location  location;
798     Z1_Parse_Func        parsing;
799     const Z1_Field_Rec*  field;
800
801   } Z1_KeyWord;
802
803
804 #define Z1_KEYWORD_CALLBACK( name, callback )                      \
805         {                                                          \
806           name, t1_keyword_callback, t1_keyword_type1, callback, 0 \
807         }
808
809 #define Z1_KEYWORD_TYPE1( name, f )                                    \
810         {                                                              \
811           name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f \
812         }
813
814 #define Z1_KEYWORD_FONTINFO( name, f )                                     \
815         {                                                                  \
816           name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f \
817         }
818
819 #define Z1_KEYWORD_PRIVATE( name, f )                                    \
820         {                                                                \
821           name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f \
822         }
823
824 #define Z1_KEYWORD_FONTINFO_TABLE( name, f )                     \
825         {                                                        \
826           name, t1_keyword_field_table, t1_keyword_font_info, 0, \
827           &t1_field_ ## f                                        \
828         }
829
830 #define Z1_KEYWORD_PRIVATE_TABLE( name, f )                    \
831         {                                                      \
832           name, t1_keyword_field_table, t1_keyword_private, 0, \
833           &t1_field_ ## f                                      \
834         }
835
836
837 #undef  Z1_FONTINFO_STRING
838 #undef  Z1_FONTINFO_NUM
839 #undef  Z1_FONTINFO_BOOL
840 #undef  Z1_PRIVATE_NUM
841 #undef  Z1_PRIVATE_FIXED
842 #undef  Z1_PRIVATE_NUM_TABLE
843 #undef  Z1_PRIVATE_NUM_TABLE2
844 #undef  Z1_TOPDICT_NUM
845 #undef  Z1_TOPDICT_NUM_FIXED2
846
847 #define Z1_FONTINFO_STRING( n, f )          Z1_KEYWORD_FONTINFO( n, f ),
848 #define Z1_FONTINFO_NUM( n, f )             Z1_KEYWORD_FONTINFO( n, f ),
849 #define Z1_FONTINFO_BOOL( n, f )            Z1_KEYWORD_FONTINFO( n, f ),
850 #define Z1_PRIVATE_NUM( n, f )              Z1_KEYWORD_PRIVATE( n, f ),
851 #define Z1_PRIVATE_FIXED( n, f )            Z1_KEYWORD_PRIVATE( n, f ),
852 #define Z1_PRIVATE_NUM_TABLE( n, f, m, c )  Z1_KEYWORD_PRIVATE_TABLE( n, f ),
853 #define Z1_PRIVATE_NUM_TABLE2( n, f, m )    Z1_KEYWORD_PRIVATE_TABLE( n, f ),
854 #define Z1_TOPDICT_NUM( n, f )              Z1_KEYWORD_TYPE1( n, f ),
855 #define Z1_TOPDICT_NUM_FIXED2( n, f, m )    Z1_KEYWORD_TYPE1( n, f ),
856
857
858   static
859   FT_Error  t1_load_keyword( T1_Face      face,
860                              Z1_Loader*   loader,
861                              Z1_KeyWord*  keyword )
862   {
863     FT_Error   error;
864     void*      dummy_object;
865     void**     objects;
866     FT_UInt    max_objects;
867     T1_Blend*  blend = face->blend;
868
869
870     /* if the keyword has a dedicated callback, call it */
871     if ( keyword->type == t1_keyword_callback )
872     {
873       keyword->parsing( face, loader );
874       error = loader->parser.error;
875       goto Exit;
876     }
877
878     /* now, the keyword is either a simple field, or a table of fields; */
879     /* we are now going to take care of it                              */
880     switch ( keyword->location )
881     {
882     case t1_keyword_font_info:
883       dummy_object = &face->type1.font_info;
884       objects      = &dummy_object;
885       max_objects  = 0;
886
887       if ( blend )
888       {
889         objects     = (void**)blend->font_infos;
890         max_objects = blend->num_designs;
891       }
892       break;
893
894     case t1_keyword_private:
895       dummy_object = &face->type1.private_dict;
896       objects      = &dummy_object;
897       max_objects  = 0;
898
899       if ( blend )
900       {
901         objects     = (void**)blend->privates;
902         max_objects = blend->num_designs;
903       }
904       break;
905
906     default:
907       dummy_object = &face->type1;
908       objects      = &dummy_object;
909       max_objects  = 0;
910     }
911
912     if ( keyword->type == t1_keyword_field_table )
913       error = Z1_Load_Field_Table( &loader->parser, keyword->field,
914                                    objects, max_objects, 0 );
915     else
916       error = Z1_Load_Field( &loader->parser, keyword->field,
917                              objects, max_objects, 0 );
918
919   Exit:
920     return error;
921   }
922
923
924   static
925   int  is_space( char  c )
926   {
927     return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
928   }
929
930
931   static
932   int  is_alpha( char c )
933   {
934     return ( isalnum( c ) ||
935              ( c == '.' ) ||
936              ( c == '_' ) );
937   }
938
939
940   static
941   void  skip_whitespace( Z1_Parser*  parser )
942   {
943     FT_Byte*  cur = parser->cursor;
944
945
946     while ( cur < parser->limit && is_space( *cur ) )
947       cur++;
948
949     parser->cursor = cur;
950   }
951
952
953   static
954   void skip_blackspace( Z1_Parser*  parser )
955   {
956     FT_Byte*  cur = parser->cursor;
957
958     while ( cur < parser->limit && !is_space( *cur ) )
959       cur++;
960
961     parser->cursor = cur;
962   }
963
964
965   static
966   int  read_binary_data( Z1_Parser*  parser,
967                          FT_Int*     size,
968                          FT_Byte**   base )
969   {
970     FT_Byte*  cur;
971     FT_Byte*  limit = parser->limit;
972
973
974     /* the binary data has the following format */
975     /*                                          */
976     /* `size' [white*] RD white ....... ND      */
977     /*                                          */
978
979     skip_whitespace( parser );
980     cur = parser->cursor;
981
982     if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
983     {
984       *size = Z1_ToInt( parser );
985
986       skip_whitespace( parser );
987       skip_blackspace( parser );  /* `RD' or `-|' or something else */
988
989       /* there is only one whitespace char after the */
990       /* `RD' or `-|' token                          */
991       *base = parser->cursor + 1;
992
993       parser->cursor += *size+1;
994       return 1;
995     }
996
997     FT_ERROR(( "read_binary_data: invalid size field\n" ));
998     parser->error = T1_Err_Invalid_File_Format;
999     return 0;
1000   }
1001
1002
1003   /* we will now define the routines used to handle */
1004   /* the `/Encoding', `/Subrs', and `/CharStrings'  */
1005   /* dictionaries                                   */
1006
1007   static
1008   void  parse_font_name( T1_Face     face,
1009                          Z1_Loader*  loader )
1010   {
1011     Z1_Parser*  parser = &loader->parser;
1012     FT_Error    error;
1013     FT_Memory   memory = parser->memory;
1014     FT_Int      len;
1015     FT_Byte*    cur;
1016     FT_Byte*    cur2;
1017     FT_Byte*    limit;
1018
1019
1020     skip_whitespace( parser );
1021
1022     cur   = parser->cursor;
1023     limit = parser->limit;
1024
1025     if ( cur >= limit - 1 || *cur != '/' )
1026       return;
1027
1028     cur++;
1029     cur2 = cur;
1030     while ( cur2 < limit && is_alpha( *cur2 ) )
1031       cur2++;
1032
1033     len = cur2 - cur;
1034     if ( len > 0 )
1035     {
1036       if ( ALLOC( face->type1.font_name, len + 1 ) )
1037       {
1038         parser->error = error;
1039         return;
1040       }
1041
1042       MEM_Copy( face->type1.font_name, cur, len );
1043       face->type1.font_name[len] = '\0';
1044     }
1045     parser->cursor = cur2;
1046   }
1047
1048
1049   static
1050   void  parse_font_bbox( T1_Face     face,
1051                          Z1_Loader*  loader )
1052   {
1053     Z1_Parser*  parser = &loader->parser;
1054     FT_Short    temp[4];
1055     FT_BBox*    bbox   = &face->type1.font_bbox;
1056
1057
1058     (void)Z1_ToCoordArray( parser, 4, temp );
1059     bbox->xMin = temp[0];
1060     bbox->yMin = temp[1];
1061     bbox->xMax = temp[2];
1062     bbox->yMax = temp[3];
1063   }
1064
1065
1066   static
1067   void  parse_font_matrix( T1_Face     face,
1068                            Z1_Loader*  loader )
1069   {
1070     Z1_Parser*  parser = &loader->parser;
1071     FT_Matrix*  matrix = &face->type1.font_matrix;
1072     FT_Fixed    temp[4];
1073
1074
1075     (void)Z1_ToFixedArray( parser, 4, temp, 3 );
1076     matrix->xx = temp[0];
1077     matrix->yx = temp[1];
1078     matrix->xy = temp[2];
1079     matrix->yy = temp[3];
1080   }
1081
1082
1083   static
1084   void  parse_encoding( T1_Face     face,
1085                         Z1_Loader*  loader )
1086   {
1087     Z1_Parser*  parser = &loader->parser;
1088     FT_Byte*    cur   = parser->cursor;
1089     FT_Byte*    limit = parser->limit;
1090
1091
1092     /* skip whitespace */
1093     while ( is_space( *cur ) )
1094     {
1095       cur++;
1096       if ( cur >= limit )
1097       {
1098         FT_ERROR(( "parse_encoding: out of bounds!\n" ));
1099         parser->error = T1_Err_Invalid_File_Format;
1100         return;
1101       }
1102     }
1103
1104     /* if we have a number, then the encoding is an array, */
1105     /* and we must load it now                             */
1106     if ( (FT_Byte)( *cur - '0' ) < 10 )
1107     {
1108       T1_Encoding*  encode     = &face->type1.encoding;
1109       FT_Int        count, n;
1110       Z1_Table*     char_table = &loader->encoding_table;
1111       FT_Memory     memory     = parser->memory;
1112       FT_Error      error;
1113
1114
1115       /* read the number of entries in the encoding, should be 256 */
1116       count = Z1_ToInt( parser );
1117       if ( parser->error )
1118         return;
1119
1120       /* we use a Z1_Table to store our charnames */
1121       encode->num_chars = count;
1122       if ( ALLOC_ARRAY( encode->char_index, count, FT_Short   )       ||
1123            ALLOC_ARRAY( encode->char_name,  count, FT_String* )       ||
1124            ( error = Z1_New_Table( char_table, count, memory ) ) != 0 )
1125       {
1126         parser->error = error;
1127         return;
1128       }
1129
1130       /* Now, we will need to read a record of the form         */
1131       /* ... charcode /charname ... for each entry in our table */
1132       /*                                                        */
1133       /* We simply look for a number followed by an immediate   */
1134       /* name.  Note that this ignores correctly the sequence   */
1135       /* that is often seen in type1 fonts:                     */
1136       /*                                                        */
1137       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
1138       /*                                                        */
1139       /* used to clean the encoding array before anything else. */
1140       /*                                                        */
1141       /* We stop when we encounter a `def'.                     */
1142
1143       cur   = parser->cursor;
1144       limit = parser->limit;
1145       n     = 0;
1146
1147       for ( ; cur < limit; )
1148       {
1149         FT_Byte  c;
1150
1151
1152         c = *cur;
1153
1154         /* we stop when we encounter a `def' */
1155         if ( c == 'd' && cur + 3 < limit )
1156         {
1157           if ( cur[1] == 'e' &&
1158                cur[2] == 'f' &&
1159                is_space(cur[-1]) &&
1160                is_space(cur[3]) )
1161           {
1162             FT_TRACE6(( "encoding end\n" ));
1163             break;
1164           }
1165         }
1166
1167         /* otherwise, we must find a number before anything else */
1168         if ( (FT_Byte)( c - '0' ) < 10 )
1169         {
1170           FT_Int  charcode;
1171
1172
1173           parser->cursor = cur;
1174           charcode = Z1_ToInt( parser );
1175           cur = parser->cursor;
1176
1177           /* skip whitespace */
1178           while ( cur < limit && is_space( *cur ) )
1179             cur++;
1180
1181           if ( cur < limit && *cur == '/' )
1182           {
1183             /* bingo, we have an immediate name -- it must be a */
1184             /* character name                                   */
1185             FT_Byte*  cur2 = cur + 1;
1186             FT_Int    len;
1187
1188
1189             while ( cur2 < limit && is_alpha( *cur2 ) )
1190               cur2++;
1191
1192             len = cur2 - cur - 1;
1193
1194             parser->error = Z1_Add_Table( char_table, charcode,
1195                                           cur + 1, len + 1 );
1196             char_table->elements[charcode][len] = '\0';
1197             if ( parser->error )
1198               return;
1199
1200             cur = cur2;
1201           }
1202         }
1203         else
1204           cur++;
1205       }
1206
1207       face->type1.encoding_type = t1_encoding_array;
1208       parser->cursor            = cur;
1209     }
1210     /* Otherwise, we should have either `StandardEncoding' or */
1211     /* `ExpertEncoding'                                       */
1212     else
1213     {
1214       if ( cur + 17 < limit &&
1215            strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
1216         face->type1.encoding_type = t1_encoding_standard;
1217
1218       else if ( cur + 15 < limit &&
1219                 strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
1220         face->type1.encoding_type = t1_encoding_expert;
1221
1222       else
1223       {
1224         FT_ERROR(( "parse_encoding: invalid token!\n" ));
1225         parser->error = T1_Err_Invalid_File_Format;
1226       }
1227     }
1228   }
1229
1230
1231   static
1232   void  parse_subrs( T1_Face     face,
1233                      Z1_Loader*  loader )
1234   {
1235     Z1_Parser*  parser = &loader->parser;
1236     Z1_Table*   table  = &loader->subrs;
1237     FT_Memory   memory = parser->memory;
1238     FT_Error    error;
1239     FT_Int      n;
1240
1241
1242     loader->num_subrs = Z1_ToInt( parser );
1243     if ( parser->error )
1244       return;
1245
1246     /* position the parser right before the `dup' of the first subr */
1247     skip_whitespace( parser );
1248     skip_blackspace( parser );      /* `array' */
1249     skip_whitespace( parser );
1250
1251     /* initialize subrs array */
1252     error = Z1_New_Table( table, loader->num_subrs, memory );
1253     if ( error )
1254       goto Fail;
1255
1256     /* the format is simple:                                 */
1257     /*                                                       */
1258     /*   `index' + binary data                               */
1259     /*                                                       */
1260
1261     for ( n = 0; n < loader->num_subrs; n++ )
1262     {
1263       FT_Int    index, size;
1264       FT_Byte*  base;
1265
1266
1267       /* If the next token isn't `dup', we are also done.  This */
1268       /* happens when there are `holes' in the Subrs array.     */
1269       if ( strncmp( (char*)parser->cursor, "dup", 3 ) != 0 )
1270         break;
1271
1272       index = Z1_ToInt( parser );
1273       
1274       if ( !read_binary_data( parser, &size, &base ) )
1275         return;
1276
1277       /* The binary string is followed by one token, e.g. `NP' */
1278       /* (bound to `noaccess put') or by two separate tokens:  */
1279       /* `noaccess' & `put'.  We position the parser right     */
1280       /* before the next `dup', if any.                        */
1281       skip_whitespace( parser );
1282       skip_blackspace( parser );    /* `NP' or `I' or `noaccess' */
1283       skip_whitespace( parser );
1284
1285       if ( strncmp( (char*)parser->cursor, "put", 3 ) == 0 )
1286       {
1287         skip_blackspace( parser );  /* skip `put' */
1288         skip_whitespace( parser );
1289       }
1290
1291       /* some fonts use a value of -1 for lenIV to indicate that */
1292       /* the charstrings are unencoded                           */
1293       /*                                                         */
1294       /* thanks to Tom Kacvinsky for pointing this out           */
1295       /*                                                         */
1296       if ( face->type1.private_dict.lenIV >= 0 )
1297       {
1298         Z1_Decrypt( base, size, 4330 );
1299         size -= face->type1.private_dict.lenIV;
1300         base += face->type1.private_dict.lenIV;
1301       }
1302
1303       error = Z1_Add_Table( table, index, base, size );
1304       if ( error )
1305         goto Fail;
1306     }
1307     return;
1308
1309   Fail:
1310     parser->error = error;
1311   }
1312
1313
1314   static
1315   void  parse_charstrings( T1_Face     face,
1316                            Z1_Loader*  loader )
1317   {
1318     Z1_Parser*  parser     = &loader->parser;
1319     Z1_Table*   code_table = &loader->charstrings;
1320     Z1_Table*   name_table = &loader->glyph_names;
1321     FT_Memory   memory     = parser->memory;
1322     FT_Error    error;
1323
1324     FT_Byte*    cur;
1325     FT_Byte*    limit = parser->limit;
1326     FT_Int      n;
1327
1328
1329     loader->num_glyphs = Z1_ToInt( parser );
1330     if ( parser->error )
1331       return;
1332
1333     /* initialize tables */
1334     error = Z1_New_Table( code_table, loader->num_glyphs, memory ) ||
1335             Z1_New_Table( name_table, loader->num_glyphs, memory );
1336     if ( error )
1337       goto Fail;
1338
1339     n = 0;
1340     for (;;)
1341     {
1342       FT_Int    size;
1343       FT_Byte*  base;
1344
1345
1346       /* the format is simple:                    */
1347       /*   `/glyphname' + binary data             */
1348       /*                                          */
1349       /* note that we stop when we find a `def'   */
1350       /*                                          */
1351       skip_whitespace( parser );
1352
1353       cur = parser->cursor;
1354       if ( cur >= limit )
1355         break;
1356
1357       /* we stop when we find a `def' or `end' keyword */
1358       if ( *cur   == 'd'   &&
1359            cur + 3 < limit &&
1360            cur[1] == 'e'   &&
1361            cur[2] == 'f'   )
1362         break;
1363
1364       if ( *cur   == 'e'   &&
1365            cur + 3 < limit &&
1366            cur[1] == 'n'   &&
1367            cur[2] == 'd'   )
1368         break;
1369
1370       if ( *cur != '/' )
1371         skip_blackspace( parser );
1372       else
1373       {
1374         FT_Byte*  cur2 = cur + 1;
1375         FT_Int    len;
1376
1377
1378         while ( cur2 < limit && is_alpha( *cur2 ) )
1379           cur2++;
1380         len = cur2 - cur - 1;
1381
1382         error = Z1_Add_Table( name_table, n, cur + 1, len + 1 );
1383         if ( error )
1384           goto Fail;
1385
1386         /* add a trailing zero to the name table */
1387         name_table->elements[n][len] = '\0';
1388
1389         parser->cursor = cur2;
1390         if ( !read_binary_data( parser, &size, &base ) )
1391           return;
1392
1393         if ( face->type1.private_dict.lenIV >= 0 )
1394         {
1395           Z1_Decrypt( base, size, 4330 );
1396           size -= face->type1.private_dict.lenIV;
1397           base += face->type1.private_dict.lenIV;
1398         }
1399
1400         error = Z1_Add_Table( code_table, n, base, size );
1401         if ( error )
1402           goto Fail;
1403
1404         n++;
1405         if ( n >= loader->num_glyphs )
1406           break;
1407       }
1408     }
1409     loader->num_glyphs = n;
1410     return;
1411
1412   Fail:
1413     parser->error = error;
1414   }
1415
1416
1417   static
1418   const Z1_KeyWord  t1_keywords[] =
1419   {
1420
1421 #ifdef FT_FLAT_COMPILE
1422
1423 #include "z1tokens.h"
1424
1425 #else
1426
1427 #include <freetype/src/type1z/z1tokens.h>
1428
1429 #endif
1430
1431     /* now add the special functions... */
1432     Z1_KEYWORD_CALLBACK( "FontName", parse_font_name ),
1433     Z1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ),
1434     Z1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ),
1435     Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding ),
1436     Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs ),
1437     Z1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ),
1438
1439 #ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
1440     Z1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ),
1441     Z1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ),
1442     Z1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ),
1443     Z1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ),
1444     Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ),
1445 #endif
1446
1447     Z1_KEYWORD_CALLBACK( 0, 0 )
1448   };
1449
1450
1451   static
1452   FT_Error  parse_dict( T1_Face     face,
1453                         Z1_Loader*  loader,
1454                         FT_Byte*    base,
1455                         FT_Long     size )
1456   {
1457     Z1_Parser*  parser = &loader->parser;
1458
1459
1460     parser->cursor = base;
1461     parser->limit  = base + size;
1462     parser->error  = 0;
1463
1464     {
1465       FT_Byte*  cur   = base;
1466       FT_Byte*  limit = cur + size;
1467
1468
1469       for ( ; cur < limit; cur++ )
1470       {
1471         /* look for `FontDirectory', which causes problems on some fonts */
1472         if ( *cur == 'F' && cur + 25 < limit                 &&
1473              strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
1474         {
1475           FT_Byte*  cur2;
1476
1477
1478           /* skip the `FontDirectory' keyword */
1479           cur += 13;
1480           cur2 = cur;
1481
1482           /* lookup the `known' keyword */
1483           while ( cur < limit && *cur != 'k'        &&
1484                   strncmp( (char*)cur, "known", 5 ) )
1485             cur++;
1486
1487           if ( cur < limit )
1488           {
1489             Z1_Token_Rec  token;
1490
1491
1492             /* skip the `known' keyword and the token following it */
1493             cur += 5;
1494             loader->parser.cursor = cur;
1495             Z1_ToToken( &loader->parser, &token );
1496
1497             /* if the last token was an array, skip it! */
1498             if ( token.type == t1_token_array )
1499               cur2 = parser->cursor;
1500           }
1501           cur = cur2;
1502         }
1503         /* look for immediates */
1504         else if ( *cur == '/' && cur + 2 < limit )
1505         {
1506           FT_Byte*  cur2;
1507           FT_Int    len;
1508
1509
1510           cur++;
1511           cur2 = cur;
1512           while ( cur2 < limit && is_alpha( *cur2 ) )
1513             cur2++;
1514
1515           len  = cur2 - cur;
1516           if ( len > 0 && len < 22 )
1517           {
1518             if ( !loader->fontdata )
1519             {
1520               if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
1521                 loader->fontdata = 1;
1522             }
1523             else
1524             {
1525               /* now, compare the immediate name to the keyword table */
1526               Z1_KeyWord*  keyword = (Z1_KeyWord*)t1_keywords;
1527
1528
1529               for (;;)
1530               {
1531                 FT_Byte*  name;
1532
1533
1534                 name = (FT_Byte*)keyword->name;
1535                 if ( !name )
1536                   break;
1537
1538                 if ( cur[0] == name[0]                          &&
1539                      len == (FT_Int)strlen( (const char*)name ) )
1540                 {
1541                   FT_Int  n;
1542
1543
1544                   for ( n = 1; n < len; n++ )
1545                     if ( cur[n] != name[n] )
1546                       break;
1547
1548                   if ( n >= len )
1549                   {
1550                     /* we found it -- run the parsing callback! */
1551                     parser->cursor = cur2;
1552                     skip_whitespace( parser );
1553                     parser->error = t1_load_keyword( face, loader, keyword );
1554                     if ( parser->error )
1555                       return parser->error;
1556
1557                     cur = parser->cursor;
1558                     break;
1559                   }
1560                 }
1561                 keyword++;
1562               }
1563             }
1564           }
1565         }
1566       }
1567     }
1568     return parser->error;
1569   }
1570
1571
1572   static
1573   void  t1_init_loader( Z1_Loader*  loader,
1574                         T1_Face     face )
1575   {
1576     FT_UNUSED( face );
1577
1578     MEM_Set( loader, 0, sizeof ( *loader ) );
1579     loader->num_glyphs = 0;
1580     loader->num_chars  = 0;
1581
1582     /* initialize the tables -- simply set their `init' field to 0 */
1583     loader->encoding_table.init = 0;
1584     loader->charstrings.init    = 0;
1585     loader->glyph_names.init    = 0;
1586     loader->subrs.init          = 0;
1587     loader->fontdata            = 0;
1588   }
1589
1590
1591   static
1592   void  t1_done_loader( Z1_Loader*  loader )
1593   {
1594     Z1_Parser*  parser = &loader->parser;
1595
1596
1597     /* finalize tables */
1598     Z1_Release_Table( &loader->encoding_table );
1599     Z1_Release_Table( &loader->charstrings );
1600     Z1_Release_Table( &loader->glyph_names );
1601     Z1_Release_Table( &loader->subrs );
1602
1603     /* finalize parser */
1604     Z1_Done_Parser( parser );
1605   }
1606
1607
1608   LOCAL_FUNC
1609   FT_Error  Z1_Open_Face( T1_Face  face )
1610   {
1611     Z1_Loader   loader;
1612     Z1_Parser*  parser;
1613     T1_Font*    type1 = &face->type1;
1614     FT_Error    error;
1615
1616
1617     t1_init_loader( &loader, face );
1618
1619     /* default lenIV */
1620     type1->private_dict.lenIV = 4;
1621
1622     parser = &loader.parser;
1623     error = Z1_New_Parser( parser, face->root.stream, face->root.memory );
1624     if ( error )
1625       goto Exit;
1626
1627     error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
1628     if ( error )
1629       goto Exit;
1630
1631     error = Z1_Get_Private_Dict( parser );
1632     if ( error )
1633       goto Exit;
1634
1635     error = parse_dict( face, &loader, parser->private_dict,
1636                         parser->private_len );
1637     if ( error )
1638       goto Exit;
1639
1640     /* now, propagate the subrs, charstrings, and glyphnames tables */
1641     /* to the Type1 data                                            */
1642     type1->num_glyphs = loader.num_glyphs;
1643
1644     if ( !loader.subrs.init )
1645     {
1646       FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" ));
1647       error = T1_Err_Invalid_File_Format;
1648     }
1649
1650     if ( !loader.charstrings.init )
1651     {
1652       FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" ));
1653       error = T1_Err_Invalid_File_Format;
1654     }
1655
1656     loader.subrs.init  = 0;
1657     type1->num_subrs   = loader.num_subrs;
1658     type1->subrs_block = loader.subrs.block;
1659     type1->subrs       = loader.subrs.elements;
1660     type1->subrs_len   = loader.subrs.lengths;
1661
1662     loader.charstrings.init  = 0;
1663     type1->charstrings_block = loader.charstrings.block;
1664     type1->charstrings       = loader.charstrings.elements;
1665     type1->charstrings_len   = loader.charstrings.lengths;
1666
1667     /* we copy the glyph names `block' and `elements' fields; */
1668     /* the `lengths' field must be released later             */
1669     type1->glyph_names_block    = loader.glyph_names.block;
1670     type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
1671     loader.glyph_names.block    = 0;
1672     loader.glyph_names.elements = 0;
1673
1674     /* we must now build type1.encoding when we have a custom */
1675     /* array..                                                */
1676     if ( type1->encoding_type == t1_encoding_array )
1677     {
1678       FT_Int    charcode, index, min_char, max_char;
1679       FT_Byte*  char_name;
1680       FT_Byte*  glyph_name;
1681
1682
1683       /* OK, we do the following: for each element in the encoding  */
1684       /* table, look up the index of the glyph having the same name */
1685       /* the index is then stored in type1.encoding.char_index, and */
1686       /* a the name to type1.encoding.char_name                     */
1687
1688       min_char = +32000;
1689       max_char = -32000;
1690
1691       charcode = 0;
1692       for ( ; charcode < loader.encoding_table.num_elems; charcode++ )
1693       {
1694         type1->encoding.char_index[charcode] = 0;
1695         type1->encoding.char_name [charcode] = ".notdef";
1696
1697         char_name = loader.encoding_table.elements[charcode];
1698         if ( char_name )
1699           for ( index = 0; index < type1->num_glyphs; index++ )
1700           {
1701             glyph_name = (FT_Byte*)type1->glyph_names[index];
1702             if ( strcmp( (const char*)char_name,
1703                          (const char*)glyph_name ) == 0 )
1704             {
1705               type1->encoding.char_index[charcode] = index;
1706               type1->encoding.char_name [charcode] = (char*)glyph_name;
1707
1708               if (charcode < min_char) min_char = charcode;
1709               if (charcode > max_char) max_char = charcode;
1710               break;
1711             }
1712           }
1713       }
1714       type1->encoding.code_first = min_char;
1715       type1->encoding.code_last  = max_char;
1716       type1->encoding.num_chars  = loader.num_chars;
1717    }
1718
1719   Exit:
1720     t1_done_loader( &loader );
1721     return error;
1722   }
1723
1724
1725 /* END */