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