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