source: trunk/poppler/freetype-2.1.10/src/type1/t1load.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

File size: 63.9 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  t1load.c                                                               */
4/*                                                                         */
5/*    Type 1 font loader (body).                                           */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2004, 2005 by                         */
8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9/*                                                                         */
10/*  This file is part of the FreeType project, and may only be used,       */
11/*  modified, and distributed under the terms of the FreeType project      */
12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13/*  this file you indicate that you have read the license and              */
14/*  understand and accept it fully.                                        */
15/*                                                                         */
16/***************************************************************************/
17
18
19  /*************************************************************************/
20  /*                                                                       */
21  /* This is the new and improved Type 1 data loader for FreeType 2.  The  */
22  /* old loader has several problems: it is slow, complex, difficult to    */
23  /* maintain, and contains incredible hacks to make it accept some        */
24  /* ill-formed Type 1 fonts without hiccup-ing.  Moreover, about 5% of    */
25  /* the Type 1 fonts on my machine still aren't loaded correctly by it.   */
26  /*                                                                       */
27  /* This version is much simpler, much faster and also easier to read and */
28  /* maintain by a great order of magnitude.  The idea behind it is to     */
29  /* _not_ try to read the Type 1 token stream with a state machine (i.e.  */
30  /* a Postscript-like interpreter) but rather to perform simple pattern   */
31  /* matching.                                                             */
32  /*                                                                       */
33  /* Indeed, nearly all data definitions follow a simple pattern like      */
34  /*                                                                       */
35  /*  ... /Field <data> ...                                                */
36  /*                                                                       */
37  /* where <data> can be a number, a boolean, a string, or an array of     */
38  /* numbers.  There are a few exceptions, namely the encoding, font name, */
39  /* charstrings, and subrs; they are handled with a special pattern       */
40  /* matching routine.                                                     */
41  /*                                                                       */
42  /* All other common cases are handled very simply.  The matching rules   */
43  /* are defined in the file `t1tokens.h' through the use of several       */
44  /* macros calls PARSE_XXX.  This file is included twice here; the first  */
45  /* time to generate parsing callback functions, the second time to       */
46  /* generate a table of keywords (with pointers to the associated         */
47  /* callback functions).                                                  */
48  /*                                                                       */
49  /* The function `parse_dict' simply scans *linearly* a given dictionary  */
50  /* (either the top-level or private one) and calls the appropriate       */
51  /* callback when it encounters an immediate keyword.                     */
52  /*                                                                       */
53  /* This is by far the fastest way one can find to parse and read all     */
54  /* data.                                                                 */
55  /*                                                                       */
56  /* This led to tremendous code size reduction.  Note that later, the     */
57  /* glyph loader will also be _greatly_ simplified, and the automatic     */
58  /* hinter will replace the clumsy `t1hinter'.                            */
59  /*                                                                       */
60  /*************************************************************************/
61
62
63#include <ft2build.h>
64#include FT_INTERNAL_DEBUG_H
65#include FT_CONFIG_CONFIG_H
66#include FT_MULTIPLE_MASTERS_H
67#include FT_INTERNAL_TYPE1_TYPES_H
68
69#include "t1load.h"
70#include "t1errors.h"
71
72
73  /*************************************************************************/
74  /*                                                                       */
75  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
76  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
77  /* messages during execution.                                            */
78  /*                                                                       */
79#undef  FT_COMPONENT
80#define FT_COMPONENT  trace_t1load
81
82
83#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
84
85
86  /*************************************************************************/
87  /*************************************************************************/
88  /*****                                                               *****/
89  /*****                    MULTIPLE MASTERS SUPPORT                   *****/
90  /*****                                                               *****/
91  /*************************************************************************/
92  /*************************************************************************/
93
94  static FT_Error
95  t1_allocate_blend( T1_Face  face,
96                     FT_UInt  num_designs,
97                     FT_UInt  num_axis )
98  {
99    PS_Blend   blend;
100    FT_Memory  memory = face->root.memory;
101    FT_Error   error  = T1_Err_Ok;
102
103
104    blend = face->blend;
105    if ( !blend )
106    {
107      if ( FT_NEW( blend ) )
108        goto Exit;
109
110      face->blend = blend;
111    }
112
113    /* allocate design data if needed */
114    if ( num_designs > 0 )
115    {
116      if ( blend->num_designs == 0 )
117      {
118        FT_UInt  nn;
119
120
121        /* allocate the blend `private' and `font_info' dictionaries */
122        if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs     ) ||
123             FT_NEW_ARRAY( blend->privates[1], num_designs       ) ||
124             FT_NEW_ARRAY( blend->bboxes[1], num_designs         ) ||
125             FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) )
126          goto Exit;
127
128        blend->default_weight_vector = blend->weight_vector + num_designs;
129
130        blend->font_infos[0] = &face->type1.font_info;
131        blend->privates  [0] = &face->type1.private_dict;
132        blend->bboxes    [0] = &face->type1.font_bbox;
133
134        for ( nn = 2; nn <= num_designs; nn++ )
135        {
136          blend->privates[nn]   = blend->privates  [nn - 1] + 1;
137          blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
138          blend->bboxes[nn]     = blend->bboxes    [nn - 1] + 1;
139        }
140
141        blend->num_designs   = num_designs;
142      }
143      else if ( blend->num_designs != num_designs )
144        goto Fail;
145    }
146
147    /* allocate axis data if needed */
148    if ( num_axis > 0 )
149    {
150      if ( blend->num_axis != 0 && blend->num_axis != num_axis )
151        goto Fail;
152
153      blend->num_axis = num_axis;
154    }
155
156    /* allocate the blend design pos table if needed */
157    num_designs = blend->num_designs;
158    num_axis    = blend->num_axis;
159    if ( num_designs && num_axis && blend->design_pos[0] == 0 )
160    {
161      FT_UInt  n;
162
163
164      if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) )
165        goto Exit;
166
167      for ( n = 1; n < num_designs; n++ )
168        blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
169    }
170
171  Exit:
172    return error;
173
174  Fail:
175    error = T1_Err_Invalid_File_Format;
176    goto Exit;
177  }
178
179
180  FT_LOCAL_DEF( FT_Error )
181  T1_Get_Multi_Master( T1_Face           face,
182                       FT_Multi_Master*  master )
183  {
184    PS_Blend  blend = face->blend;
185    FT_UInt   n;
186    FT_Error  error;
187
188
189    error = T1_Err_Invalid_Argument;
190
191    if ( blend )
192    {
193      master->num_axis    = blend->num_axis;
194      master->num_designs = blend->num_designs;
195
196      for ( n = 0; n < blend->num_axis; n++ )
197      {
198        FT_MM_Axis*   axis = master->axis + n;
199        PS_DesignMap  map = blend->design_map + n;
200
201
202        axis->name    = blend->axis_names[n];
203        axis->minimum = map->design_points[0];
204        axis->maximum = map->design_points[map->num_points - 1];
205      }
206
207      error = T1_Err_Ok;
208    }
209
210    return error;
211  }
212
213
214#define FT_INT_TO_FIXED( a )  ( (a) << 16 )
215#define FT_FIXED_TO_INT( a )  ( FT_RoundFix( a ) >> 16 )
216
217
218  /*************************************************************************/
219  /*                                                                       */
220  /* Given a normalized (blend) coordinate, figure out the design          */
221  /* coordinate appropriate for that value.                                */
222  /*                                                                       */
223  FT_LOCAL_DEF( FT_Fixed )
224  mm_axis_unmap( PS_DesignMap  axismap,
225                 FT_Fixed      ncv )
226  {
227    int  j;
228
229
230    if ( ncv <= axismap->blend_points[0] )
231      return axismap->design_points[0];
232
233    for ( j = 1; j < axismap->num_points; ++j )
234    {
235      if ( ncv <= axismap->blend_points[j] )
236      {
237        FT_Fixed  t = FT_MulDiv( ncv - axismap->blend_points[j - 1],
238                                 0x10000L,
239                                 axismap->blend_points[j] -
240                                   axismap->blend_points[j - 1] );
241
242
243        return axismap->design_points[j - 1] +
244                 FT_MulDiv( t,
245                            axismap->design_points[j] - 
246                              axismap->design_points[j - 1],
247                            1L );
248      }
249    }
250
251    return axismap->design_points[axismap->num_points - 1];
252  }
253
254
255  /*************************************************************************/
256  /*                                                                       */
257  /* Given a vector of weights, one for each design, figure out the        */
258  /* normalized axis coordinates which gave rise to those weights.         */
259  /*                                                                       */
260  FT_LOCAL_DEF( void )
261  mm_weights_unmap( FT_Fixed*  weights,
262                    FT_Fixed*  axiscoords,
263                    FT_UInt    axis_count )
264  {
265    FT_ASSERT( axis_count <= T1_MAX_MM_AXIS );
266
267    if ( axis_count == 1 )
268      axiscoords[0] = weights[1];
269
270    else if ( axis_count == 2 )
271    {
272      axiscoords[0] = weights[3] + weights[1];
273      axiscoords[1] = weights[3] + weights[2];
274    }
275
276    else if ( axis_count == 3 )
277    {
278      axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1];
279      axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2];
280      axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4];
281    }
282
283    else
284    {
285      axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] +
286                        weights[7] + weights[5] + weights[3] + weights[1];
287      axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] +
288                        weights[7] + weights[6] + weights[3] + weights[2];
289      axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] +
290                        weights[7] + weights[6] + weights[5] + weights[4];
291      axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] +
292                        weights[11] + weights[10] + weights[9] + weights[8];
293    }
294  }
295
296
297  /*************************************************************************/
298  /*                                                                       */
299  /* Just a wrapper around T1_Get_Multi_Master to support the different    */
300  /*  arguments needed by the GX var distortable fonts.                    */
301  /*                                                                       */
302  FT_LOCAL_DEF( FT_Error )
303  T1_Get_MM_Var( T1_Face      face,
304                 FT_MM_Var*  *master )
305  {
306    FT_Memory        memory = face->root.memory;
307    FT_MM_Var       *mmvar;
308    FT_Multi_Master  mmaster;
309    FT_Error         error;
310    FT_UInt          i;
311    FT_Fixed         axiscoords[T1_MAX_MM_AXIS];
312    PS_Blend         blend = face->blend;
313
314
315    error = T1_Get_Multi_Master( face, &mmaster );
316    if ( error )
317      goto Exit;
318    if ( FT_ALLOC( mmvar,
319                   sizeof ( FT_MM_Var ) +
320                     mmaster.num_axis * sizeof ( FT_Var_Axis ) ) )
321      goto Exit;
322
323    mmvar->num_axis        = mmaster.num_axis;
324    mmvar->num_designs     = mmaster.num_designs;
325    mmvar->num_namedstyles = (FT_UInt)-1;                /* Does not apply */
326    mmvar->axis            = (FT_Var_Axis*)&mmvar[1];
327                                      /* Point to axes after MM_Var struct */
328    mmvar->namedstyle      = NULL;
329
330    for ( i = 0 ; i < mmaster.num_axis; ++i )
331    {
332      mmvar->axis[i].name    = mmaster.axis[i].name;
333      mmvar->axis[i].minimum = FT_INT_TO_FIXED( mmaster.axis[i].minimum);
334      mmvar->axis[i].maximum = FT_INT_TO_FIXED( mmaster.axis[i].maximum);
335      mmvar->axis[i].def     = ( mmvar->axis[i].minimum +
336                                   mmvar->axis[i].maximum ) / 2;
337                            /* Does not apply.  But this value is in range */
338      mmvar->axis[i].strid   = 0xFFFFFFFFLU;   /* Does not apply */
339      mmvar->axis[i].tag     = 0xFFFFFFFFLU;   /* Does not apply */
340
341      if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 )
342        mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' );
343      else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 )
344        mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' );
345      else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 )
346        mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' );
347    }
348
349    if ( blend->num_designs == 1U << blend->num_axis )
350    {
351      mm_weights_unmap( blend->default_weight_vector,
352                        axiscoords,
353                        blend->num_axis );
354
355      for ( i = 0; i < mmaster.num_axis; ++i )
356        mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i],
357                                            axiscoords[i] );
358    }
359
360    *master = mmvar;
361
362  Exit:
363    return error;
364  }
365
366
367  FT_LOCAL_DEF( FT_Error )
368  T1_Set_MM_Blend( T1_Face    face,
369                   FT_UInt    num_coords,
370                   FT_Fixed*  coords )
371  {
372    PS_Blend  blend = face->blend;
373    FT_Error  error;
374    FT_UInt   n, m;
375
376
377    error = T1_Err_Invalid_Argument;
378
379    if ( blend && blend->num_axis == num_coords )
380    {
381      /* recompute the weight vector from the blend coordinates */
382      error = T1_Err_Ok;
383
384      for ( n = 0; n < blend->num_designs; n++ )
385      {
386        FT_Fixed  result = 0x10000L;  /* 1.0 fixed */
387
388
389        for ( m = 0; m < blend->num_axis; m++ )
390        {
391          FT_Fixed  factor;
392
393
394          /* get current blend axis position */
395          factor = coords[m];
396          if ( factor < 0 )        factor = 0;
397          if ( factor > 0x10000L ) factor = 0x10000L;
398
399          if ( ( n & ( 1 << m ) ) == 0 )
400            factor = 0x10000L - factor;
401
402          result = FT_MulFix( result, factor );
403        }
404        blend->weight_vector[n] = result;
405      }
406
407      error = T1_Err_Ok;
408    }
409
410    return error;
411  }
412
413
414  FT_LOCAL_DEF( FT_Error )
415  T1_Set_MM_Design( T1_Face   face,
416                    FT_UInt   num_coords,
417                    FT_Long*  coords )
418  {
419    PS_Blend  blend = face->blend;
420    FT_Error  error;
421    FT_UInt   n, p;
422
423
424    error = T1_Err_Invalid_Argument;
425    if ( blend && blend->num_axis == num_coords )
426    {
427      /* compute the blend coordinates through the blend design map */
428      FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
429
430
431      for ( n = 0; n < blend->num_axis; n++ )
432      {
433        FT_Long       design  = coords[n];
434        FT_Fixed      the_blend;
435        PS_DesignMap  map     = blend->design_map + n;
436        FT_Long*      designs = map->design_points;
437        FT_Fixed*     blends  = map->blend_points;
438        FT_Int        before  = -1, after = -1;
439
440
441        for ( p = 0; p < (FT_UInt)map->num_points; p++ )
442        {
443          FT_Long  p_design = designs[p];
444
445
446          /* exact match? */
447          if ( design == p_design )
448          {
449            the_blend = blends[p];
450            goto Found;
451          }
452
453          if ( design < p_design )
454          {
455            after = p;
456            break;
457          }
458
459          before = p;
460        }
461
462        /* now interpolate if necessary */
463        if ( before < 0 )
464          the_blend = blends[0];
465
466        else if ( after < 0 )
467          the_blend = blends[map->num_points - 1];
468
469        else
470          the_blend = FT_MulDiv( design         - designs[before],
471                                 blends [after] - blends [before],
472                                 designs[after] - designs[before] );
473
474      Found:
475        final_blends[n] = the_blend;
476      }
477
478      error = T1_Set_MM_Blend( face, num_coords, final_blends );
479    }
480
481    return error;
482  }
483
484
485  /*************************************************************************/
486  /*                                                                       */
487  /* Just a wrapper around T1_Set_MM_Design to support the different       */
488  /* arguments needed by the GX var distortable fonts.                     */
489  /*                                                                       */
490  FT_LOCAL_DEF( FT_Error )
491  T1_Set_Var_Design( T1_Face    face,
492                     FT_UInt    num_coords,
493                     FT_Fixed*  coords )
494  {
495     FT_Long   lcoords[4];          /* maximum axis count is 4 */
496     FT_UInt   i;
497     FT_Error  error;
498
499
500     error = T1_Err_Invalid_Argument;
501     if ( num_coords <= 4 && num_coords > 0 )
502     {
503       for ( i = 0; i < num_coords; ++i )
504         lcoords[i] = FT_FIXED_TO_INT( coords[i] );
505       error = T1_Set_MM_Design( face, num_coords, lcoords );
506     }
507
508     return error;
509  }
510
511
512  FT_LOCAL_DEF( void )
513  T1_Done_Blend( T1_Face  face )
514  {
515    FT_Memory  memory = face->root.memory;
516    PS_Blend   blend  = face->blend;
517
518
519    if ( blend )
520    {
521      FT_UInt  num_designs = blend->num_designs;
522      FT_UInt  num_axis    = blend->num_axis;
523      FT_UInt  n;
524
525
526      /* release design pos table */
527      FT_FREE( blend->design_pos[0] );
528      for ( n = 1; n < num_designs; n++ )
529        blend->design_pos[n] = 0;
530
531      /* release blend `private' and `font info' dictionaries */
532      FT_FREE( blend->privates[1] );
533      FT_FREE( blend->font_infos[1] );
534      FT_FREE( blend->bboxes[1] );
535
536      for ( n = 0; n < num_designs; n++ )
537      {
538        blend->privates  [n] = 0;
539        blend->font_infos[n] = 0;
540        blend->bboxes    [n] = 0;
541      }
542
543      /* release weight vectors */
544      FT_FREE( blend->weight_vector );
545      blend->default_weight_vector = 0;
546
547      /* release axis names */
548      for ( n = 0; n < num_axis; n++ )
549        FT_FREE( blend->axis_names[n] );
550
551      /* release design map */
552      for ( n = 0; n < num_axis; n++ )
553      {
554        PS_DesignMap  dmap = blend->design_map + n;
555
556
557        FT_FREE( dmap->design_points );
558        dmap->num_points = 0;
559      }
560
561      FT_FREE( face->blend );
562    }
563  }
564
565
566  static void
567  parse_blend_axis_types( T1_Face    face,
568                          T1_Loader  loader )
569  {
570    T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
571    FT_Int       n, num_axis;
572    FT_Error     error = T1_Err_Ok;
573    PS_Blend     blend;
574    FT_Memory    memory;
575
576
577    /* take an array of objects */
578    T1_ToTokenArray( &loader->parser, axis_tokens,
579                     T1_MAX_MM_AXIS, &num_axis );
580    if ( num_axis < 0 )
581    {
582      error = T1_Err_Ignore;
583      goto Exit;
584    }
585    if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
586    {
587      FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
588                 num_axis ));
589      error = T1_Err_Invalid_File_Format;
590      goto Exit;
591    }
592
593    /* allocate blend if necessary */
594    error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
595    if ( error )
596      goto Exit;
597
598    blend  = face->blend;
599    memory = face->root.memory;
600
601    /* each token is an immediate containing the name of the axis */
602    for ( n = 0; n < num_axis; n++ )
603    {
604      T1_Token    token = axis_tokens + n;
605      FT_Byte*    name;
606      FT_PtrDist  len;
607
608
609      /* skip first slash, if any */
610      if ( token->start[0] == '/' )
611        token->start++;
612
613      len = token->limit - token->start;
614      if ( len == 0 )
615      {
616        error = T1_Err_Invalid_File_Format;
617        goto Exit;
618      }
619
620      if ( FT_ALLOC( blend->axis_names[n], len + 1 ) )
621        goto Exit;
622
623      name = (FT_Byte*)blend->axis_names[n];
624      FT_MEM_COPY( name, token->start, len );
625      name[len] = 0;
626    }
627
628  Exit:
629    loader->parser.root.error = error;
630  }
631
632
633  static void
634  parse_blend_design_positions( T1_Face    face,
635                                T1_Loader  loader )
636  {
637    T1_TokenRec  design_tokens[T1_MAX_MM_DESIGNS];
638    FT_Int       num_designs;
639    FT_Int       num_axis;
640    T1_Parser    parser = &loader->parser;
641
642    FT_Error     error = T1_Err_Ok;
643    PS_Blend     blend;
644
645
646    /* get the array of design tokens -- compute number of designs */
647    T1_ToTokenArray( parser, design_tokens,
648                     T1_MAX_MM_DESIGNS, &num_designs );
649    if ( num_designs < 0 )
650    {
651      error = T1_Err_Ignore;
652      goto Exit;
653    }
654    if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
655    {
656      FT_ERROR(( "parse_blend_design_positions:" ));
657      FT_ERROR(( " incorrect number of designs: %d\n",
658                 num_designs ));
659      error = T1_Err_Invalid_File_Format;
660      goto Exit;
661    }
662
663    {
664      FT_Byte*  old_cursor = parser->root.cursor;
665      FT_Byte*  old_limit  = parser->root.limit;
666      FT_Int    n;
667
668
669      blend    = face->blend;
670      num_axis = 0;  /* make compiler happy */
671
672      for ( n = 0; n < num_designs; n++ )
673      {
674        T1_TokenRec  axis_tokens[T1_MAX_MM_DESIGNS];
675        T1_Token     token;
676        FT_Int       axis, n_axis;
677
678
679        /* read axis/coordinates tokens */
680        token = design_tokens + n;
681        parser->root.cursor = token->start;
682        parser->root.limit  = token->limit;
683        T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
684
685        if ( n == 0 )
686        {
687          num_axis = n_axis;
688          error = t1_allocate_blend( face, num_designs, num_axis );
689          if ( error )
690            goto Exit;
691          blend = face->blend;
692        }
693        else if ( n_axis != num_axis )
694        {
695          FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
696          error = T1_Err_Invalid_File_Format;
697          goto Exit;
698        }
699
700        /* now read each axis token into the design position */
701        for ( axis = 0; axis < n_axis; axis++ )
702        {
703          T1_Token  token2 = axis_tokens + axis;
704
705
706          parser->root.cursor = token2->start;
707          parser->root.limit  = token2->limit;
708          blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
709        }
710      }
711
712      loader->parser.root.cursor = old_cursor;
713      loader->parser.root.limit  = old_limit;
714    }
715
716  Exit:
717    loader->parser.root.error = error;
718  }
719
720
721  static void
722  parse_blend_design_map( T1_Face    face,
723                          T1_Loader  loader )
724  {
725    FT_Error     error  = T1_Err_Ok;
726    T1_Parser    parser = &loader->parser;
727    PS_Blend     blend;
728    T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
729    FT_Int       n, num_axis;
730    FT_Byte*     old_cursor;
731    FT_Byte*     old_limit;
732    FT_Memory    memory = face->root.memory;
733
734
735    T1_ToTokenArray( parser, axis_tokens, 
736                     T1_MAX_MM_AXIS, &num_axis );
737    if ( num_axis < 0 )
738    {
739      error = T1_Err_Ignore;
740      goto Exit;
741    }
742    if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
743    {
744      FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
745                 num_axis ));
746      error = T1_Err_Invalid_File_Format;
747      goto Exit;
748    }
749
750    old_cursor = parser->root.cursor;
751    old_limit  = parser->root.limit;
752
753    error = t1_allocate_blend( face, 0, num_axis );
754    if ( error )
755      goto Exit;
756    blend = face->blend;
757
758    /* now read each axis design map */
759    for ( n = 0; n < num_axis; n++ )
760    {
761      PS_DesignMap  map = blend->design_map + n;
762      T1_Token      axis_token;
763      T1_TokenRec   point_tokens[T1_MAX_MM_MAP_POINTS];
764      FT_Int        p, num_points;
765
766
767      axis_token = axis_tokens + n;
768
769      parser->root.cursor = axis_token->start;
770      parser->root.limit  = axis_token->limit;
771      T1_ToTokenArray( parser, point_tokens,
772                       T1_MAX_MM_MAP_POINTS, &num_points );
773
774      if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
775      {
776        FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
777        error = T1_Err_Invalid_File_Format;
778        goto Exit;
779      }
780
781      /* allocate design map data */
782      if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) )
783        goto Exit;
784      map->blend_points = map->design_points + num_points;
785      map->num_points   = (FT_Byte)num_points;
786
787      for ( p = 0; p < num_points; p++ )
788      {
789        T1_Token  point_token;
790
791
792        point_token = point_tokens + p;
793
794        /* don't include delimiting brackets */
795        parser->root.cursor = point_token->start + 1;
796        parser->root.limit  = point_token->limit - 1;
797
798        map->design_points[p] = T1_ToInt( parser );
799        map->blend_points [p] = T1_ToFixed( parser, 0 );
800      }
801    }
802
803    parser->root.cursor = old_cursor;
804    parser->root.limit  = old_limit;
805
806  Exit:
807    parser->root.error = error;
808  }
809
810
811  static void
812  parse_weight_vector( T1_Face    face,
813                       T1_Loader  loader )
814  {
815    T1_TokenRec  design_tokens[T1_MAX_MM_DESIGNS];
816    FT_Int       num_designs;
817    FT_Error     error  = T1_Err_Ok;
818    T1_Parser    parser = &loader->parser;
819    PS_Blend     blend  = face->blend;
820    T1_Token     token;
821    FT_Int       n;
822    FT_Byte*     old_cursor;
823    FT_Byte*     old_limit;
824
825
826    T1_ToTokenArray( parser, design_tokens,
827                     T1_MAX_MM_DESIGNS, &num_designs );
828    if ( num_designs < 0 )
829    {
830      error = T1_Err_Ignore;
831      goto Exit;
832    }
833    if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
834    {
835      FT_ERROR(( "parse_weight_vector:" ));
836      FT_ERROR(( " incorrect number of designs: %d\n",
837                 num_designs ));
838      error = T1_Err_Invalid_File_Format;
839      goto Exit;
840    }
841
842    if ( !blend || !blend->num_designs )
843    {
844      error = t1_allocate_blend( face, num_designs, 0 );
845      if ( error )
846        goto Exit;
847      blend = face->blend;
848    }
849    else if ( blend->num_designs != (FT_UInt)num_designs )
850    {
851      FT_ERROR(( "parse_weight_vector:"
852                 " /BlendDesignPosition and /WeightVector have\n" ));
853      FT_ERROR(( "                    "
854                 " different number of elements!\n" ));
855      error = T1_Err_Invalid_File_Format;
856      goto Exit;
857    }
858
859    old_cursor = parser->root.cursor;
860    old_limit  = parser->root.limit;
861
862    for ( n = 0; n < num_designs; n++ )
863    {
864      token = design_tokens + n;
865      parser->root.cursor = token->start;
866      parser->root.limit  = token->limit;
867
868      blend->default_weight_vector[n] =
869      blend->weight_vector[n]         = T1_ToFixed( parser, 0 );
870    }
871
872    parser->root.cursor = old_cursor;
873    parser->root.limit  = old_limit;
874
875  Exit:
876    parser->root.error = error;
877  }
878
879
880#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
881
882
883
884
885  /*************************************************************************/
886  /*************************************************************************/
887  /*****                                                               *****/
888  /*****                      TYPE 1 SYMBOL PARSING                    *****/
889  /*****                                                               *****/
890  /*************************************************************************/
891  /*************************************************************************/
892
893  static FT_Error
894  t1_load_keyword( T1_Face         face,
895                   T1_Loader       loader,
896                   const T1_Field  field )
897  {
898    FT_Error  error;
899    void*     dummy_object;
900    void**    objects;
901    FT_UInt   max_objects;
902    PS_Blend  blend = face->blend;
903
904
905    /* if the keyword has a dedicated callback, call it */
906    if ( field->type == T1_FIELD_TYPE_CALLBACK )
907    {
908      field->reader( (FT_Face)face, loader );
909      error = loader->parser.root.error;
910      goto Exit;
911    }
912
913    /* now, the keyword is either a simple field, or a table of fields; */
914    /* we are now going to take care of it                              */
915    switch ( field->location )
916    {
917    case T1_FIELD_LOCATION_FONT_INFO:
918      dummy_object = &face->type1.font_info;
919      objects      = &dummy_object;
920      max_objects  = 0;
921
922      if ( blend )
923      {
924        objects     = (void**)blend->font_infos;
925        max_objects = blend->num_designs;
926      }
927      break;
928
929    case T1_FIELD_LOCATION_PRIVATE:
930      dummy_object = &face->type1.private_dict;
931      objects      = &dummy_object;
932      max_objects  = 0;
933
934      if ( blend )
935      {
936        objects     = (void**)blend->privates;
937        max_objects = blend->num_designs;
938      }
939      break;
940
941    case T1_FIELD_LOCATION_BBOX:
942      dummy_object = &face->type1.font_bbox;
943      objects      = &dummy_object;
944      max_objects  = 0;
945
946      if ( blend )
947      {
948        objects     = (void**)blend->bboxes;
949        max_objects = blend->num_designs;
950      }
951      break;
952
953    default:
954      dummy_object = &face->type1;
955      objects      = &dummy_object;
956      max_objects  = 0;
957    }
958
959    if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
960         field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
961      error = T1_Load_Field_Table( &loader->parser, field,
962                                   objects, max_objects, 0 );
963    else
964      error = T1_Load_Field( &loader->parser, field,
965                             objects, max_objects, 0 );
966
967  Exit:
968    return error;
969  }
970
971
972  static int
973  is_space( FT_Byte  c )
974  {
975    return ( c == ' '  || c == '\t'              ||
976             c == '\r' || c == '\n' || c == '\f' ||
977             c == '\0'                           );
978  }
979
980
981  static int
982  read_binary_data( T1_Parser  parser,
983                    FT_Long*   size,
984                    FT_Byte**  base )
985  {
986    FT_Byte*  cur;
987    FT_Byte*  limit = parser->root.limit;
988
989
990    /* the binary data has one of the following formats */
991    /*                                                  */
992    /*   `size' [white*] RD white ....... ND            */
993    /*   `size' [white*] -| white ....... |-            */
994    /*                                                  */
995
996    T1_Skip_Spaces( parser );
997
998    cur = parser->root.cursor;
999
1000    if ( cur < limit && ft_isdigit( *cur ) )
1001    {
1002      *size = T1_ToInt( parser );
1003
1004      T1_Skip_PS_Token( parser );   /* `RD' or `-|' or something else */
1005
1006      /* there is only one whitespace char after the */
1007      /* `RD' or `-|' token                          */
1008      *base = parser->root.cursor + 1;
1009
1010      parser->root.cursor += *size + 1;
1011      return !parser->root.error;
1012    }
1013
1014    FT_ERROR(( "read_binary_data: invalid size field\n" ));
1015    parser->root.error = T1_Err_Invalid_File_Format;
1016    return 0;
1017  }
1018
1019
1020  /* We now define the routines to handle the `/Encoding', `/Subrs', */
1021  /* and `/CharStrings' dictionaries.                                */
1022
1023  static void
1024  parse_font_matrix( T1_Face    face,
1025                     T1_Loader  loader )
1026  {
1027    T1_Parser   parser = &loader->parser;
1028    FT_Matrix*  matrix = &face->type1.font_matrix;
1029    FT_Vector*  offset = &face->type1.font_offset;
1030    FT_Face     root   = (FT_Face)&face->root;
1031    FT_Fixed    temp[6];
1032    FT_Fixed    temp_scale;
1033
1034
1035    (void)T1_ToFixedArray( parser, 6, temp, 3 );
1036
1037    temp_scale = FT_ABS( temp[3] );
1038
1039    /* Set Units per EM based on FontMatrix values.  We set the value to */
1040    /* 1000 / temp_scale, because temp_scale was already multiplied by   */
1041    /* 1000 (in t1_tofixed, from psobjs.c).                              */
1042
1043    root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
1044                                                 temp_scale ) >> 16 );
1045
1046    /* we need to scale the values by 1.0/temp_scale */
1047    if ( temp_scale != 0x10000L )
1048    {
1049      temp[0] = FT_DivFix( temp[0], temp_scale );
1050      temp[1] = FT_DivFix( temp[1], temp_scale );
1051      temp[2] = FT_DivFix( temp[2], temp_scale );
1052      temp[4] = FT_DivFix( temp[4], temp_scale );
1053      temp[5] = FT_DivFix( temp[5], temp_scale );
1054      temp[3] = 0x10000L;
1055    }
1056
1057    matrix->xx = temp[0];
1058    matrix->yx = temp[1];
1059    matrix->xy = temp[2];
1060    matrix->yy = temp[3];
1061
1062    /* note that the offsets must be expressed in integer font units */
1063    offset->x = temp[4] >> 16;
1064    offset->y = temp[5] >> 16;
1065  }
1066
1067
1068  static void
1069  parse_encoding( T1_Face    face,
1070                  T1_Loader  loader )
1071  {
1072    T1_Parser  parser = &loader->parser;
1073    FT_Byte*   cur;
1074    FT_Byte*   limit  = parser->root.limit;
1075
1076    PSAux_Service  psaux = (PSAux_Service)face->psaux;
1077
1078
1079    T1_Skip_Spaces( parser );
1080    cur = parser->root.cursor;
1081    if ( cur >= limit )
1082    {
1083      FT_ERROR(( "parse_encoding: out of bounds!\n" ));
1084      parser->root.error = T1_Err_Invalid_File_Format;
1085      return;
1086    }
1087
1088    /* if we have a number or `[', the encoding is an array, */
1089    /* and we must load it now                               */
1090    if ( ft_isdigit( *cur ) || *cur == '[' )
1091    {
1092      T1_Encoding  encode          = &face->type1.encoding;
1093      FT_Int       count, n;
1094      PS_Table     char_table      = &loader->encoding_table;
1095      FT_Memory    memory          = parser->root.memory;
1096      FT_Error     error;
1097      FT_Bool      only_immediates = 0;
1098
1099
1100      /* read the number of entries in the encoding; should be 256 */
1101      if ( *cur == '[' )
1102      {
1103        count           = 256;
1104        only_immediates = 1;
1105        parser->root.cursor++;
1106      }
1107      else
1108        count = (FT_Int)T1_ToInt( parser );
1109
1110      T1_Skip_Spaces( parser );
1111      if ( parser->root.cursor >= limit )
1112        return;
1113
1114      /* we use a T1_Table to store our charnames */
1115      loader->num_chars = encode->num_chars = count;
1116      if ( FT_NEW_ARRAY( encode->char_index, count )     ||
1117           FT_NEW_ARRAY( encode->char_name,  count )     ||
1118           FT_SET_ERROR( psaux->ps_table_funcs->init(
1119                           char_table, count, memory ) ) )
1120      {
1121        parser->root.error = error;
1122        return;
1123      }
1124
1125      /* We need to `zero' out encoding_table.elements */
1126      for ( n = 0; n < count; n++ )
1127      {
1128        char*  notdef = (char *)".notdef";
1129
1130
1131        T1_Add_Table( char_table, n, notdef, 8 );
1132      }
1133
1134      /* Now we need to read records of the form                */
1135      /*                                                        */
1136      /*   ... charcode /charname ...                           */
1137      /*                                                        */
1138      /* for each entry in our table.                           */
1139      /*                                                        */
1140      /* We simply look for a number followed by an immediate   */
1141      /* name.  Note that this ignores correctly the sequence   */
1142      /* that is often seen in type1 fonts:                     */
1143      /*                                                        */
1144      /*   0 1 255 { 1 index exch /.notdef put } for dup        */
1145      /*                                                        */
1146      /* used to clean the encoding array before anything else. */
1147      /*                                                        */
1148      /* Alternatively, if the array is directly given as       */
1149      /*                                                        */
1150      /*   /Encoding [ ... ]                                    */
1151      /*                                                        */
1152      /* we only read immediates.                               */
1153
1154      n = 0;
1155      T1_Skip_Spaces( parser );
1156
1157      while ( parser->root.cursor < limit )
1158      {
1159        cur = parser->root.cursor;
1160
1161        /* we stop when we encounter a `def' or `]' */
1162        if ( *cur == 'd' && cur + 3 < limit )
1163        {
1164          if ( cur[1] == 'e'      &&
1165               cur[2] == 'f'      &&
1166               is_space( cur[3] ) )
1167          {
1168            FT_TRACE6(( "encoding end\n" ));
1169            cur += 3;
1170            break;
1171          }
1172        }
1173        if ( *cur == ']' )
1174        {
1175          FT_TRACE6(( "encoding end\n" ));
1176          cur++;
1177          break;
1178        }
1179
1180        /* check whether we've found an entry */
1181        if ( ft_isdigit( *cur ) || only_immediates )
1182        {
1183          FT_Int  charcode;
1184
1185
1186          if ( only_immediates )
1187            charcode = n;
1188          else
1189          {
1190            charcode = (FT_Int)T1_ToInt( parser );
1191            T1_Skip_Spaces( parser );
1192          }
1193
1194          cur = parser->root.cursor;
1195
1196          if ( *cur == '/' && cur + 2 < limit && n < count )
1197          {
1198            FT_PtrDist  len;
1199
1200
1201            cur++;
1202
1203            parser->root.cursor = cur;
1204            T1_Skip_PS_Token( parser );
1205            if ( parser->root.error )
1206              return;
1207
1208            len = parser->root.cursor - cur;
1209
1210            parser->root.error = T1_Add_Table( char_table, charcode,
1211                                               cur, len + 1 );
1212            if ( parser->root.error )
1213              return;
1214            char_table->elements[charcode][len] = '\0';
1215
1216            n++;
1217          }
1218        }
1219        else
1220          T1_Skip_PS_Token( parser );
1221
1222        T1_Skip_Spaces( parser );
1223      }
1224
1225      face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
1226      parser->root.cursor       = cur;
1227    }
1228
1229    /* Otherwise, we should have either `StandardEncoding', */
1230    /* `ExpertEncoding', or `ISOLatin1Encoding'             */
1231    else
1232    {
1233      if ( cur + 17 < limit                                            &&
1234           ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
1235        face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
1236
1237      else if ( cur + 15 < limit                                          &&
1238                ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
1239        face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
1240
1241      else if ( cur + 18 < limit                                             &&
1242                ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
1243        face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
1244
1245      else
1246        parser->root.error = T1_Err_Ignore;
1247    }
1248  }
1249
1250
1251  static void
1252  parse_subrs( T1_Face    face,
1253               T1_Loader  loader )
1254  {
1255    T1_Parser  parser = &loader->parser;
1256    PS_Table   table  = &loader->subrs;
1257    FT_Memory  memory = parser->root.memory;
1258    FT_Error   error;
1259    FT_Int     n, num_subrs;
1260
1261    PSAux_Service  psaux  = (PSAux_Service)face->psaux;
1262
1263
1264    T1_Skip_Spaces( parser );
1265
1266    /* test for empty array */
1267    if ( parser->root.cursor < parser->root.limit &&
1268         *parser->root.cursor == '['              )
1269    {
1270      T1_Skip_PS_Token( parser );
1271      T1_Skip_Spaces  ( parser );
1272      if ( parser->root.cursor >= parser->root.limit ||
1273           *parser->root.cursor != ']'               )
1274        parser->root.error = T1_Err_Invalid_File_Format;
1275      return;
1276    }
1277
1278    num_subrs = (FT_Int)T1_ToInt( parser );
1279
1280    /* position the parser right before the `dup' of the first subr */
1281    T1_Skip_PS_Token( parser );         /* `array' */
1282    if ( parser->root.error )
1283      return;
1284    T1_Skip_Spaces( parser );
1285
1286    /* initialize subrs array -- with synthetic fonts it is possible */
1287    /* we get here twice                                             */
1288    if ( !loader->num_subrs )
1289    {
1290      error = psaux->ps_table_funcs->init( table, num_subrs, memory );
1291      if ( error )
1292        goto Fail;
1293    }
1294
1295    /* the format is simple:                                 */
1296    /*                                                       */
1297    /*   `index' + binary data                               */
1298    /*                                                       */
1299    for ( n = 0; n < num_subrs; n++ )
1300    {
1301      FT_Long   idx, size;
1302      FT_Byte*  base;
1303
1304
1305      /* If the next token isn't `dup', we are also done.  This */
1306      /* happens when there are `holes' in the Subrs array.     */
1307      if ( ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
1308        break;
1309
1310      T1_Skip_PS_Token( parser );       /* `dup' */
1311
1312      idx = T1_ToInt( parser );
1313
1314      if ( !read_binary_data( parser, &size, &base ) )
1315        return;
1316
1317      /* The binary string is followed by one token, e.g. `NP' */
1318      /* (bound to `noaccess put') or by two separate tokens:  */
1319      /* `noaccess' & `put'.  We position the parser right     */
1320      /* before the next `dup', if any.                        */
1321      T1_Skip_PS_Token( parser );   /* `NP' or `|' or `noaccess' */
1322      if ( parser->root.error )
1323        return;
1324      T1_Skip_Spaces  ( parser );
1325
1326      if ( ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
1327      {
1328        T1_Skip_PS_Token( parser ); /* skip `put' */
1329        T1_Skip_Spaces  ( parser );
1330      }
1331
1332      /* with synthetic fonts it is possible we get here twice */
1333      if ( loader->num_subrs )
1334        continue;
1335
1336      /* some fonts use a value of -1 for lenIV to indicate that */
1337      /* the charstrings are unencoded                           */
1338      /*                                                         */
1339      /* thanks to Tom Kacvinsky for pointing this out           */
1340      /*                                                         */
1341      if ( face->type1.private_dict.lenIV >= 0 )
1342      {
1343        FT_Byte*  temp;
1344
1345
1346        /* t1_decrypt() shouldn't write to base -- make temporary copy */
1347        if ( FT_ALLOC( temp, size ) )
1348          goto Fail;
1349        FT_MEM_COPY( temp, base, size );
1350        psaux->t1_decrypt( temp, size, 4330 );
1351        size -= face->type1.private_dict.lenIV;
1352        error = T1_Add_Table( table, (FT_Int)idx,
1353                              temp + face->type1.private_dict.lenIV, size );
1354        FT_FREE( temp );
1355      }
1356      else
1357        error = T1_Add_Table( table, (FT_Int)idx, base, size );
1358      if ( error )
1359        goto Fail;
1360    }
1361
1362    if ( !loader->num_subrs )
1363      loader->num_subrs = num_subrs;
1364
1365    return;
1366
1367  Fail:
1368    parser->root.error = error;
1369  }
1370
1371
1372#define TABLE_EXTEND  5
1373
1374
1375  static void
1376  parse_charstrings( T1_Face    face,
1377                     T1_Loader  loader )
1378  {
1379    T1_Parser      parser       = &loader->parser;
1380    PS_Table       code_table   = &loader->charstrings;
1381    PS_Table       name_table   = &loader->glyph_names;
1382    PS_Table       swap_table   = &loader->swap_table;
1383    FT_Memory      memory       = parser->root.memory;
1384    FT_Error       error;
1385
1386    PSAux_Service  psaux        = (PSAux_Service)face->psaux;
1387
1388    FT_Byte*       cur;
1389    FT_Byte*       limit        = parser->root.limit;
1390    FT_Int         n, num_glyphs;
1391    FT_UInt        notdef_index = 0;
1392    FT_Byte        notdef_found = 0;
1393
1394
1395    num_glyphs = (FT_Int)T1_ToInt( parser );
1396    /* some fonts like Optima-Oblique not only define the /CharStrings */
1397    /* array but access it also                                        */
1398    if ( num_glyphs == 0 || parser->root.error )
1399      return;
1400
1401    /* initialize tables, leaving space for addition of .notdef, */
1402    /* if necessary, and a few other glyphs to handle buggy      */
1403    /* fonts which have more glyphs than specified.              */
1404
1405    /* for some non-standard fonts like `Optima' which provides  */
1406    /* different outlines depending on the resolution it is      */
1407    /* possible to get here twice                                */
1408    if ( !loader->num_glyphs )
1409    {
1410      error = psaux->ps_table_funcs->init(
1411                code_table, num_glyphs + 1 + TABLE_EXTEND, memory );
1412      if ( error )
1413        goto Fail;
1414
1415      error = psaux->ps_table_funcs->init(
1416                name_table, num_glyphs + 1 + TABLE_EXTEND, memory );
1417      if ( error )
1418        goto Fail;
1419
1420      /* Initialize table for swapping index notdef_index and */
1421      /* index 0 names and codes (if necessary).              */
1422
1423      error = psaux->ps_table_funcs->init( swap_table, 4, memory );
1424      if ( error )
1425        goto Fail;
1426    }
1427
1428    n = 0;
1429
1430    for (;;)
1431    {
1432      FT_Long   size;
1433      FT_Byte*  base;
1434
1435
1436      /* the format is simple:        */
1437      /*   `/glyphname' + binary data */
1438
1439      T1_Skip_Spaces( parser );
1440
1441      cur = parser->root.cursor;
1442      if ( cur >= limit )
1443        break;
1444
1445      /* we stop when we find a `def' or `end' keyword */
1446      if ( cur + 3 < limit && is_space( cur[3] ) )
1447      {
1448        if ( cur[0] == 'd' &&
1449             cur[1] == 'e' &&
1450             cur[2] == 'f' )
1451        {
1452          /* There are fonts which have this: */
1453          /*                                  */
1454          /*   /CharStrings 118 dict def      */
1455          /*   Private begin                  */
1456          /*   CharStrings begin              */
1457          /*   ...                            */
1458          /*                                  */
1459          /* To catch this we ignore `def' if */
1460          /* no charstring has actually been  */
1461          /* seen.                            */
1462          if ( n )
1463            break;
1464        }
1465
1466        if ( cur[0] == 'e' &&
1467             cur[1] == 'n' &&
1468             cur[2] == 'd' )
1469          break;
1470      }
1471
1472      T1_Skip_PS_Token( parser );
1473      if ( parser->root.error )
1474        return;
1475
1476      if ( *cur == '/' )
1477      {
1478        FT_PtrDist  len;
1479
1480
1481        if ( cur + 1 >= limit )
1482        {
1483          error = T1_Err_Invalid_File_Format;
1484          goto Fail;
1485        }
1486
1487        cur++;                              /* skip `/' */
1488        len = parser->root.cursor - cur;
1489
1490        if ( !read_binary_data( parser, &size, &base ) )
1491          return;
1492
1493        /* for some non-standard fonts like `Optima' which provides */
1494        /* different outlines depending on the resolution it is     */
1495        /* possible to get here twice                               */
1496        if ( loader->num_glyphs )
1497          continue;
1498
1499        error = T1_Add_Table( name_table, n, cur, len + 1 );
1500        if ( error )
1501          goto Fail;
1502
1503        /* add a trailing zero to the name table */
1504        name_table->elements[n][len] = '\0';
1505
1506        /* record index of /.notdef */
1507        if ( *cur == '.'                                              &&
1508             ft_strcmp( ".notdef",
1509                        (const char*)(name_table->elements[n]) ) == 0 )
1510        {
1511          notdef_index = n;
1512          notdef_found = 1;
1513        }
1514
1515        if ( face->type1.private_dict.lenIV >= 0   &&
1516             n < num_glyphs + TABLE_EXTEND )
1517        {
1518          FT_Byte*  temp;
1519
1520
1521          /* t1_decrypt() shouldn't write to base -- make temporary copy */
1522          if ( FT_ALLOC( temp, size ) )
1523            goto Fail;
1524          FT_MEM_COPY( temp, base, size );
1525          psaux->t1_decrypt( temp, size, 4330 );
1526          size -= face->type1.private_dict.lenIV;
1527          error = T1_Add_Table( code_table, n,
1528                                temp + face->type1.private_dict.lenIV, size );
1529          FT_FREE( temp );
1530        }
1531        else
1532          error = T1_Add_Table( code_table, n, base, size );
1533        if ( error )
1534          goto Fail;
1535
1536        n++;
1537      }
1538    }
1539
1540    if ( loader->num_glyphs )
1541      return;
1542    else
1543      loader->num_glyphs = n;
1544
1545    /* if /.notdef is found but does not occupy index 0, do our magic. */
1546    if ( ft_strcmp( (const char*)".notdef",
1547                    (const char*)name_table->elements[0] ) &&
1548         notdef_found                                      )
1549    {
1550      /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0  */
1551      /* name and code entries to swap_table.  Then place notdef_index   */
1552      /* name and code entries into swap_table.  Then swap name and code */
1553      /* entries at indices notdef_index and 0 using values stored in    */
1554      /* swap_table.                                                     */
1555
1556      /* Index 0 name */
1557      error = T1_Add_Table( swap_table, 0,
1558                            name_table->elements[0],
1559                            name_table->lengths [0] );
1560      if ( error )
1561        goto Fail;
1562
1563      /* Index 0 code */
1564      error = T1_Add_Table( swap_table, 1,
1565                            code_table->elements[0],
1566                            code_table->lengths [0] );
1567      if ( error )
1568        goto Fail;
1569
1570      /* Index notdef_index name */
1571      error = T1_Add_Table( swap_table, 2,
1572                            name_table->elements[notdef_index],
1573                            name_table->lengths [notdef_index] );
1574      if ( error )
1575        goto Fail;
1576
1577      /* Index notdef_index code */
1578      error = T1_Add_Table( swap_table, 3,
1579                            code_table->elements[notdef_index],
1580                            code_table->lengths [notdef_index] );
1581      if ( error )
1582        goto Fail;
1583
1584      error = T1_Add_Table( name_table, notdef_index,
1585                            swap_table->elements[0],
1586                            swap_table->lengths [0] );
1587      if ( error )
1588        goto Fail;
1589
1590      error = T1_Add_Table( code_table, notdef_index,
1591                            swap_table->elements[1],
1592                            swap_table->lengths [1] );
1593      if ( error )
1594        goto Fail;
1595
1596      error = T1_Add_Table( name_table, 0,
1597                            swap_table->elements[2],
1598                            swap_table->lengths [2] );
1599      if ( error )
1600        goto Fail;
1601
1602      error = T1_Add_Table( code_table, 0,
1603                            swap_table->elements[3],
1604                            swap_table->lengths [3] );
1605      if ( error )
1606        goto Fail;
1607
1608    }
1609    else if ( !notdef_found )
1610    {
1611      /* notdef_index is already 0, or /.notdef is undefined in   */
1612      /* charstrings dictionary.  Worry about /.notdef undefined. */
1613      /* We take index 0 and add it to the end of the table(s)    */
1614      /* and add our own /.notdef glyph to index 0.               */
1615
1616      /* 0 333 hsbw endchar */
1617      FT_Byte  notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E};
1618      char*    notdef_name    = (char *)".notdef";
1619
1620
1621      error = T1_Add_Table( swap_table, 0,
1622                            name_table->elements[0],
1623                            name_table->lengths [0] );
1624      if ( error )
1625        goto Fail;
1626
1627      error = T1_Add_Table( swap_table, 1,
1628                            code_table->elements[0],
1629                            code_table->lengths [0] );
1630      if ( error )
1631        goto Fail;
1632
1633      error = T1_Add_Table( name_table, 0, notdef_name, 8 );
1634      if ( error )
1635        goto Fail;
1636
1637      error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );
1638
1639      if ( error )
1640        goto Fail;
1641
1642      error = T1_Add_Table( name_table, n,
1643                            swap_table->elements[0],
1644                            swap_table->lengths [0] );
1645      if ( error )
1646        goto Fail;
1647
1648      error = T1_Add_Table( code_table, n,
1649                            swap_table->elements[1],
1650                            swap_table->lengths [1] );
1651      if ( error )
1652        goto Fail;
1653
1654      /* we added a glyph. */
1655      loader->num_glyphs = n + 1;
1656    }
1657
1658    return;
1659
1660  Fail:
1661    parser->root.error = error;
1662  }
1663
1664
1665  /*************************************************************************/
1666  /*                                                                       */
1667  /* Define the token field static variables.  This is a set of            */
1668  /* T1_FieldRec variables.                                                */
1669  /*                                                                       */
1670  /*************************************************************************/
1671
1672
1673  static
1674  const T1_FieldRec  t1_keywords[] =
1675  {
1676
1677#include "t1tokens.h"
1678
1679    /* now add the special functions... */
1680    T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
1681    T1_FIELD_CALLBACK( "Encoding", parse_encoding )
1682    T1_FIELD_CALLBACK( "Subrs", parse_subrs )
1683    T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
1684
1685#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
1686    T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
1687    T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
1688    T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
1689    T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
1690#endif
1691
1692    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
1693  };
1694
1695
1696#define T1_FIELD_COUNT                                           \
1697          ( sizeof ( t1_keywords ) / sizeof ( t1_keywords[0] ) )
1698
1699
1700  static FT_Error
1701  parse_dict( T1_Face    face,
1702              T1_Loader  loader,
1703              FT_Byte*   base,
1704              FT_Long    size,
1705              FT_Byte*   keyword_flags )
1706  {
1707    T1_Parser  parser = &loader->parser;
1708    FT_Byte   *limit, *start_binary = NULL;
1709    FT_Bool    have_integer = 0;
1710
1711
1712    parser->root.cursor = base;
1713    parser->root.limit  = base + size;
1714    parser->root.error  = T1_Err_Ok;
1715
1716    limit = parser->root.limit;
1717
1718    T1_Skip_Spaces( parser );
1719
1720    while ( parser->root.cursor < limit )
1721    {
1722      FT_Byte*  cur;
1723
1724
1725      cur = parser->root.cursor;
1726
1727      /* look for `FontDirectory' which causes problems for some fonts */
1728      if ( *cur == 'F' && cur + 25 < limit                    &&
1729           ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
1730      {
1731        FT_Byte*  cur2;
1732
1733
1734        /* skip the `FontDirectory' keyword */
1735        T1_Skip_PS_Token( parser );
1736        T1_Skip_Spaces  ( parser );
1737        cur = cur2 = parser->root.cursor;
1738
1739        /* look up the `known' keyword */
1740        while ( cur < limit )
1741        {
1742          if ( *cur == 'k' && cur + 5 < limit            &&
1743               ft_strncmp( (char*)cur, "known", 5 ) == 0 )
1744            break;
1745
1746          T1_Skip_PS_Token( parser );
1747          if ( parser->root.error )
1748            goto Exit;
1749          T1_Skip_Spaces( parser );
1750          cur = parser->root.cursor;
1751        }
1752
1753        if ( cur < limit )
1754        {
1755          T1_TokenRec  token;
1756
1757
1758          /* skip the `known' keyword and the token following it */
1759          T1_Skip_PS_Token( parser );
1760          T1_ToToken( parser, &token );
1761
1762          /* if the last token was an array, skip it! */
1763          if ( token.type == T1_TOKEN_TYPE_ARRAY )
1764            cur2 = parser->root.cursor;
1765        }
1766        parser->root.cursor = cur2;
1767        have_integer = 0;
1768      }
1769
1770      /* look for `eexec' */
1771      else if ( *cur == 'e' && cur + 5 < limit &&
1772                ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
1773        break;
1774
1775      /* look for `closefile' which ends the eexec section */
1776      else if ( *cur == 'c' && cur + 9 < limit &&
1777                ft_strncmp( (char*)cur, "closefile", 9 ) == 0 )
1778        break;
1779
1780      /* check whether we have an integer */
1781      else if ( ft_isdigit( *cur ) )
1782      {
1783        start_binary = cur;
1784        T1_Skip_PS_Token( parser );
1785        if ( parser->root.error )
1786          goto Exit;
1787        have_integer = 1;
1788      }
1789
1790      /* in valid Type 1 fonts we don't see `RD' or `-|' directly */
1791      /* since those tokens are handled by parse_subrs and        */
1792      /* parse_charstrings                                        */
1793      else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' &&
1794                have_integer )
1795      {
1796        FT_Long   s;
1797        FT_Byte*  b;
1798
1799
1800        parser->root.cursor = start_binary;
1801        if ( !read_binary_data( parser, &s, &b ) )
1802          return T1_Err_Invalid_File_Format;
1803        have_integer = 0;
1804      }
1805
1806      else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' &&
1807                have_integer )
1808      {
1809        FT_Long   s;
1810        FT_Byte*  b;
1811
1812
1813        parser->root.cursor = start_binary;
1814        if ( !read_binary_data( parser, &s, &b ) )
1815          return T1_Err_Invalid_File_Format;
1816        have_integer = 0;
1817      }
1818
1819      /* look for immediates */
1820      else if ( *cur == '/' && cur + 2 < limit )
1821      {
1822        FT_PtrDist  len;
1823
1824
1825        cur++;
1826
1827        parser->root.cursor = cur;
1828        T1_Skip_PS_Token( parser );
1829        if ( parser->root.error )
1830          goto Exit;
1831
1832        len = parser->root.cursor - cur;
1833
1834        if ( len > 0 && len < 22 && parser->root.cursor < limit )
1835        {
1836          /* now compare the immediate name to the keyword table */
1837          T1_Field  keyword      = (T1_Field)t1_keywords;
1838          FT_Byte*  keyword_flag = keyword_flags;
1839
1840
1841          for (;;)
1842          {
1843            FT_Byte*  name;
1844
1845
1846            name = (FT_Byte*)keyword->ident;
1847            if ( !name )
1848              break;
1849
1850            if ( cur[0] == name[0]                                  &&
1851                 len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
1852                 ft_memcmp( cur, name, len ) == 0                   )
1853            {
1854              /* We found it -- run the parsing callback! */
1855              /* We only record the first instance of any */
1856              /* field to deal adequately with synthetic  */
1857              /* fonts; /Subrs and /CharStrings are       */
1858              /* handled specially.                       */
1859              if ( keyword_flag[0] == 0                              ||
1860                   ft_strcmp( (const char*)name, "Subrs" ) == 0      ||
1861                   ft_strcmp( (const char*)name, "CharStrings") == 0 )
1862              {
1863                parser->root.error = t1_load_keyword( face,
1864                                                      loader,
1865                                                      keyword );
1866                if ( parser->root.error == T1_Err_Ok )
1867                  keyword_flag[0] = 1;
1868                else
1869                {
1870                  if ( FT_ERROR_BASE( parser->root.error ) == FT_Err_Ignore )
1871                    parser->root.error = T1_Err_Ok;
1872                  else
1873                    return parser->root.error;
1874                }
1875              }
1876              break;
1877            }
1878
1879            keyword++;
1880            keyword_flag++;
1881          }
1882        }
1883
1884        have_integer = 0;
1885      }
1886      else
1887      {
1888        T1_Skip_PS_Token( parser );
1889        if ( parser->root.error )
1890          goto Exit;
1891        have_integer = 0;
1892      }
1893
1894      T1_Skip_Spaces( parser );
1895    }
1896
1897  Exit:
1898    return parser->root.error;
1899  }
1900
1901
1902  static void
1903  t1_init_loader( T1_Loader  loader,
1904                  T1_Face    face )
1905  {
1906    FT_UNUSED( face );
1907
1908    FT_MEM_ZERO( loader, sizeof ( *loader ) );
1909    loader->num_glyphs = 0;
1910    loader->num_chars  = 0;
1911
1912    /* initialize the tables -- simply set their `init' field to 0 */
1913    loader->encoding_table.init = 0;
1914    loader->charstrings.init    = 0;
1915    loader->glyph_names.init    = 0;
1916    loader->subrs.init          = 0;
1917    loader->swap_table.init     = 0;
1918    loader->fontdata            = 0;
1919  }
1920
1921
1922  static void
1923  t1_done_loader( T1_Loader  loader )
1924  {
1925    T1_Parser  parser = &loader->parser;
1926
1927
1928    /* finalize tables */
1929    T1_Release_Table( &loader->encoding_table );
1930    T1_Release_Table( &loader->charstrings );
1931    T1_Release_Table( &loader->glyph_names );
1932    T1_Release_Table( &loader->swap_table );
1933    T1_Release_Table( &loader->subrs );
1934
1935    /* finalize parser */
1936    T1_Finalize_Parser( parser );
1937  }
1938
1939
1940  FT_LOCAL_DEF( FT_Error )
1941  T1_Open_Face( T1_Face  face )
1942  {
1943    T1_LoaderRec   loader;
1944    T1_Parser      parser;
1945    T1_Font        type1 = &face->type1;
1946    PS_Private     priv  = &type1->private_dict;
1947    FT_Error       error;
1948    FT_Byte        keyword_flags[T1_FIELD_COUNT];
1949
1950    PSAux_Service  psaux = (PSAux_Service)face->psaux;
1951
1952
1953    t1_init_loader( &loader, face );
1954
1955    /* default values */
1956    priv->blue_shift       = 7;
1957    priv->blue_fuzz        = 1;
1958    priv->lenIV            = 4;
1959    priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
1960    priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
1961
1962    parser = &loader.parser;
1963    error  = T1_New_Parser( parser,
1964                            face->root.stream,
1965                            face->root.memory,
1966                            psaux );
1967    if ( error )
1968      goto Exit;
1969
1970    {
1971      FT_UInt  n;
1972     
1973
1974      for ( n = 0; n < T1_FIELD_COUNT; n++ )
1975        keyword_flags[n] = 0;
1976    }
1977
1978    error = parse_dict( face, &loader, parser->base_dict, parser->base_len,
1979                        keyword_flags );
1980    if ( error )
1981      goto Exit;
1982
1983    error = T1_Get_Private_Dict( parser, psaux );
1984    if ( error )
1985      goto Exit;
1986
1987    error = parse_dict( face, &loader, parser->private_dict,
1988                        parser->private_len,
1989                        keyword_flags );
1990    if ( error )
1991      goto Exit;
1992
1993#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
1994
1995    /* the following can happen for MM instances; we then treat the */
1996    /* font as a normal PS font                                     */
1997    if ( face->blend                                             &&
1998         ( !face->blend->num_designs || !face->blend->num_axis ) )
1999      T1_Done_Blend( face );
2000
2001    /* another safety check */
2002    if ( face->blend )
2003    {
2004      FT_UInt  i;
2005
2006
2007      for ( i = 0; i < face->blend->num_axis; i++ )
2008        if ( !face->blend->design_map[i].num_points )
2009        {
2010          T1_Done_Blend( face );
2011          break;
2012        }
2013    }
2014
2015#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
2016
2017    /* now, propagate the subrs, charstrings, and glyphnames tables */
2018    /* to the Type1 data                                            */
2019    type1->num_glyphs = loader.num_glyphs;
2020
2021    if ( loader.subrs.init )
2022    {
2023      loader.subrs.init  = 0;
2024      type1->num_subrs   = loader.num_subrs;
2025      type1->subrs_block = loader.subrs.block;
2026      type1->subrs       = loader.subrs.elements;
2027      type1->subrs_len   = loader.subrs.lengths;
2028    }
2029
2030#ifdef FT_CONFIG_OPTION_INCREMENTAL
2031    if ( !face->root.internal->incremental_interface )
2032#endif
2033      if ( !loader.charstrings.init )
2034      {
2035        FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face!\n" ));
2036        error = T1_Err_Invalid_File_Format;
2037      }
2038
2039    loader.charstrings.init  = 0;
2040    type1->charstrings_block = loader.charstrings.block;
2041    type1->charstrings       = loader.charstrings.elements;
2042    type1->charstrings_len   = loader.charstrings.lengths;
2043
2044    /* we copy the glyph names `block' and `elements' fields; */
2045    /* the `lengths' field must be released later             */
2046    type1->glyph_names_block    = loader.glyph_names.block;
2047    type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
2048    loader.glyph_names.block    = 0;
2049    loader.glyph_names.elements = 0;
2050
2051    /* we must now build type1.encoding when we have a custom array */
2052    if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
2053    {
2054      FT_Int    charcode, idx, min_char, max_char;
2055      FT_Byte*  char_name;
2056      FT_Byte*  glyph_name;
2057
2058
2059      /* OK, we do the following: for each element in the encoding  */
2060      /* table, look up the index of the glyph having the same name */
2061      /* the index is then stored in type1.encoding.char_index, and */
2062      /* a the name to type1.encoding.char_name                     */
2063
2064      min_char = +32000;
2065      max_char = -32000;
2066
2067      charcode = 0;
2068      for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
2069      {
2070        type1->encoding.char_index[charcode] = 0;
2071        type1->encoding.char_name [charcode] = (char *)".notdef";
2072
2073        char_name = loader.encoding_table.elements[charcode];
2074        if ( char_name )
2075          for ( idx = 0; idx < type1->num_glyphs; idx++ )
2076          {
2077            glyph_name = (FT_Byte*)type1->glyph_names[idx];
2078            if ( ft_strcmp( (const char*)char_name,
2079                            (const char*)glyph_name ) == 0 )
2080            {
2081              type1->encoding.char_index[charcode] = (FT_UShort)idx;
2082              type1->encoding.char_name [charcode] = (char*)glyph_name;
2083
2084              /* Change min/max encoded char only if glyph name is */
2085              /* not /.notdef                                      */
2086              if ( ft_strcmp( (const char*)".notdef",
2087                              (const char*)glyph_name ) != 0 )
2088              {
2089                if ( charcode < min_char )
2090                  min_char = charcode;
2091                if ( charcode > max_char )
2092                  max_char = charcode;
2093              }
2094              break;
2095            }
2096          }
2097      }
2098
2099      /*
2100       *  Yes, this happens: Certain PDF-embedded fonts have only a
2101       *  `.notdef' glyph defined!
2102       */
2103
2104      if ( min_char > max_char )
2105      {
2106        min_char = 0;
2107        max_char = loader.encoding_table.max_elems;
2108      }
2109
2110      type1->encoding.code_first = min_char;
2111      type1->encoding.code_last  = max_char;
2112      type1->encoding.num_chars  = loader.num_chars;
2113    }
2114
2115  Exit:
2116    t1_done_loader( &loader );
2117    return error;
2118  }
2119
2120
2121/* END */
Note: See TracBrowser for help on using the repository browser.