• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * t1load.c
4  *
5  *   Type 1 font loader (body).
6  *
7  * Copyright (C) 1996-2019 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.  This file is included twice here; the first
45    * time to generate parsing callback functions, the second time to
46    * generate a table of keywords (with pointers to the associated
47    * callback functions).
48    *
49    * The function `parse_dict' simply scans *linearly* a given dictionary
50    * (either the top-level or private one) and calls the appropriate
51    * callback when it encounters an immediate keyword.
52    *
53    * This is by far the fastest way one can find to parse and read all
54    * data.
55    *
56    * This led to tremendous code size reduction.  Note that later, the
57    * glyph loader will also be _greatly_ simplified, and the automatic
58    * hinter will replace the clumsy `t1hinter'.
59    *
60    */
61 
62 
63 #include <ft2build.h>
64 #include FT_INTERNAL_DEBUG_H
65 #include FT_CONFIG_CONFIG_H
66 #include FT_MULTIPLE_MASTERS_H
67 #include FT_INTERNAL_TYPE1_TYPES_H
68 #include FT_INTERNAL_CALC_H
69 #include FT_INTERNAL_HASH_H
70 
71 #include "t1load.h"
72 #include "t1errors.h"
73 
74 
75 #ifdef FT_CONFIG_OPTION_INCREMENTAL
76 #define IS_INCREMENTAL  FT_BOOL( face->root.internal->incremental_interface )
77 #else
78 #define IS_INCREMENTAL  0
79 #endif
80 
81 
82   /**************************************************************************
83    *
84    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
85    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
86    * messages during execution.
87    */
88 #undef  FT_COMPONENT
89 #define FT_COMPONENT  t1load
90 
91 
92 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
93 
94 
95   /*************************************************************************/
96   /*************************************************************************/
97   /*****                                                               *****/
98   /*****                    MULTIPLE MASTERS SUPPORT                   *****/
99   /*****                                                               *****/
100   /*************************************************************************/
101   /*************************************************************************/
102 
103   static FT_Error
t1_allocate_blend(T1_Face face,FT_UInt num_designs,FT_UInt num_axis)104   t1_allocate_blend( T1_Face  face,
105                      FT_UInt  num_designs,
106                      FT_UInt  num_axis )
107   {
108     PS_Blend   blend;
109     FT_Memory  memory = face->root.memory;
110     FT_Error   error  = FT_Err_Ok;
111 
112 
113     blend = face->blend;
114     if ( !blend )
115     {
116       if ( FT_NEW( blend ) )
117         goto Exit;
118 
119       blend->num_default_design_vector = 0;
120 
121       face->blend = blend;
122     }
123 
124     /* allocate design data if needed */
125     if ( num_designs > 0 )
126     {
127       if ( blend->num_designs == 0 )
128       {
129         FT_UInt  nn;
130 
131 
132         /* allocate the blend `private' and `font_info' dictionaries */
133         if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs     ) ||
134              FT_NEW_ARRAY( blend->privates  [1], num_designs     ) ||
135              FT_NEW_ARRAY( blend->bboxes    [1], num_designs     ) ||
136              FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) )
137           goto Exit;
138 
139         blend->default_weight_vector = blend->weight_vector + num_designs;
140 
141         blend->font_infos[0] = &face->type1.font_info;
142         blend->privates  [0] = &face->type1.private_dict;
143         blend->bboxes    [0] = &face->type1.font_bbox;
144 
145         for ( nn = 2; nn <= num_designs; nn++ )
146         {
147           blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
148           blend->privates  [nn] = blend->privates  [nn - 1] + 1;
149           blend->bboxes    [nn] = blend->bboxes    [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 ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) )
176         goto Exit;
177 
178       for ( n = 1; n < num_designs; n++ )
179         blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
180     }
181 
182   Exit:
183     return error;
184 
185   Fail:
186     error = FT_THROW( Invalid_File_Format );
187     goto Exit;
188   }
189 
190 
191   FT_LOCAL_DEF( FT_Error )
T1_Get_Multi_Master(T1_Face face,FT_Multi_Master * master)192   T1_Get_Multi_Master( T1_Face           face,
193                        FT_Multi_Master*  master )
194   {
195     PS_Blend  blend = face->blend;
196     FT_UInt   n;
197     FT_Error  error;
198 
199 
200     error = FT_THROW( Invalid_Argument );
201 
202     if ( blend )
203     {
204       master->num_axis    = blend->num_axis;
205       master->num_designs = blend->num_designs;
206 
207       for ( n = 0; n < blend->num_axis; n++ )
208       {
209         FT_MM_Axis*   axis = master->axis + n;
210         PS_DesignMap  map = blend->design_map + n;
211 
212 
213         axis->name    = blend->axis_names[n];
214         axis->minimum = map->design_points[0];
215         axis->maximum = map->design_points[map->num_points - 1];
216       }
217 
218       error = FT_Err_Ok;
219     }
220 
221     return error;
222   }
223 
224 
225   /**************************************************************************
226    *
227    * Given a normalized (blend) coordinate, figure out the design
228    * coordinate appropriate for that value.
229    */
230   static FT_Fixed
mm_axis_unmap(PS_DesignMap axismap,FT_Fixed ncv)231   mm_axis_unmap( PS_DesignMap  axismap,
232                  FT_Fixed      ncv )
233   {
234     int  j;
235 
236 
237     if ( ncv <= axismap->blend_points[0] )
238       return INT_TO_FIXED( axismap->design_points[0] );
239 
240     for ( j = 1; j < axismap->num_points; j++ )
241     {
242       if ( ncv <= axismap->blend_points[j] )
243         return INT_TO_FIXED( axismap->design_points[j - 1] ) +
244                ( axismap->design_points[j] - axismap->design_points[j - 1] ) *
245                FT_DivFix( ncv - axismap->blend_points[j - 1],
246                           axismap->blend_points[j] -
247                             axismap->blend_points[j - 1] );
248     }
249 
250     return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] );
251   }
252 
253 
254   /**************************************************************************
255    *
256    * Given a vector of weights, one for each design, figure out the
257    * normalized axis coordinates which gave rise to those weights.
258    */
259   static void
mm_weights_unmap(FT_Fixed * weights,FT_Fixed * axiscoords,FT_UInt axis_count)260   mm_weights_unmap( FT_Fixed*  weights,
261                     FT_Fixed*  axiscoords,
262                     FT_UInt    axis_count )
263   {
264     FT_ASSERT( axis_count <= T1_MAX_MM_AXIS );
265 
266     if ( axis_count == 1 )
267       axiscoords[0] = weights[1];
268 
269     else if ( axis_count == 2 )
270     {
271       axiscoords[0] = weights[3] + weights[1];
272       axiscoords[1] = weights[3] + weights[2];
273     }
274 
275     else if ( axis_count == 3 )
276     {
277       axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1];
278       axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2];
279       axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4];
280     }
281 
282     else
283     {
284       axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] +
285                         weights[7] + weights[5] + weights[3] + weights[1];
286       axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] +
287                         weights[7] + weights[6] + weights[3] + weights[2];
288       axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] +
289                         weights[7] + weights[6] + weights[5] + weights[4];
290       axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] +
291                         weights[11] + weights[10] + weights[9] + weights[8];
292     }
293   }
294 
295 
296   /**************************************************************************
297    *
298    * Just a wrapper around T1_Get_Multi_Master to support the different
299    * arguments needed by the GX var distortable fonts.
300    */
301   FT_LOCAL_DEF( FT_Error )
T1_Get_MM_Var(T1_Face face,FT_MM_Var ** master)302   T1_Get_MM_Var( T1_Face      face,
303                  FT_MM_Var*  *master )
304   {
305     FT_Memory        memory = face->root.memory;
306     FT_MM_Var       *mmvar = NULL;
307     FT_Multi_Master  mmaster;
308     FT_Error         error;
309     FT_UInt          i;
310     FT_Fixed         axiscoords[T1_MAX_MM_AXIS];
311     PS_Blend         blend = face->blend;
312 
313 
314     error = T1_Get_Multi_Master( face, &mmaster );
315     if ( error )
316       goto Exit;
317     if ( FT_ALLOC( mmvar,
318                    sizeof ( FT_MM_Var ) +
319                      mmaster.num_axis * sizeof ( FT_Var_Axis ) ) )
320       goto Exit;
321 
322     mmvar->num_axis        = mmaster.num_axis;
323     mmvar->num_designs     = mmaster.num_designs;
324     mmvar->num_namedstyles = 0;                           /* Not supported */
325     mmvar->axis            = (FT_Var_Axis*)&mmvar[1];
326                                       /* Point to axes after MM_Var struct */
327     mmvar->namedstyle      = NULL;
328 
329     for ( i = 0; i < mmaster.num_axis; i++ )
330     {
331       mmvar->axis[i].name    = mmaster.axis[i].name;
332       mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum );
333       mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum );
334       mmvar->axis[i].def     = ( mmvar->axis[i].minimum +
335                                    mmvar->axis[i].maximum ) / 2;
336                             /* Does not apply.  But this value is in range */
337       mmvar->axis[i].strid   = ~0U;                      /* Does not apply */
338       mmvar->axis[i].tag     = ~0U;                      /* Does not apply */
339 
340       if ( !mmvar->axis[i].name )
341         continue;
342 
343       if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 )
344         mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' );
345       else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 )
346         mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' );
347       else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 )
348         mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' );
349     }
350 
351     mm_weights_unmap( blend->default_weight_vector,
352                       axiscoords,
353                       blend->num_axis );
354 
355     for ( i = 0; i < mmaster.num_axis; i++ )
356       mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i],
357                                           axiscoords[i] );
358 
359     *master = mmvar;
360 
361   Exit:
362     return error;
363   }
364 
365 
366   static FT_Error
t1_set_mm_blend(T1_Face face,FT_UInt num_coords,FT_Fixed * coords)367   t1_set_mm_blend( T1_Face    face,
368                    FT_UInt    num_coords,
369                    FT_Fixed*  coords )
370   {
371     PS_Blend  blend = face->blend;
372     FT_UInt   n, m;
373 
374     FT_Bool  have_diff = 0;
375 
376 
377     if ( !blend )
378       return FT_THROW( Invalid_Argument );
379 
380     if ( num_coords > blend->num_axis )
381       num_coords = blend->num_axis;
382 
383     /* recompute the weight vector from the blend coordinates */
384     for ( n = 0; n < blend->num_designs; n++ )
385     {
386       FT_Fixed  result = 0x10000L;  /* 1.0 fixed */
387       FT_Fixed  factor;
388 
389 
390       for ( m = 0; m < blend->num_axis; m++ )
391       {
392         /* use a default value if we don't have a coordinate */
393         if ( m >= num_coords )
394         {
395           result >>= 1;
396           continue;
397         }
398 
399         /* get current blend axis position */
400         factor = coords[m];
401         if ( ( n & ( 1 << m ) ) == 0 )
402           factor = 0x10000L - factor;
403 
404         if ( factor <= 0 )
405         {
406           result = 0;
407           break;
408         }
409         else if ( factor >= 0x10000L )
410           continue;
411 
412         result = FT_MulFix( result, factor );
413       }
414 
415       if ( blend->weight_vector[n] != result )
416       {
417         blend->weight_vector[n] = result;
418         have_diff               = 1;
419       }
420     }
421 
422     /* return value -1 indicates `no change' */
423     return have_diff ? FT_Err_Ok : -1;
424   }
425 
426 
427   FT_LOCAL_DEF( FT_Error )
T1_Set_MM_Blend(T1_Face face,FT_UInt num_coords,FT_Fixed * coords)428   T1_Set_MM_Blend( T1_Face    face,
429                    FT_UInt    num_coords,
430                    FT_Fixed*  coords )
431   {
432     FT_Error  error;
433 
434 
435     error = t1_set_mm_blend( face, num_coords, coords );
436     if ( error )
437       return error;
438 
439     if ( num_coords )
440       face->root.face_flags |= FT_FACE_FLAG_VARIATION;
441     else
442       face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
443 
444     return FT_Err_Ok;
445   }
446 
447 
448   FT_LOCAL_DEF( FT_Error )
T1_Get_MM_Blend(T1_Face face,FT_UInt num_coords,FT_Fixed * coords)449   T1_Get_MM_Blend( T1_Face    face,
450                    FT_UInt    num_coords,
451                    FT_Fixed*  coords )
452   {
453     PS_Blend  blend = face->blend;
454 
455     FT_Fixed  axiscoords[4];
456     FT_UInt   i, nc;
457 
458 
459     if ( !blend )
460       return FT_THROW( Invalid_Argument );
461 
462     mm_weights_unmap( blend->weight_vector,
463                       axiscoords,
464                       blend->num_axis );
465 
466     nc = num_coords;
467     if ( num_coords > blend->num_axis )
468     {
469       FT_TRACE2(( "T1_Get_MM_Blend: only using first %d of %d coordinates\n",
470                   blend->num_axis, num_coords ));
471       nc = blend->num_axis;
472     }
473 
474     for ( i = 0; i < nc; i++ )
475       coords[i] = axiscoords[i];
476     for ( ; i < num_coords; i++ )
477       coords[i] = 0x8000;
478 
479     return FT_Err_Ok;
480   }
481 
482 
483   FT_LOCAL_DEF( FT_Error )
T1_Set_MM_WeightVector(T1_Face face,FT_UInt len,FT_Fixed * weightvector)484   T1_Set_MM_WeightVector( T1_Face    face,
485                           FT_UInt    len,
486                           FT_Fixed*  weightvector )
487   {
488     PS_Blend  blend = face->blend;
489     FT_UInt   i, n;
490 
491 
492     if ( !blend )
493      return FT_THROW( Invalid_Argument );
494 
495     if ( !len && !weightvector )
496     {
497       for ( i = 0; i < blend->num_designs; i++ )
498         blend->weight_vector[i] = blend->default_weight_vector[i];
499     }
500     else
501     {
502       if ( !weightvector )
503         return FT_THROW( Invalid_Argument );
504 
505       n = len < blend->num_designs ? len : blend->num_designs;
506 
507       for ( i = 0; i < n; i++ )
508         blend->weight_vector[i] = weightvector[i];
509 
510       for ( ; i < blend->num_designs; i++ )
511         blend->weight_vector[i] = (FT_Fixed)0;
512 
513       if ( len )
514         face->root.face_flags |= FT_FACE_FLAG_VARIATION;
515       else
516         face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
517     }
518 
519     return FT_Err_Ok;
520   }
521 
522 
523   FT_LOCAL_DEF( FT_Error )
T1_Get_MM_WeightVector(T1_Face face,FT_UInt * len,FT_Fixed * weightvector)524   T1_Get_MM_WeightVector( T1_Face    face,
525                           FT_UInt*   len,
526                           FT_Fixed*  weightvector )
527   {
528     PS_Blend  blend = face->blend;
529     FT_UInt   i;
530 
531 
532     if ( !blend )
533       return FT_THROW( Invalid_Argument );
534 
535     if ( *len < blend->num_designs )
536     {
537       *len = blend->num_designs;
538       return FT_THROW( Invalid_Argument );
539     }
540 
541     for ( i = 0; i < blend->num_designs; i++ )
542       weightvector[i] = blend->weight_vector[i];
543     for ( ; i < *len; i++ )
544       weightvector[i] = (FT_Fixed)0;
545 
546     *len = blend->num_designs;
547 
548     return FT_Err_Ok;
549   }
550 
551 
552   FT_LOCAL_DEF( FT_Error )
T1_Set_MM_Design(T1_Face face,FT_UInt num_coords,FT_Long * coords)553   T1_Set_MM_Design( T1_Face   face,
554                     FT_UInt   num_coords,
555                     FT_Long*  coords )
556   {
557     FT_Error  error;
558     PS_Blend  blend = face->blend;
559     FT_UInt   n, p;
560     FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
561 
562 
563     if ( !blend )
564       return FT_THROW( Invalid_Argument );
565 
566     if ( num_coords > blend->num_axis )
567       num_coords = blend->num_axis;
568 
569     /* compute the blend coordinates through the blend design map */
570 
571     for ( n = 0; n < blend->num_axis; n++ )
572     {
573       FT_Long       design;
574       FT_Fixed      the_blend;
575       PS_DesignMap  map     = blend->design_map + n;
576       FT_Long*      designs = map->design_points;
577       FT_Fixed*     blends  = map->blend_points;
578       FT_Int        before  = -1, after = -1;
579 
580 
581       /* use a default value if we don't have a coordinate */
582       if ( n < num_coords )
583         design = coords[n];
584       else
585         design = ( designs[map->num_points - 1] - designs[0] ) / 2;
586 
587       for ( p = 0; p < (FT_UInt)map->num_points; p++ )
588       {
589         FT_Long  p_design = designs[p];
590 
591 
592         /* exact match? */
593         if ( design == p_design )
594         {
595           the_blend = blends[p];
596           goto Found;
597         }
598 
599         if ( design < p_design )
600         {
601           after = (FT_Int)p;
602           break;
603         }
604 
605         before = (FT_Int)p;
606       }
607 
608       /* now interpolate if necessary */
609       if ( before < 0 )
610         the_blend = blends[0];
611 
612       else if ( after < 0 )
613         the_blend = blends[map->num_points - 1];
614 
615       else
616         the_blend = FT_MulDiv( design         - designs[before],
617                                blends [after] - blends [before],
618                                designs[after] - designs[before] );
619 
620     Found:
621       final_blends[n] = the_blend;
622     }
623 
624     error = t1_set_mm_blend( face, blend->num_axis, final_blends );
625     if ( error )
626       return error;
627 
628     if ( num_coords )
629       face->root.face_flags |= FT_FACE_FLAG_VARIATION;
630     else
631       face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
632 
633     return FT_Err_Ok;
634   }
635 
636 
637   /* MM fonts don't have named instances, so only the design is reset */
638 
639   FT_LOCAL_DEF( FT_Error )
T1_Reset_MM_Blend(T1_Face face,FT_UInt instance_index)640   T1_Reset_MM_Blend( T1_Face  face,
641                      FT_UInt  instance_index )
642   {
643     FT_UNUSED( instance_index );
644 
645     return T1_Set_MM_Blend( face, 0, NULL );
646   }
647 
648 
649   /**************************************************************************
650    *
651    * Just a wrapper around T1_Set_MM_Design to support the different
652    * arguments needed by the GX var distortable fonts.
653    */
654   FT_LOCAL_DEF( FT_Error )
T1_Set_Var_Design(T1_Face face,FT_UInt num_coords,FT_Fixed * coords)655   T1_Set_Var_Design( T1_Face    face,
656                      FT_UInt    num_coords,
657                      FT_Fixed*  coords )
658   {
659      FT_Long  lcoords[T1_MAX_MM_AXIS];
660      FT_UInt  i;
661 
662 
663      if ( num_coords > T1_MAX_MM_AXIS )
664        num_coords = T1_MAX_MM_AXIS;
665 
666      for ( i = 0; i < num_coords; i++ )
667        lcoords[i] = FIXED_TO_INT( coords[i] );
668 
669      return T1_Set_MM_Design( face, num_coords, lcoords );
670   }
671 
672 
673   FT_LOCAL_DEF( FT_Error )
T1_Get_Var_Design(T1_Face face,FT_UInt num_coords,FT_Fixed * coords)674   T1_Get_Var_Design( T1_Face    face,
675                      FT_UInt    num_coords,
676                      FT_Fixed*  coords )
677   {
678     PS_Blend  blend = face->blend;
679 
680     FT_Fixed  axiscoords[4];
681     FT_UInt   i, nc;
682 
683 
684     if ( !blend )
685       return FT_THROW( Invalid_Argument );
686 
687     mm_weights_unmap( blend->weight_vector,
688                       axiscoords,
689                       blend->num_axis );
690 
691     nc = num_coords;
692     if ( num_coords > blend->num_axis )
693     {
694       FT_TRACE2(( "T1_Get_Var_Design:"
695                   " only using first %d of %d coordinates\n",
696                   blend->num_axis, num_coords ));
697       nc = blend->num_axis;
698     }
699 
700     for ( i = 0; i < nc; i++ )
701       coords[i] = mm_axis_unmap( &blend->design_map[i], axiscoords[i] );
702     for ( ; i < num_coords; i++ )
703       coords[i] = 0;
704 
705     return FT_Err_Ok;
706   }
707 
708 
709   FT_LOCAL_DEF( void )
T1_Done_Blend(T1_Face face)710   T1_Done_Blend( T1_Face  face )
711   {
712     FT_Memory  memory = face->root.memory;
713     PS_Blend   blend  = face->blend;
714 
715 
716     if ( blend )
717     {
718       FT_UInt  num_designs = blend->num_designs;
719       FT_UInt  num_axis    = blend->num_axis;
720       FT_UInt  n;
721 
722 
723       /* release design pos table */
724       FT_FREE( blend->design_pos[0] );
725       for ( n = 1; n < num_designs; n++ )
726         blend->design_pos[n] = NULL;
727 
728       /* release blend `private' and `font info' dictionaries */
729       FT_FREE( blend->privates[1] );
730       FT_FREE( blend->font_infos[1] );
731       FT_FREE( blend->bboxes[1] );
732 
733       for ( n = 0; n < num_designs; n++ )
734       {
735         blend->privates  [n] = NULL;
736         blend->font_infos[n] = NULL;
737         blend->bboxes    [n] = NULL;
738       }
739 
740       /* release weight vectors */
741       FT_FREE( blend->weight_vector );
742       blend->default_weight_vector = NULL;
743 
744       /* release axis names */
745       for ( n = 0; n < num_axis; n++ )
746         FT_FREE( blend->axis_names[n] );
747 
748       /* release design map */
749       for ( n = 0; n < num_axis; n++ )
750       {
751         PS_DesignMap  dmap = blend->design_map + n;
752 
753 
754         FT_FREE( dmap->design_points );
755         dmap->num_points = 0;
756       }
757 
758       FT_FREE( face->blend );
759     }
760   }
761 
762 
763   static void
parse_blend_axis_types(T1_Face face,T1_Loader loader)764   parse_blend_axis_types( T1_Face    face,
765                           T1_Loader  loader )
766   {
767     T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
768     FT_Int       n, num_axis;
769     FT_Error     error = FT_Err_Ok;
770     PS_Blend     blend;
771     FT_Memory    memory;
772 
773 
774     /* take an array of objects */
775     T1_ToTokenArray( &loader->parser, axis_tokens,
776                      T1_MAX_MM_AXIS, &num_axis );
777     if ( num_axis < 0 )
778     {
779       error = FT_ERR( Ignore );
780       goto Exit;
781     }
782     if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
783     {
784       FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
785                  num_axis ));
786       error = FT_THROW( Invalid_File_Format );
787       goto Exit;
788     }
789 
790     /* allocate blend if necessary */
791     error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
792     if ( error )
793       goto Exit;
794 
795     FT_TRACE4(( " [" ));
796 
797     blend  = face->blend;
798     memory = face->root.memory;
799 
800     /* each token is an immediate containing the name of the axis */
801     for ( n = 0; n < num_axis; n++ )
802     {
803       T1_Token  token = axis_tokens + n;
804       FT_Byte*  name;
805       FT_UInt   len;
806 
807 
808       /* skip first slash, if any */
809       if ( token->start[0] == '/' )
810         token->start++;
811 
812       len = (FT_UInt)( token->limit - token->start );
813       if ( len == 0 )
814       {
815         error = FT_THROW( Invalid_File_Format );
816         goto Exit;
817       }
818 
819       FT_TRACE4(( " /%.*s", len, token->start ));
820 
821       name = (FT_Byte*)blend->axis_names[n];
822       if ( name )
823       {
824         FT_TRACE0(( "parse_blend_axis_types:"
825                     " overwriting axis name `%s' with `%.*s'\n",
826                     name, len, token->start ));
827         FT_FREE( name );
828       }
829 
830       if ( FT_ALLOC( blend->axis_names[n], len + 1 ) )
831         goto Exit;
832 
833       name = (FT_Byte*)blend->axis_names[n];
834       FT_MEM_COPY( name, token->start, len );
835       name[len] = '\0';
836     }
837 
838     FT_TRACE4(( "]\n" ));
839 
840   Exit:
841     loader->parser.root.error = error;
842   }
843 
844 
845   static void
parse_blend_design_positions(T1_Face face,T1_Loader loader)846   parse_blend_design_positions( T1_Face    face,
847                                 T1_Loader  loader )
848   {
849     T1_TokenRec  design_tokens[T1_MAX_MM_DESIGNS];
850     FT_Int       num_designs;
851     FT_Int       num_axis;
852     T1_Parser    parser = &loader->parser;
853 
854     FT_Error     error = FT_Err_Ok;
855     PS_Blend     blend;
856 
857 
858     /* get the array of design tokens -- compute number of designs */
859     T1_ToTokenArray( parser, design_tokens,
860                      T1_MAX_MM_DESIGNS, &num_designs );
861     if ( num_designs < 0 )
862     {
863       error = FT_ERR( Ignore );
864       goto Exit;
865     }
866     if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
867     {
868       FT_ERROR(( "parse_blend_design_positions:"
869                  " incorrect number of designs: %d\n",
870                  num_designs ));
871       error = FT_THROW( Invalid_File_Format );
872       goto Exit;
873     }
874 
875     {
876       FT_Byte*  old_cursor = parser->root.cursor;
877       FT_Byte*  old_limit  = parser->root.limit;
878       FT_Int    n;
879 
880 
881       blend    = face->blend;
882       num_axis = 0;  /* make compiler happy */
883 
884       FT_TRACE4(( " [" ));
885 
886       for ( n = 0; n < num_designs; n++ )
887       {
888         T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
889         T1_Token     token;
890         FT_Int       axis, n_axis;
891 
892 
893         /* read axis/coordinates tokens */
894         token = design_tokens + n;
895         parser->root.cursor = token->start;
896         parser->root.limit  = token->limit;
897         T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
898 
899         if ( n == 0 )
900         {
901           if ( n_axis <= 0 || n_axis > T1_MAX_MM_AXIS )
902           {
903             FT_ERROR(( "parse_blend_design_positions:"
904                        " invalid number of axes: %d\n",
905                        n_axis ));
906             error = FT_THROW( Invalid_File_Format );
907             goto Exit;
908           }
909 
910           num_axis = n_axis;
911           error = t1_allocate_blend( face,
912                                      (FT_UInt)num_designs,
913                                      (FT_UInt)num_axis );
914           if ( error )
915             goto Exit;
916           blend = face->blend;
917         }
918         else if ( n_axis != num_axis )
919         {
920           FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
921           error = FT_THROW( Invalid_File_Format );
922           goto Exit;
923         }
924 
925         /* now read each axis token into the design position */
926         FT_TRACE4(( " [" )) ;
927         for ( axis = 0; axis < n_axis; axis++ )
928         {
929           T1_Token  token2 = axis_tokens + axis;
930 
931 
932           parser->root.cursor = token2->start;
933           parser->root.limit  = token2->limit;
934           blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
935           FT_TRACE4(( " %f", (double)blend->design_pos[n][axis] / 65536 ));
936         }
937         FT_TRACE4(( "]" )) ;
938       }
939 
940       FT_TRACE4(( "]\n" ));
941 
942       loader->parser.root.cursor = old_cursor;
943       loader->parser.root.limit  = old_limit;
944     }
945 
946   Exit:
947     loader->parser.root.error = error;
948   }
949 
950 
951   static void
parse_blend_design_map(T1_Face face,T1_Loader loader)952   parse_blend_design_map( T1_Face    face,
953                           T1_Loader  loader )
954   {
955     FT_Error     error  = FT_Err_Ok;
956     T1_Parser    parser = &loader->parser;
957     PS_Blend     blend;
958     T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
959     FT_Int       n, num_axis;
960     FT_Byte*     old_cursor;
961     FT_Byte*     old_limit;
962     FT_Memory    memory = face->root.memory;
963 
964 
965     T1_ToTokenArray( parser, axis_tokens,
966                      T1_MAX_MM_AXIS, &num_axis );
967     if ( num_axis < 0 )
968     {
969       error = FT_ERR( Ignore );
970       goto Exit;
971     }
972     if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
973     {
974       FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
975                  num_axis ));
976       error = FT_THROW( Invalid_File_Format );
977       goto Exit;
978     }
979 
980     old_cursor = parser->root.cursor;
981     old_limit  = parser->root.limit;
982 
983     error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
984     if ( error )
985       goto Exit;
986     blend = face->blend;
987 
988     FT_TRACE4(( " [" ));
989 
990     /* now read each axis design map */
991     for ( n = 0; n < num_axis; n++ )
992     {
993       PS_DesignMap  map = blend->design_map + n;
994       T1_Token      axis_token;
995       T1_TokenRec   point_tokens[T1_MAX_MM_MAP_POINTS];
996       FT_Int        p, num_points;
997 
998 
999       axis_token = axis_tokens + n;
1000 
1001       parser->root.cursor = axis_token->start;
1002       parser->root.limit  = axis_token->limit;
1003       T1_ToTokenArray( parser, point_tokens,
1004                        T1_MAX_MM_MAP_POINTS, &num_points );
1005 
1006       FT_TRACE4(( " [" ));
1007 
1008       if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
1009       {
1010         FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
1011         error = FT_THROW( Invalid_File_Format );
1012         goto Exit;
1013       }
1014 
1015       if ( map->design_points )
1016       {
1017         FT_ERROR(( "parse_blend_design_map: duplicate table\n" ));
1018         error = FT_THROW( Invalid_File_Format );
1019         goto Exit;
1020       }
1021 
1022       /* allocate design map data */
1023       if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) )
1024         goto Exit;
1025       map->blend_points = map->design_points + num_points;
1026       map->num_points   = (FT_Byte)num_points;
1027 
1028       for ( p = 0; p < num_points; p++ )
1029       {
1030         T1_Token  point_token;
1031 
1032 
1033         point_token = point_tokens + p;
1034 
1035         /* don't include delimiting brackets */
1036         parser->root.cursor = point_token->start + 1;
1037         parser->root.limit  = point_token->limit - 1;
1038 
1039         map->design_points[p] = T1_ToInt( parser );
1040         map->blend_points [p] = T1_ToFixed( parser, 0 );
1041 
1042         FT_TRACE4(( " [%d %f]",
1043                     map->design_points[p],
1044                     (double)map->blend_points[p] / 65536 ));
1045       }
1046 
1047       FT_TRACE4(( "]" ));
1048     }
1049 
1050     FT_TRACE4(( "]\n" ));
1051 
1052     parser->root.cursor = old_cursor;
1053     parser->root.limit  = old_limit;
1054 
1055   Exit:
1056     parser->root.error = error;
1057   }
1058 
1059 
1060   static void
parse_weight_vector(T1_Face face,T1_Loader loader)1061   parse_weight_vector( T1_Face    face,
1062                        T1_Loader  loader )
1063   {
1064     T1_TokenRec  design_tokens[T1_MAX_MM_DESIGNS];
1065     FT_Int       num_designs;
1066     FT_Error     error  = FT_Err_Ok;
1067     T1_Parser    parser = &loader->parser;
1068     PS_Blend     blend  = face->blend;
1069     T1_Token     token;
1070     FT_Int       n;
1071     FT_Byte*     old_cursor;
1072     FT_Byte*     old_limit;
1073 
1074 
1075     T1_ToTokenArray( parser, design_tokens,
1076                      T1_MAX_MM_DESIGNS, &num_designs );
1077     if ( num_designs < 0 )
1078     {
1079       error = FT_ERR( Ignore );
1080       goto Exit;
1081     }
1082     if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
1083     {
1084       FT_ERROR(( "parse_weight_vector:"
1085                  " incorrect number of designs: %d\n",
1086                  num_designs ));
1087       error = FT_THROW( Invalid_File_Format );
1088       goto Exit;
1089     }
1090 
1091     if ( !blend || !blend->num_designs )
1092     {
1093       error = t1_allocate_blend( face, (FT_UInt)num_designs, 0 );
1094       if ( error )
1095         goto Exit;
1096       blend = face->blend;
1097     }
1098     else if ( blend->num_designs != (FT_UInt)num_designs )
1099     {
1100       FT_ERROR(( "parse_weight_vector:"
1101                  " /BlendDesignPosition and /WeightVector have\n"
1102                  "                    "
1103                  " different number of elements\n" ));
1104       error = FT_THROW( Invalid_File_Format );
1105       goto Exit;
1106     }
1107 
1108     old_cursor = parser->root.cursor;
1109     old_limit  = parser->root.limit;
1110 
1111     FT_TRACE4(( "[" ));
1112 
1113     for ( n = 0; n < num_designs; n++ )
1114     {
1115       token = design_tokens + n;
1116       parser->root.cursor = token->start;
1117       parser->root.limit  = token->limit;
1118 
1119       blend->default_weight_vector[n] =
1120       blend->weight_vector[n]         = T1_ToFixed( parser, 0 );
1121 
1122       FT_TRACE4(( " %f", (double)blend->weight_vector[n] / 65536 ));
1123     }
1124 
1125     FT_TRACE4(( "]\n" ));
1126 
1127     parser->root.cursor = old_cursor;
1128     parser->root.limit  = old_limit;
1129 
1130   Exit:
1131     parser->root.error = error;
1132   }
1133 
1134 
1135   /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def           */
1136   /* we're only interested in the number of array elements */
1137   static void
parse_buildchar(T1_Face face,T1_Loader loader)1138   parse_buildchar( T1_Face    face,
1139                    T1_Loader  loader )
1140   {
1141     face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser,
1142                                                     0, NULL, 0 );
1143 
1144 #ifdef FT_DEBUG_LEVEL_TRACE
1145     {
1146       FT_UInt  i;
1147 
1148 
1149       FT_TRACE4(( " [" ));
1150       for ( i = 0; i < face->len_buildchar; i++ )
1151         FT_TRACE4(( " 0" ));
1152 
1153       FT_TRACE4(( "]\n" ));
1154     }
1155 #endif
1156 
1157     return;
1158   }
1159 
1160 
1161 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
1162 
1163 
1164 
1165 
1166   /*************************************************************************/
1167   /*************************************************************************/
1168   /*****                                                               *****/
1169   /*****                      TYPE 1 SYMBOL PARSING                    *****/
1170   /*****                                                               *****/
1171   /*************************************************************************/
1172   /*************************************************************************/
1173 
1174   static FT_Error
t1_load_keyword(T1_Face face,T1_Loader loader,const T1_Field field)1175   t1_load_keyword( T1_Face         face,
1176                    T1_Loader       loader,
1177                    const T1_Field  field )
1178   {
1179     FT_Error  error;
1180     void*     dummy_object;
1181     void**    objects;
1182     FT_UInt   max_objects;
1183     PS_Blend  blend = face->blend;
1184 
1185 
1186     if ( blend && blend->num_designs == 0 )
1187       blend = NULL;
1188 
1189     /* if the keyword has a dedicated callback, call it */
1190     if ( field->type == T1_FIELD_TYPE_CALLBACK )
1191     {
1192       FT_TRACE4(( "  %s", field->ident ));
1193 
1194       field->reader( (FT_Face)face, loader );
1195       error = loader->parser.root.error;
1196       goto Exit;
1197     }
1198 
1199     /* now, the keyword is either a simple field, or a table of fields; */
1200     /* we are now going to take care of it                              */
1201     switch ( field->location )
1202     {
1203     case T1_FIELD_LOCATION_FONT_INFO:
1204       dummy_object = &face->type1.font_info;
1205       objects      = &dummy_object;
1206       max_objects  = 0;
1207 
1208       if ( blend )
1209       {
1210         objects     = (void**)blend->font_infos;
1211         max_objects = blend->num_designs;
1212       }
1213       break;
1214 
1215     case T1_FIELD_LOCATION_FONT_EXTRA:
1216       dummy_object = &face->type1.font_extra;
1217       objects      = &dummy_object;
1218       max_objects  = 0;
1219       break;
1220 
1221     case T1_FIELD_LOCATION_PRIVATE:
1222       dummy_object = &face->type1.private_dict;
1223       objects      = &dummy_object;
1224       max_objects  = 0;
1225 
1226       if ( blend )
1227       {
1228         objects     = (void**)blend->privates;
1229         max_objects = blend->num_designs;
1230       }
1231       break;
1232 
1233     case T1_FIELD_LOCATION_BBOX:
1234       dummy_object = &face->type1.font_bbox;
1235       objects      = &dummy_object;
1236       max_objects  = 0;
1237 
1238       if ( blend )
1239       {
1240         objects     = (void**)blend->bboxes;
1241         max_objects = blend->num_designs;
1242       }
1243       break;
1244 
1245     case T1_FIELD_LOCATION_LOADER:
1246       dummy_object = loader;
1247       objects      = &dummy_object;
1248       max_objects  = 0;
1249       break;
1250 
1251     case T1_FIELD_LOCATION_FACE:
1252       dummy_object = face;
1253       objects      = &dummy_object;
1254       max_objects  = 0;
1255       break;
1256 
1257 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
1258     case T1_FIELD_LOCATION_BLEND:
1259       dummy_object = face->blend;
1260       objects      = &dummy_object;
1261       max_objects  = 0;
1262       break;
1263 #endif
1264 
1265     default:
1266       dummy_object = &face->type1;
1267       objects      = &dummy_object;
1268       max_objects  = 0;
1269     }
1270 
1271     FT_TRACE4(( "  %s", field->ident ));
1272 
1273     if ( *objects )
1274     {
1275       if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
1276            field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
1277         error = T1_Load_Field_Table( &loader->parser, field,
1278                                      objects, max_objects, 0 );
1279       else
1280         error = T1_Load_Field( &loader->parser, field,
1281                                objects, max_objects, 0 );
1282     }
1283     else
1284     {
1285       FT_TRACE1(( "t1_load_keyword: ignoring keyword `%s'"
1286                   " which is not valid at this point\n"
1287                   "                 (probably due to missing keywords)\n",
1288                  field->ident ));
1289       error = FT_Err_Ok;
1290     }
1291 
1292     FT_TRACE4(( "\n" ));
1293 
1294   Exit:
1295     return error;
1296   }
1297 
1298 
1299   static void
parse_private(T1_Face face,T1_Loader loader)1300   parse_private( T1_Face    face,
1301                  T1_Loader  loader )
1302   {
1303     FT_UNUSED( face );
1304 
1305     loader->keywords_encountered |= T1_PRIVATE;
1306 
1307     FT_TRACE4(( "\n" ));
1308   }
1309 
1310 
1311   /* return 1 in case of success */
1312 
1313   static int
read_binary_data(T1_Parser parser,FT_ULong * size,FT_Byte ** base,FT_Bool incremental)1314   read_binary_data( T1_Parser  parser,
1315                     FT_ULong*  size,
1316                     FT_Byte**  base,
1317                     FT_Bool    incremental )
1318   {
1319     FT_Byte*  cur;
1320     FT_Byte*  limit = parser->root.limit;
1321 
1322 
1323     /* the binary data has one of the following formats */
1324     /*                                                  */
1325     /*   `size' [white*] RD white ....... ND            */
1326     /*   `size' [white*] -| white ....... |-            */
1327     /*                                                  */
1328 
1329     T1_Skip_Spaces( parser );
1330 
1331     cur = parser->root.cursor;
1332 
1333     if ( cur < limit && ft_isdigit( *cur ) )
1334     {
1335       FT_Long  s = T1_ToInt( parser );
1336 
1337 
1338       T1_Skip_PS_Token( parser );   /* `RD' or `-|' or something else */
1339 
1340       /* there is only one whitespace char after the */
1341       /* `RD' or `-|' token                          */
1342       *base = parser->root.cursor + 1;
1343 
1344       if ( s >= 0 && s < limit - *base )
1345       {
1346         parser->root.cursor += s + 1;
1347         *size = (FT_ULong)s;
1348         return !parser->root.error;
1349       }
1350     }
1351 
1352     if( !incremental )
1353     {
1354       FT_ERROR(( "read_binary_data: invalid size field\n" ));
1355       parser->root.error = FT_THROW( Invalid_File_Format );
1356     }
1357 
1358     return 0;
1359   }
1360 
1361 
1362   /* We now define the routines to handle the `/Encoding', `/Subrs', */
1363   /* and `/CharStrings' dictionaries.                                */
1364 
1365   static void
t1_parse_font_matrix(T1_Face face,T1_Loader loader)1366   t1_parse_font_matrix( T1_Face    face,
1367                         T1_Loader  loader )
1368   {
1369     T1_Parser   parser = &loader->parser;
1370     FT_Matrix*  matrix = &face->type1.font_matrix;
1371     FT_Vector*  offset = &face->type1.font_offset;
1372     FT_Face     root   = (FT_Face)&face->root;
1373     FT_Fixed    temp[6];
1374     FT_Fixed    temp_scale;
1375     FT_Int      result;
1376 
1377 
1378     /* input is scaled by 1000 to accommodate default FontMatrix */
1379     result = T1_ToFixedArray( parser, 6, temp, 3 );
1380 
1381     if ( result < 6 )
1382     {
1383       parser->root.error = FT_THROW( Invalid_File_Format );
1384       return;
1385     }
1386 
1387     FT_TRACE4(( " [%f %f %f %f %f %f]\n",
1388                 (double)temp[0] / 65536 / 1000,
1389                 (double)temp[1] / 65536 / 1000,
1390                 (double)temp[2] / 65536 / 1000,
1391                 (double)temp[3] / 65536 / 1000,
1392                 (double)temp[4] / 65536 / 1000,
1393                 (double)temp[5] / 65536 / 1000 ));
1394 
1395     temp_scale = FT_ABS( temp[3] );
1396 
1397     if ( temp_scale == 0 )
1398     {
1399       FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
1400       parser->root.error = FT_THROW( Invalid_File_Format );
1401       return;
1402     }
1403 
1404     /* atypical case */
1405     if ( temp_scale != 0x10000L )
1406     {
1407       /* set units per EM based on FontMatrix values */
1408       root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );
1409 
1410       temp[0] = FT_DivFix( temp[0], temp_scale );
1411       temp[1] = FT_DivFix( temp[1], temp_scale );
1412       temp[2] = FT_DivFix( temp[2], temp_scale );
1413       temp[4] = FT_DivFix( temp[4], temp_scale );
1414       temp[5] = FT_DivFix( temp[5], temp_scale );
1415       temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
1416     }
1417     matrix->xx = temp[0];
1418     matrix->yx = temp[1];
1419     matrix->xy = temp[2];
1420     matrix->yy = temp[3];
1421 
1422     if ( !FT_Matrix_Check( matrix ) )
1423     {
1424       FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
1425       parser->root.error = FT_THROW( Invalid_File_Format );
1426       return;
1427     }
1428 
1429     /* note that the offsets must be expressed in integer font units */
1430     offset->x = temp[4] >> 16;
1431     offset->y = temp[5] >> 16;
1432   }
1433 
1434 
1435   static void
parse_encoding(T1_Face face,T1_Loader loader)1436   parse_encoding( T1_Face    face,
1437                   T1_Loader  loader )
1438   {
1439     T1_Parser  parser = &loader->parser;
1440     FT_Byte*   cur;
1441     FT_Byte*   limit  = parser->root.limit;
1442 
1443     PSAux_Service  psaux = (PSAux_Service)face->psaux;
1444 
1445 
1446     T1_Skip_Spaces( parser );
1447     cur = parser->root.cursor;
1448     if ( cur >= limit )
1449     {
1450       FT_ERROR(( "parse_encoding: out of bounds\n" ));
1451       parser->root.error = FT_THROW( Invalid_File_Format );
1452       return;
1453     }
1454 
1455     /* if we have a number or `[', the encoding is an array, */
1456     /* and we must load it now                               */
1457     if ( ft_isdigit( *cur ) || *cur == '[' )
1458     {
1459       T1_Encoding  encode          = &face->type1.encoding;
1460       FT_Int       count, array_size, n;
1461       PS_Table     char_table      = &loader->encoding_table;
1462       FT_Memory    memory          = parser->root.memory;
1463       FT_Error     error;
1464       FT_Bool      only_immediates = 0;
1465 
1466 
1467       /* read the number of entries in the encoding; should be 256 */
1468       if ( *cur == '[' )
1469       {
1470         count           = 256;
1471         only_immediates = 1;
1472         parser->root.cursor++;
1473       }
1474       else
1475         count = (FT_Int)T1_ToInt( parser );
1476 
1477       array_size = count;
1478       if ( count > 256 )
1479       {
1480         FT_TRACE2(( "parse_encoding:"
1481                     " only using first 256 encoding array entries\n" ));
1482         array_size = 256;
1483       }
1484 
1485       T1_Skip_Spaces( parser );
1486       if ( parser->root.cursor >= limit )
1487         return;
1488 
1489       /* PostScript happily allows overwriting of encoding arrays */
1490       if ( encode->char_index )
1491       {
1492         FT_FREE( encode->char_index );
1493         FT_FREE( encode->char_name );
1494         T1_Release_Table( char_table );
1495       }
1496 
1497       /* we use a T1_Table to store our charnames */
1498       loader->num_chars = encode->num_chars = array_size;
1499       if ( FT_NEW_ARRAY( encode->char_index, array_size )     ||
1500            FT_NEW_ARRAY( encode->char_name,  array_size )     ||
1501            FT_SET_ERROR( psaux->ps_table_funcs->init(
1502                            char_table, array_size, memory ) ) )
1503       {
1504         parser->root.error = error;
1505         return;
1506       }
1507 
1508       /* We need to `zero' out encoding_table.elements */
1509       for ( n = 0; n < array_size; n++ )
1510         (void)T1_Add_Table( char_table, n, ".notdef", 8 );
1511 
1512       /* Now we need to read records of the form                */
1513       /*                                                        */
1514       /*   ... charcode /charname ...                           */
1515       /*                                                        */
1516       /* for each entry in our table.                           */
1517       /*                                                        */
1518       /* We simply look for a number followed by an immediate   */
1519       /* name.  Note that this ignores correctly the sequence   */
1520       /* that is often seen in type1 fonts:                     */
1521       /*                                                        */
1522       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
1523       /*                                                        */
1524       /* used to clean the encoding array before anything else. */
1525       /*                                                        */
1526       /* Alternatively, if the array is directly given as       */
1527       /*                                                        */
1528       /*   /Encoding [ ... ]                                    */
1529       /*                                                        */
1530       /* we only read immediates.                               */
1531 
1532       n = 0;
1533       T1_Skip_Spaces( parser );
1534 
1535       while ( parser->root.cursor < limit )
1536       {
1537         cur = parser->root.cursor;
1538 
1539         /* we stop when we encounter a `def' or `]' */
1540         if ( *cur == 'd' && cur + 3 < limit )
1541         {
1542           if ( cur[1] == 'e'         &&
1543                cur[2] == 'f'         &&
1544                IS_PS_DELIM( cur[3] ) )
1545           {
1546             FT_TRACE6(( "encoding end\n" ));
1547             cur += 3;
1548             break;
1549           }
1550         }
1551         if ( *cur == ']' )
1552         {
1553           FT_TRACE6(( "encoding end\n" ));
1554           cur++;
1555           break;
1556         }
1557 
1558         /* check whether we've found an entry */
1559         if ( ft_isdigit( *cur ) || only_immediates )
1560         {
1561           FT_Int  charcode;
1562 
1563 
1564           if ( only_immediates )
1565             charcode = n;
1566           else
1567           {
1568             charcode = (FT_Int)T1_ToInt( parser );
1569             T1_Skip_Spaces( parser );
1570 
1571             /* protect against invalid charcode */
1572             if ( cur == parser->root.cursor )
1573             {
1574               parser->root.error = FT_THROW( Unknown_File_Format );
1575               return;
1576             }
1577           }
1578 
1579           cur = parser->root.cursor;
1580 
1581           if ( cur + 2 < limit && *cur == '/' && n < count )
1582           {
1583             FT_UInt  len;
1584 
1585 
1586             cur++;
1587 
1588             parser->root.cursor = cur;
1589             T1_Skip_PS_Token( parser );
1590             if ( parser->root.cursor >= limit )
1591               return;
1592             if ( parser->root.error )
1593               return;
1594 
1595             len = (FT_UInt)( parser->root.cursor - cur );
1596 
1597             if ( n < array_size )
1598             {
1599               parser->root.error = T1_Add_Table( char_table, charcode,
1600                                                  cur, len + 1 );
1601               if ( parser->root.error )
1602                 return;
1603               char_table->elements[charcode][len] = '\0';
1604             }
1605 
1606             n++;
1607           }
1608           else if ( only_immediates )
1609           {
1610             /* Since the current position is not updated for           */
1611             /* immediates-only mode we would get an infinite loop if   */
1612             /* we don't do anything here.                              */
1613             /*                                                         */
1614             /* This encoding array is not valid according to the type1 */
1615             /* specification (it might be an encoding for a CID type1  */
1616             /* font, however), so we conclude that this font is NOT a  */
1617             /* type1 font.                                             */
1618             parser->root.error = FT_THROW( Unknown_File_Format );
1619             return;
1620           }
1621         }
1622         else
1623         {
1624           T1_Skip_PS_Token( parser );
1625           if ( parser->root.error )
1626             return;
1627         }
1628 
1629         T1_Skip_Spaces( parser );
1630       }
1631 
1632 #ifdef FT_DEBUG_LEVEL_TRACE
1633       FT_TRACE4(( " [" ));
1634 
1635       /* XXX show encoding vector */
1636       FT_TRACE4(( "..." ));
1637 
1638       FT_TRACE4(( "]\n" ));
1639 #endif
1640 
1641       face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
1642       parser->root.cursor       = cur;
1643     }
1644 
1645     /* Otherwise, we should have either `StandardEncoding', */
1646     /* `ExpertEncoding', or `ISOLatin1Encoding'             */
1647     else
1648     {
1649       if ( cur + 17 < limit                                            &&
1650            ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
1651       {
1652         face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
1653         FT_TRACE4(( " StandardEncoding\n" ));
1654       }
1655 
1656       else if ( cur + 15 < limit                                          &&
1657                 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
1658       {
1659         face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
1660         FT_TRACE4(( " ExpertEncoding\n" ));
1661       }
1662 
1663       else if ( cur + 18 < limit                                             &&
1664                 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
1665       {
1666         face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
1667         FT_TRACE4(( " ISOLatin1Encoding\n" ));
1668       }
1669 
1670       else
1671       {
1672         parser->root.error = FT_ERR( Ignore );
1673         FT_TRACE4(( "<unknown>\n" ));
1674       }
1675     }
1676   }
1677 
1678 
1679   static void
parse_subrs(T1_Face face,T1_Loader loader)1680   parse_subrs( T1_Face    face,
1681                T1_Loader  loader )
1682   {
1683     T1_Parser  parser = &loader->parser;
1684     PS_Table   table  = &loader->subrs;
1685     FT_Memory  memory = parser->root.memory;
1686     FT_Error   error;
1687     FT_Int     num_subrs;
1688     FT_UInt    count;
1689 
1690     PSAux_Service  psaux = (PSAux_Service)face->psaux;
1691 
1692 
1693     T1_Skip_Spaces( parser );
1694 
1695     /* test for empty array */
1696     if ( parser->root.cursor < parser->root.limit &&
1697          *parser->root.cursor == '['              )
1698     {
1699       T1_Skip_PS_Token( parser );
1700       T1_Skip_Spaces  ( parser );
1701       if ( parser->root.cursor >= parser->root.limit ||
1702            *parser->root.cursor != ']'               )
1703         parser->root.error = FT_THROW( Invalid_File_Format );
1704       return;
1705     }
1706 
1707     num_subrs = (FT_Int)T1_ToInt( parser );
1708     if ( num_subrs < 0 )
1709     {
1710       parser->root.error = FT_THROW( Invalid_File_Format );
1711       return;
1712     }
1713 
1714     /* we certainly need more than 8 bytes per subroutine */
1715     if ( parser->root.limit >= parser->root.cursor                     &&
1716          num_subrs > ( parser->root.limit - parser->root.cursor ) >> 3 )
1717     {
1718       /*
1719        * There are two possibilities.  Either the font contains an invalid
1720        * value for `num_subrs', or we have a subsetted font where the
1721        * subroutine indices are not adjusted, e.g.
1722        *
1723        *   /Subrs 812 array
1724        *     dup 0 { ... } NP
1725        *     dup 51 { ... } NP
1726        *     dup 681 { ... } NP
1727        *   ND
1728        *
1729        * In both cases, we use a number hash that maps from subr indices to
1730        * actual array elements.
1731        */
1732 
1733       FT_TRACE0(( "parse_subrs: adjusting number of subroutines"
1734                   " (from %d to %d)\n",
1735                   num_subrs,
1736                   ( parser->root.limit - parser->root.cursor ) >> 3 ));
1737       num_subrs = ( parser->root.limit - parser->root.cursor ) >> 3;
1738 
1739       if ( !loader->subrs_hash )
1740       {
1741         if ( FT_NEW( loader->subrs_hash ) )
1742           goto Fail;
1743 
1744         error = ft_hash_num_init( loader->subrs_hash, memory );
1745         if ( error )
1746           goto Fail;
1747       }
1748     }
1749 
1750     /* position the parser right before the `dup' of the first subr */
1751     T1_Skip_PS_Token( parser );         /* `array' */
1752     if ( parser->root.error )
1753       return;
1754     T1_Skip_Spaces( parser );
1755 
1756     /* initialize subrs array -- with synthetic fonts it is possible */
1757     /* we get here twice                                             */
1758     if ( !loader->num_subrs )
1759     {
1760       error = psaux->ps_table_funcs->init( table, num_subrs, memory );
1761       if ( error )
1762         goto Fail;
1763     }
1764 
1765     /* the format is simple:   */
1766     /*                         */
1767     /*   `index' + binary data */
1768     /*                         */
1769     for ( count = 0; ; count++ )
1770     {
1771       FT_Long   idx;
1772       FT_ULong  size;
1773       FT_Byte*  base;
1774 
1775 
1776       /* If we are out of data, or if the next token isn't `dup', */
1777       /* we are done.                                             */
1778       if ( parser->root.cursor + 4 >= parser->root.limit          ||
1779           ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
1780         break;
1781 
1782       T1_Skip_PS_Token( parser );       /* `dup' */
1783 
1784       idx = T1_ToInt( parser );
1785 
1786       if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) )
1787         return;
1788 
1789       /* The binary string is followed by one token, e.g. `NP' */
1790       /* (bound to `noaccess put') or by two separate tokens:  */
1791       /* `noaccess' & `put'.  We position the parser right     */
1792       /* before the next `dup', if any.                        */
1793       T1_Skip_PS_Token( parser );   /* `NP' or `|' or `noaccess' */
1794       if ( parser->root.error )
1795         return;
1796       T1_Skip_Spaces  ( parser );
1797 
1798       if ( parser->root.cursor + 4 < parser->root.limit            &&
1799            ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
1800       {
1801         T1_Skip_PS_Token( parser ); /* skip `put' */
1802         T1_Skip_Spaces  ( parser );
1803       }
1804 
1805       /* if we use a hash, the subrs index is the key, and a running */
1806       /* counter specified for `T1_Add_Table' acts as the value      */
1807       if ( loader->subrs_hash )
1808       {
1809         ft_hash_num_insert( idx, count, loader->subrs_hash, memory );
1810         idx = count;
1811       }
1812 
1813       /* with synthetic fonts it is possible we get here twice */
1814       if ( loader->num_subrs )
1815         continue;
1816 
1817       /* some fonts use a value of -1 for lenIV to indicate that */
1818       /* the charstrings are unencoded                           */
1819       /*                                                         */
1820       /* thanks to Tom Kacvinsky for pointing this out           */
1821       /*                                                         */
1822       if ( face->type1.private_dict.lenIV >= 0 )
1823       {
1824         FT_Byte*  temp = NULL;
1825 
1826 
1827         /* some fonts define empty subr records -- this is not totally */
1828         /* compliant to the specification (which says they should at   */
1829         /* least contain a `return'), but we support them anyway       */
1830         if ( size < (FT_ULong)face->type1.private_dict.lenIV )
1831         {
1832           error = FT_THROW( Invalid_File_Format );
1833           goto Fail;
1834         }
1835 
1836         /* t1_decrypt() shouldn't write to base -- make temporary copy */
1837         if ( FT_ALLOC( temp, size ) )
1838           goto Fail;
1839         FT_MEM_COPY( temp, base, size );
1840         psaux->t1_decrypt( temp, size, 4330 );
1841         size -= (FT_ULong)face->type1.private_dict.lenIV;
1842         error = T1_Add_Table( table, (FT_Int)idx,
1843                               temp + face->type1.private_dict.lenIV, size );
1844         FT_FREE( temp );
1845       }
1846       else
1847         error = T1_Add_Table( table, (FT_Int)idx, base, size );
1848       if ( error )
1849         goto Fail;
1850     }
1851 
1852     if ( !loader->num_subrs )
1853       loader->num_subrs = num_subrs;
1854 
1855 #ifdef FT_DEBUG_LEVEL_TRACE
1856       FT_TRACE4(( " <" ));
1857 
1858       /* XXX show subrs? */
1859       FT_TRACE4(( "%d elements", num_subrs ));
1860 
1861       FT_TRACE4(( ">\n" ));
1862 #endif
1863 
1864     return;
1865 
1866   Fail:
1867     parser->root.error = error;
1868   }
1869 
1870 
1871 #define TABLE_EXTEND  5
1872 
1873 
1874   static void
parse_charstrings(T1_Face face,T1_Loader loader)1875   parse_charstrings( T1_Face    face,
1876                      T1_Loader  loader )
1877   {
1878     T1_Parser      parser       = &loader->parser;
1879     PS_Table       code_table   = &loader->charstrings;
1880     PS_Table       name_table   = &loader->glyph_names;
1881     PS_Table       swap_table   = &loader->swap_table;
1882     FT_Memory      memory       = parser->root.memory;
1883     FT_Error       error;
1884 
1885     PSAux_Service  psaux        = (PSAux_Service)face->psaux;
1886 
1887     FT_Byte*       cur          = parser->root.cursor;
1888     FT_Byte*       limit        = parser->root.limit;
1889     FT_Int         n, num_glyphs;
1890     FT_Int         notdef_index = 0;
1891     FT_Byte        notdef_found = 0;
1892 
1893 
1894     num_glyphs = (FT_Int)T1_ToInt( parser );
1895     if ( num_glyphs < 0 )
1896     {
1897       error = FT_THROW( Invalid_File_Format );
1898       goto Fail;
1899     }
1900 
1901     /* we certainly need more than 8 bytes per glyph */
1902     if ( num_glyphs > ( limit - cur ) >> 3 )
1903     {
1904       FT_TRACE0(( "parse_charstrings: adjusting number of glyphs"
1905                   " (from %d to %d)\n",
1906                   num_glyphs, ( limit - cur ) >> 3 ));
1907       num_glyphs = ( limit - cur ) >> 3;
1908     }
1909 
1910     /* some fonts like Optima-Oblique not only define the /CharStrings */
1911     /* array but access it also                                        */
1912     if ( num_glyphs == 0 || parser->root.error )
1913       return;
1914 
1915     /* initialize tables, leaving space for addition of .notdef, */
1916     /* if necessary, and a few other glyphs to handle buggy      */
1917     /* fonts which have more glyphs than specified.              */
1918 
1919     /* for some non-standard fonts like `Optima' which provides  */
1920     /* different outlines depending on the resolution it is      */
1921     /* possible to get here twice                                */
1922     if ( !loader->num_glyphs )
1923     {
1924       error = psaux->ps_table_funcs->init(
1925                 code_table, num_glyphs + 1 + TABLE_EXTEND, memory );
1926       if ( error )
1927         goto Fail;
1928 
1929       error = psaux->ps_table_funcs->init(
1930                 name_table, num_glyphs + 1 + TABLE_EXTEND, memory );
1931       if ( error )
1932         goto Fail;
1933 
1934       /* Initialize table for swapping index notdef_index and */
1935       /* index 0 names and codes (if necessary).              */
1936 
1937       error = psaux->ps_table_funcs->init( swap_table, 4, memory );
1938       if ( error )
1939         goto Fail;
1940     }
1941 
1942     n = 0;
1943 
1944     for (;;)
1945     {
1946       FT_ULong  size;
1947       FT_Byte*  base;
1948 
1949 
1950       /* the format is simple:        */
1951       /*   `/glyphname' + binary data */
1952 
1953       T1_Skip_Spaces( parser );
1954 
1955       cur = parser->root.cursor;
1956       if ( cur >= limit )
1957         break;
1958 
1959       /* we stop when we find a `def' or `end' keyword */
1960       if ( cur + 3 < limit && IS_PS_DELIM( cur[3] ) )
1961       {
1962         if ( cur[0] == 'd' &&
1963              cur[1] == 'e' &&
1964              cur[2] == 'f' )
1965         {
1966           /* There are fonts which have this: */
1967           /*                                  */
1968           /*   /CharStrings 118 dict def      */
1969           /*   Private begin                  */
1970           /*   CharStrings begin              */
1971           /*   ...                            */
1972           /*                                  */
1973           /* To catch this we ignore `def' if */
1974           /* no charstring has actually been  */
1975           /* seen.                            */
1976           if ( n )
1977             break;
1978         }
1979 
1980         if ( cur[0] == 'e' &&
1981              cur[1] == 'n' &&
1982              cur[2] == 'd' )
1983           break;
1984       }
1985 
1986       T1_Skip_PS_Token( parser );
1987       if ( parser->root.cursor >= limit )
1988       {
1989         error = FT_THROW( Invalid_File_Format );
1990         goto Fail;
1991       }
1992       if ( parser->root.error )
1993         return;
1994 
1995       if ( *cur == '/' )
1996       {
1997         FT_UInt  len;
1998 
1999 
2000         if ( cur + 2 >= limit )
2001         {
2002           error = FT_THROW( Invalid_File_Format );
2003           goto Fail;
2004         }
2005 
2006         cur++;                              /* skip `/' */
2007         len = (FT_UInt)( parser->root.cursor - cur );
2008 
2009         if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) )
2010           return;
2011 
2012         /* for some non-standard fonts like `Optima' which provides */
2013         /* different outlines depending on the resolution it is     */
2014         /* possible to get here twice                               */
2015         if ( loader->num_glyphs )
2016           continue;
2017 
2018         error = T1_Add_Table( name_table, n, cur, len + 1 );
2019         if ( error )
2020           goto Fail;
2021 
2022         /* add a trailing zero to the name table */
2023         name_table->elements[n][len] = '\0';
2024 
2025         /* record index of /.notdef */
2026         if ( *cur == '.'                                              &&
2027              ft_strcmp( ".notdef",
2028                         (const char*)(name_table->elements[n]) ) == 0 )
2029         {
2030           notdef_index = n;
2031           notdef_found = 1;
2032         }
2033 
2034         if ( face->type1.private_dict.lenIV >= 0 &&
2035              n < num_glyphs + TABLE_EXTEND       )
2036         {
2037           FT_Byte*  temp = NULL;
2038 
2039 
2040           if ( size <= (FT_ULong)face->type1.private_dict.lenIV )
2041           {
2042             error = FT_THROW( Invalid_File_Format );
2043             goto Fail;
2044           }
2045 
2046           /* t1_decrypt() shouldn't write to base -- make temporary copy */
2047           if ( FT_ALLOC( temp, size ) )
2048             goto Fail;
2049           FT_MEM_COPY( temp, base, size );
2050           psaux->t1_decrypt( temp, size, 4330 );
2051           size -= (FT_ULong)face->type1.private_dict.lenIV;
2052           error = T1_Add_Table( code_table, n,
2053                                 temp + face->type1.private_dict.lenIV, size );
2054           FT_FREE( temp );
2055         }
2056         else
2057           error = T1_Add_Table( code_table, n, base, size );
2058         if ( error )
2059           goto Fail;
2060 
2061         n++;
2062       }
2063     }
2064 
2065     if ( !n )
2066     {
2067       error = FT_THROW( Invalid_File_Format );
2068       goto Fail;
2069     }
2070 
2071     loader->num_glyphs = n;
2072 
2073     /* if /.notdef is found but does not occupy index 0, do our magic. */
2074     if ( notdef_found                                                 &&
2075          ft_strcmp( ".notdef", (const char*)name_table->elements[0] ) )
2076     {
2077       /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0  */
2078       /* name and code entries to swap_table.  Then place notdef_index   */
2079       /* name and code entries into swap_table.  Then swap name and code */
2080       /* entries at indices notdef_index and 0 using values stored in    */
2081       /* swap_table.                                                     */
2082 
2083       /* Index 0 name */
2084       error = T1_Add_Table( swap_table, 0,
2085                             name_table->elements[0],
2086                             name_table->lengths [0] );
2087       if ( error )
2088         goto Fail;
2089 
2090       /* Index 0 code */
2091       error = T1_Add_Table( swap_table, 1,
2092                             code_table->elements[0],
2093                             code_table->lengths [0] );
2094       if ( error )
2095         goto Fail;
2096 
2097       /* Index notdef_index name */
2098       error = T1_Add_Table( swap_table, 2,
2099                             name_table->elements[notdef_index],
2100                             name_table->lengths [notdef_index] );
2101       if ( error )
2102         goto Fail;
2103 
2104       /* Index notdef_index code */
2105       error = T1_Add_Table( swap_table, 3,
2106                             code_table->elements[notdef_index],
2107                             code_table->lengths [notdef_index] );
2108       if ( error )
2109         goto Fail;
2110 
2111       error = T1_Add_Table( name_table, notdef_index,
2112                             swap_table->elements[0],
2113                             swap_table->lengths [0] );
2114       if ( error )
2115         goto Fail;
2116 
2117       error = T1_Add_Table( code_table, notdef_index,
2118                             swap_table->elements[1],
2119                             swap_table->lengths [1] );
2120       if ( error )
2121         goto Fail;
2122 
2123       error = T1_Add_Table( name_table, 0,
2124                             swap_table->elements[2],
2125                             swap_table->lengths [2] );
2126       if ( error )
2127         goto Fail;
2128 
2129       error = T1_Add_Table( code_table, 0,
2130                             swap_table->elements[3],
2131                             swap_table->lengths [3] );
2132       if ( error )
2133         goto Fail;
2134 
2135     }
2136     else if ( !notdef_found )
2137     {
2138       /* notdef_index is already 0, or /.notdef is undefined in   */
2139       /* charstrings dictionary.  Worry about /.notdef undefined. */
2140       /* We take index 0 and add it to the end of the table(s)    */
2141       /* and add our own /.notdef glyph to index 0.               */
2142 
2143       /* 0 333 hsbw endchar */
2144       FT_Byte  notdef_glyph[] = { 0x8B, 0xF7, 0xE1, 0x0D, 0x0E };
2145 
2146 
2147       error = T1_Add_Table( swap_table, 0,
2148                             name_table->elements[0],
2149                             name_table->lengths [0] );
2150       if ( error )
2151         goto Fail;
2152 
2153       error = T1_Add_Table( swap_table, 1,
2154                             code_table->elements[0],
2155                             code_table->lengths [0] );
2156       if ( error )
2157         goto Fail;
2158 
2159       error = T1_Add_Table( name_table, 0, ".notdef", 8 );
2160       if ( error )
2161         goto Fail;
2162 
2163       error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );
2164 
2165       if ( error )
2166         goto Fail;
2167 
2168       error = T1_Add_Table( name_table, n,
2169                             swap_table->elements[0],
2170                             swap_table->lengths [0] );
2171       if ( error )
2172         goto Fail;
2173 
2174       error = T1_Add_Table( code_table, n,
2175                             swap_table->elements[1],
2176                             swap_table->lengths [1] );
2177       if ( error )
2178         goto Fail;
2179 
2180       /* we added a glyph. */
2181       loader->num_glyphs += 1;
2182     }
2183 
2184 #ifdef FT_DEBUG_LEVEL_TRACE
2185       FT_TRACE4(( " <" ));
2186 
2187       /* XXX show charstrings? */
2188       FT_TRACE4(( "%d elements", loader->num_glyphs ));
2189 
2190       FT_TRACE4(( ">\n" ));
2191 #endif
2192 
2193     return;
2194 
2195   Fail:
2196     parser->root.error = error;
2197   }
2198 
2199 
2200   /**************************************************************************
2201    *
2202    * Define the token field static variables.  This is a set of
2203    * T1_FieldRec variables.
2204    *
2205    */
2206 
2207 
2208   static
2209   const T1_FieldRec  t1_keywords[] =
2210   {
2211 
2212 #include "t1tokens.h"
2213 
2214     /* now add the special functions... */
2215     T1_FIELD_CALLBACK( "FontMatrix",           t1_parse_font_matrix,
2216                        T1_FIELD_DICT_FONTDICT )
2217     T1_FIELD_CALLBACK( "Encoding",             parse_encoding,
2218                        T1_FIELD_DICT_FONTDICT )
2219     T1_FIELD_CALLBACK( "Subrs",                parse_subrs,
2220                        T1_FIELD_DICT_PRIVATE )
2221     T1_FIELD_CALLBACK( "CharStrings",          parse_charstrings,
2222                        T1_FIELD_DICT_PRIVATE )
2223     T1_FIELD_CALLBACK( "Private",              parse_private,
2224                        T1_FIELD_DICT_FONTDICT )
2225 
2226 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
2227     T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions,
2228                        T1_FIELD_DICT_FONTDICT )
2229     T1_FIELD_CALLBACK( "BlendDesignMap",       parse_blend_design_map,
2230                        T1_FIELD_DICT_FONTDICT )
2231     T1_FIELD_CALLBACK( "BlendAxisTypes",       parse_blend_axis_types,
2232                        T1_FIELD_DICT_FONTDICT )
2233     T1_FIELD_CALLBACK( "WeightVector",         parse_weight_vector,
2234                        T1_FIELD_DICT_FONTDICT )
2235     T1_FIELD_CALLBACK( "BuildCharArray",       parse_buildchar,
2236                        T1_FIELD_DICT_PRIVATE )
2237 #endif
2238 
2239     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
2240   };
2241 
2242 
2243   static FT_Error
parse_dict(T1_Face face,T1_Loader loader,FT_Byte * base,FT_ULong size)2244   parse_dict( T1_Face    face,
2245               T1_Loader  loader,
2246               FT_Byte*   base,
2247               FT_ULong   size )
2248   {
2249     T1_Parser  parser = &loader->parser;
2250     FT_Byte   *limit, *start_binary = NULL;
2251     FT_Bool    have_integer = 0;
2252 
2253 
2254     parser->root.cursor = base;
2255     parser->root.limit  = base + size;
2256     parser->root.error  = FT_Err_Ok;
2257 
2258     limit = parser->root.limit;
2259 
2260     T1_Skip_Spaces( parser );
2261 
2262     while ( parser->root.cursor < limit )
2263     {
2264       FT_Byte*  cur;
2265 
2266 
2267       cur = parser->root.cursor;
2268 
2269       /* look for `eexec' */
2270       if ( IS_PS_TOKEN( cur, limit, "eexec" ) )
2271         break;
2272 
2273       /* look for `closefile' which ends the eexec section */
2274       else if ( IS_PS_TOKEN( cur, limit, "closefile" ) )
2275         break;
2276 
2277       /* in a synthetic font the base font starts after a           */
2278       /* `FontDictionary' token that is placed after a Private dict */
2279       else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) )
2280       {
2281         if ( loader->keywords_encountered & T1_PRIVATE )
2282           loader->keywords_encountered |=
2283             T1_FONTDIR_AFTER_PRIVATE;
2284         parser->root.cursor += 13;
2285       }
2286 
2287       /* check whether we have an integer */
2288       else if ( ft_isdigit( *cur ) )
2289       {
2290         start_binary = cur;
2291         T1_Skip_PS_Token( parser );
2292         if ( parser->root.error )
2293           goto Exit;
2294         have_integer = 1;
2295       }
2296 
2297       /* in valid Type 1 fonts we don't see `RD' or `-|' directly */
2298       /* since those tokens are handled by parse_subrs and        */
2299       /* parse_charstrings                                        */
2300       else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' &&
2301                 have_integer )
2302       {
2303         FT_ULong  s;
2304         FT_Byte*  b;
2305 
2306 
2307         parser->root.cursor = start_binary;
2308         if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) )
2309           return FT_THROW( Invalid_File_Format );
2310         have_integer = 0;
2311       }
2312 
2313       else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' &&
2314                 have_integer )
2315       {
2316         FT_ULong  s;
2317         FT_Byte*  b;
2318 
2319 
2320         parser->root.cursor = start_binary;
2321         if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) )
2322           return FT_THROW( Invalid_File_Format );
2323         have_integer = 0;
2324       }
2325 
2326       /* look for immediates */
2327       else if ( *cur == '/' && cur + 2 < limit )
2328       {
2329         FT_UInt  len;
2330 
2331 
2332         cur++;
2333 
2334         parser->root.cursor = cur;
2335         T1_Skip_PS_Token( parser );
2336         if ( parser->root.error )
2337           goto Exit;
2338 
2339         len = (FT_UInt)( parser->root.cursor - cur );
2340 
2341         if ( len > 0 && len < 22 && parser->root.cursor < limit )
2342         {
2343           /* now compare the immediate name to the keyword table */
2344           T1_Field  keyword = (T1_Field)t1_keywords;
2345 
2346 
2347           for (;;)
2348           {
2349             FT_Byte*  name;
2350 
2351 
2352             name = (FT_Byte*)keyword->ident;
2353             if ( !name )
2354               break;
2355 
2356             if ( cur[0] == name[0]                      &&
2357                  len == ft_strlen( (const char *)name ) &&
2358                  ft_memcmp( cur, name, len ) == 0       )
2359             {
2360               /* We found it -- run the parsing callback!     */
2361               /* We record every instance of every field      */
2362               /* (until we reach the base font of a           */
2363               /* synthetic font) to deal adequately with      */
2364               /* multiple master fonts; this is also          */
2365               /* necessary because later PostScript           */
2366               /* definitions override earlier ones.           */
2367 
2368               /* Once we encounter `FontDirectory' after      */
2369               /* `/Private', we know that this is a synthetic */
2370               /* font; except for `/CharStrings' we are not   */
2371               /* interested in anything that follows this     */
2372               /* `FontDirectory'.                             */
2373 
2374               /* MM fonts have more than one /Private token at */
2375               /* the top level; let's hope that all the junk   */
2376               /* that follows the first /Private token is not  */
2377               /* interesting to us.                            */
2378 
2379               /* According to Adobe Tech Note #5175 (CID-Keyed */
2380               /* Font Installation for ATM Software) a `begin' */
2381               /* must be followed by exactly one `end', and    */
2382               /* `begin' -- `end' pairs must be accurately     */
2383               /* paired.  We could use this to distinguish     */
2384               /* between the global Private and the Private    */
2385               /* dict that is a member of the Blend dict.      */
2386 
2387               const FT_UInt dict =
2388                 ( loader->keywords_encountered & T1_PRIVATE )
2389                     ? T1_FIELD_DICT_PRIVATE
2390                     : T1_FIELD_DICT_FONTDICT;
2391 
2392 
2393               if ( !( dict & keyword->dict ) )
2394               {
2395                 FT_TRACE1(( "parse_dict: found `%s' but ignoring it"
2396                             " since it is in the wrong dictionary\n",
2397                             keyword->ident ));
2398                 break;
2399               }
2400 
2401               if ( !( loader->keywords_encountered &
2402                       T1_FONTDIR_AFTER_PRIVATE     )                  ||
2403                    ft_strcmp( (const char*)name, "CharStrings" ) == 0 )
2404               {
2405                 parser->root.error = t1_load_keyword( face,
2406                                                       loader,
2407                                                       keyword );
2408                 if ( parser->root.error )
2409                 {
2410                   if ( FT_ERR_EQ( parser->root.error, Ignore ) )
2411                     parser->root.error = FT_Err_Ok;
2412                   else
2413                     return parser->root.error;
2414                 }
2415               }
2416               break;
2417             }
2418 
2419             keyword++;
2420           }
2421         }
2422 
2423         have_integer = 0;
2424       }
2425       else
2426       {
2427         T1_Skip_PS_Token( parser );
2428         if ( parser->root.error )
2429           goto Exit;
2430         have_integer = 0;
2431       }
2432 
2433       T1_Skip_Spaces( parser );
2434     }
2435 
2436   Exit:
2437     return parser->root.error;
2438   }
2439 
2440 
2441   static void
t1_init_loader(T1_Loader loader,T1_Face face)2442   t1_init_loader( T1_Loader  loader,
2443                   T1_Face    face )
2444   {
2445     FT_UNUSED( face );
2446 
2447     FT_ZERO( loader );
2448   }
2449 
2450 
2451   static void
t1_done_loader(T1_Loader loader)2452   t1_done_loader( T1_Loader  loader )
2453   {
2454     T1_Parser  parser = &loader->parser;
2455     FT_Memory  memory = parser->root.memory;
2456 
2457 
2458     /* finalize tables */
2459     T1_Release_Table( &loader->encoding_table );
2460     T1_Release_Table( &loader->charstrings );
2461     T1_Release_Table( &loader->glyph_names );
2462     T1_Release_Table( &loader->swap_table );
2463     T1_Release_Table( &loader->subrs );
2464 
2465     /* finalize hash */
2466     ft_hash_num_free( loader->subrs_hash, memory );
2467     FT_FREE( loader->subrs_hash );
2468 
2469     /* finalize parser */
2470     T1_Finalize_Parser( parser );
2471   }
2472 
2473 
2474   FT_LOCAL_DEF( FT_Error )
T1_Open_Face(T1_Face face)2475   T1_Open_Face( T1_Face  face )
2476   {
2477     T1_LoaderRec   loader;
2478     T1_Parser      parser;
2479     T1_Font        type1 = &face->type1;
2480     PS_Private     priv  = &type1->private_dict;
2481     FT_Error       error;
2482 
2483     PSAux_Service  psaux = (PSAux_Service)face->psaux;
2484 
2485 
2486     t1_init_loader( &loader, face );
2487 
2488     /* default values */
2489     face->ndv_idx          = -1;
2490     face->cdv_idx          = -1;
2491     face->len_buildchar    = 0;
2492 
2493     priv->blue_shift       = 7;
2494     priv->blue_fuzz        = 1;
2495     priv->lenIV            = 4;
2496     priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
2497     priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
2498 
2499     parser = &loader.parser;
2500     error  = T1_New_Parser( parser,
2501                             face->root.stream,
2502                             face->root.memory,
2503                             psaux );
2504     if ( error )
2505       goto Exit;
2506 
2507     FT_TRACE4(( " top dictionary:\n" ));
2508     error = parse_dict( face, &loader,
2509                         parser->base_dict, parser->base_len );
2510     if ( error )
2511       goto Exit;
2512 
2513     error = T1_Get_Private_Dict( parser, psaux );
2514     if ( error )
2515       goto Exit;
2516 
2517     FT_TRACE4(( " private dictionary:\n" ));
2518     error = parse_dict( face, &loader,
2519                         parser->private_dict, parser->private_len );
2520     if ( error )
2521       goto Exit;
2522 
2523     /* ensure even-ness of `num_blue_values' */
2524     priv->num_blue_values &= ~1;
2525 
2526 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
2527 
2528     /* we don't support Multiple Master fonts with intermediate designs; */
2529     /* this implies that `num_designs' must be equal to `2^^num_axis'    */
2530     if ( face->blend                                                 &&
2531          face->blend->num_designs != ( 1U << face->blend->num_axis ) )
2532     {
2533       FT_ERROR(( "T1_Open_Face:"
2534                  " number-of-designs != 2 ^^ number-of-axes\n" ));
2535       T1_Done_Blend( face );
2536     }
2537 
2538     if ( face->blend                                                     &&
2539          face->blend->num_default_design_vector != 0                     &&
2540          face->blend->num_default_design_vector != face->blend->num_axis )
2541     {
2542       /* we don't use it currently so just warn, reset, and ignore */
2543       FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries "
2544                  "while there are %u axes.\n",
2545                  face->blend->num_default_design_vector,
2546                  face->blend->num_axis ));
2547 
2548       face->blend->num_default_design_vector = 0;
2549     }
2550 
2551     /* the following can happen for MM instances; we then treat the */
2552     /* font as a normal PS font                                     */
2553     if ( face->blend                                             &&
2554          ( !face->blend->num_designs || !face->blend->num_axis ) )
2555       T1_Done_Blend( face );
2556 
2557     /* another safety check */
2558     if ( face->blend )
2559     {
2560       FT_UInt  i;
2561 
2562 
2563       for ( i = 0; i < face->blend->num_axis; i++ )
2564         if ( !face->blend->design_map[i].num_points )
2565         {
2566           T1_Done_Blend( face );
2567           break;
2568         }
2569     }
2570 
2571     if ( face->blend )
2572     {
2573       if ( face->len_buildchar > 0 )
2574       {
2575         FT_Memory  memory = face->root.memory;
2576 
2577 
2578         if ( FT_NEW_ARRAY( face->buildchar, face->len_buildchar ) )
2579         {
2580           FT_ERROR(( "T1_Open_Face: cannot allocate BuildCharArray\n" ));
2581           face->len_buildchar = 0;
2582           goto Exit;
2583         }
2584       }
2585     }
2586     else
2587       face->len_buildchar = 0;
2588 
2589 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
2590 
2591     /* now, propagate the subrs, charstrings, and glyphnames tables */
2592     /* to the Type1 data                                            */
2593     type1->num_glyphs = loader.num_glyphs;
2594 
2595     if ( loader.subrs.init )
2596     {
2597       type1->num_subrs   = loader.num_subrs;
2598       type1->subrs_block = loader.subrs.block;
2599       type1->subrs       = loader.subrs.elements;
2600       type1->subrs_len   = loader.subrs.lengths;
2601       type1->subrs_hash  = loader.subrs_hash;
2602 
2603       /* prevent `t1_done_loader' from freeing the propagated data */
2604       loader.subrs.init = 0;
2605       loader.subrs_hash = NULL;
2606     }
2607 
2608     if ( !IS_INCREMENTAL )
2609       if ( !loader.charstrings.init )
2610       {
2611         FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face\n" ));
2612         error = FT_THROW( Invalid_File_Format );
2613       }
2614 
2615     loader.charstrings.init  = 0;
2616     type1->charstrings_block = loader.charstrings.block;
2617     type1->charstrings       = loader.charstrings.elements;
2618     type1->charstrings_len   = loader.charstrings.lengths;
2619 
2620     /* we copy the glyph names `block' and `elements' fields; */
2621     /* the `lengths' field must be released later             */
2622     type1->glyph_names_block    = loader.glyph_names.block;
2623     type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
2624     loader.glyph_names.block    = NULL;
2625     loader.glyph_names.elements = NULL;
2626 
2627     /* we must now build type1.encoding when we have a custom array */
2628     if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
2629     {
2630       FT_Int  charcode, idx, min_char, max_char;
2631 
2632 
2633       /* OK, we do the following: for each element in the encoding  */
2634       /* table, look up the index of the glyph having the same name */
2635       /* the index is then stored in type1.encoding.char_index, and */
2636       /* the name to type1.encoding.char_name                       */
2637 
2638       min_char = 0;
2639       max_char = 0;
2640 
2641       charcode = 0;
2642       for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
2643       {
2644         const FT_String*  char_name =
2645               (const FT_String*)loader.encoding_table.elements[charcode];
2646 
2647 
2648         type1->encoding.char_index[charcode] = 0;
2649         type1->encoding.char_name [charcode] = ".notdef";
2650 
2651         if ( char_name )
2652           for ( idx = 0; idx < type1->num_glyphs; idx++ )
2653           {
2654             const FT_String*  glyph_name = type1->glyph_names[idx];
2655 
2656 
2657             if ( ft_strcmp( char_name, glyph_name ) == 0 )
2658             {
2659               type1->encoding.char_index[charcode] = (FT_UShort)idx;
2660               type1->encoding.char_name [charcode] = glyph_name;
2661 
2662               /* Change min/max encoded char only if glyph name is */
2663               /* not /.notdef                                      */
2664               if ( ft_strcmp( ".notdef", glyph_name ) != 0 )
2665               {
2666                 if ( charcode < min_char )
2667                   min_char = charcode;
2668                 if ( charcode >= max_char )
2669                   max_char = charcode + 1;
2670               }
2671               break;
2672             }
2673           }
2674       }
2675 
2676       type1->encoding.code_first = min_char;
2677       type1->encoding.code_last  = max_char;
2678       type1->encoding.num_chars  = loader.num_chars;
2679     }
2680 
2681     /* some sanitizing to avoid overflows later on; */
2682     /* the upper limits are ad-hoc values           */
2683     if ( priv->blue_shift > 1000 || priv->blue_shift < 0 )
2684     {
2685       FT_TRACE2(( "T1_Open_Face:"
2686                   " setting unlikely BlueShift value %d to default (7)\n",
2687                   priv->blue_shift ));
2688       priv->blue_shift = 7;
2689     }
2690 
2691     if ( priv->blue_fuzz > 1000 || priv->blue_fuzz < 0 )
2692     {
2693       FT_TRACE2(( "T1_Open_Face:"
2694                   " setting unlikely BlueFuzz value %d to default (1)\n",
2695                   priv->blue_fuzz ));
2696       priv->blue_fuzz = 1;
2697     }
2698 
2699   Exit:
2700     t1_done_loader( &loader );
2701     return error;
2702   }
2703 
2704 
2705 /* END */
2706