z1load.c 45.3 KB
Newer Older
Werner Lemberg's avatar
   
Werner Lemberg committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/***************************************************************************/
/*                                                                         */
/*  z1load.c                                                               */
/*                                                                         */
/*    Experimental Type 1 font loader (body).                              */
/*                                                                         */
/*  Copyright 1996-2000 by                                                 */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/***************************************************************************/


  /*************************************************************************/
  /*                                                                       */
  /* This is the new and improved Type 1 data loader for FreeType 2.  The  */
  /* old loader has several problems: it is slow, complex, difficult to    */
  /* maintain, and contains incredible hacks to make it accept some        */
  /* ill-formed Type 1 fonts without hiccup-ing.  Moreover, about 5% of    */
  /* the Type 1 fonts on my machine still aren't loaded correctly by it.   */
  /*                                                                       */
  /* This version is much simpler, much faster and also easier to read and */
  /* maintain by a great order of magnitude.  The idea behind it is to     */
  /* _not_ try to read the Type 1 token stream with a state machine (i.e.  */
  /* a Postscript-like interpreter) but rather to perform simple pattern   */
  /* matching.                                                             */
  /*                                                                       */
  /* Indeed, nearly all data definitions follow a simple pattern like      */
  /*                                                                       */
  /*  ... /Field <data> ...                                                */
  /*                                                                       */
  /* where <data> can be a number, a boolean, a string, or an array of     */
  /* numbers.  There are a few exceptions, namely the encoding, font name, */
  /* charstrings, and subrs; they are handled with a special pattern       */
  /* matching routine.                                                     */
  /*                                                                       */
  /* All other common cases are handled very simply.  The matching rules   */
  /* are defined in the file `t1tokens.h' through the use of several       */
  /* macros calls PARSE_XXX.                                               */
  /*                                                                       */
  /* This file is included twice here; the first time to generate parsing  */
  /* callback functions, the second to generate a table of keywords (with  */
  /* pointers to the associated callback).                                 */
  /*                                                                       */
  /* The function `parse_dict' simply scans *linearly* a given dictionary  */
  /* (either the top-level or private one) and calls the appropriate       */
  /* callback when it encounters an immediate keyword.                     */
  /*                                                                       */
  /* This is by far the fastest way one can find to parse and read all     */
  /* data.                                                                 */
  /*                                                                       */
  /* This led to tremendous code size reduction.  Note that later, the     */
  /* glyph loader will also be _greatly_ simplified, and the automatic     */
  /* hinter will replace the clumsy `t1hinter'.                            */
  /*                                                                       */
  /*************************************************************************/

63

64
65
#include <freetype/internal/ftdebug.h>
#include <freetype/config/ftconfig.h>
66
#include <freetype/ftmm.h>
67

68
#include <freetype/internal/t1types.h>
Werner Lemberg's avatar
   
Werner Lemberg committed
69
#include <freetype/internal/t1errors.h>
70

Werner Lemberg's avatar
   
Werner Lemberg committed
71

72
#ifdef FT_FLAT_COMPILE
Werner Lemberg's avatar
   
Werner Lemberg committed
73

74
#include "z1load.h"
Werner Lemberg's avatar
   
Werner Lemberg committed
75

76
#else
Werner Lemberg's avatar
   
Werner Lemberg committed
77

78
#include <type1z/z1load.h>
Werner Lemberg's avatar
   
Werner Lemberg committed
79

80
81
#endif

82

Werner Lemberg's avatar
   
Werner Lemberg committed
83
84
85
86
87
88
89
90
91
92
#include <string.h>     /* for strncmp(), strcmp() */
#include <ctype.h>      /* for isalnum()           */


  /*************************************************************************/
  /*                                                                       */
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  /* messages during execution.                                            */
  /*                                                                       */
93
#undef  FT_COMPONENT
Werner Lemberg's avatar
   
Werner Lemberg committed
94
95
#define FT_COMPONENT  trace_z1load

96

97
#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
Werner Lemberg's avatar
   
Werner Lemberg committed
98
99
100
101
102
103
104
105
106


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                    MULTIPLE MASTERS SUPPORT                   *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/
Werner Lemberg's avatar
   
Werner Lemberg committed
107

Werner Lemberg's avatar
   
Werner Lemberg committed
108
109
110
111
112
113
114
115
  static
  FT_Error  t1_allocate_blend( T1_Face  face,
                               FT_UInt  num_designs,
                               FT_UInt  num_axis )
  {
    T1_Blend*  blend;
    FT_Memory  memory = face->root.memory;
    FT_Error   error  = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
116
117


Werner Lemberg's avatar
   
Werner Lemberg committed
118
119
120
121
122
    blend = face->blend;
    if ( !blend )
    {
      if ( ALLOC( blend, sizeof ( *blend ) ) )
        goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
123

Werner Lemberg's avatar
   
Werner Lemberg committed
124
125
      face->blend = blend;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
126

Werner Lemberg's avatar
   
Werner Lemberg committed
127
128
129
130
131
    /* allocate design data if needed */
    if ( num_designs > 0 )
    {
      if ( blend->num_designs == 0 )
      {
132
133
        FT_UInt  nn;
        
Werner Lemberg's avatar
   
Werner Lemberg committed
134

Werner Lemberg's avatar
   
Werner Lemberg committed
135
136
137
138
139
        /* allocate the blend `private' and `font_info' dictionaries */
        if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo )  ||
             ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private )     ||
             ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) )
          goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
140

Werner Lemberg's avatar
   
Werner Lemberg committed
141
        blend->default_weight_vector = blend->weight_vector + num_designs;
Werner Lemberg's avatar
   
Werner Lemberg committed
142

Werner Lemberg's avatar
   
Werner Lemberg committed
143
144
        blend->font_infos[0] = &face->type1.font_info;
        blend->privates  [0] = &face->type1.private_dict;
145
146
147
        
        for ( nn = 2; nn <= num_designs; nn++ )
        {
Werner Lemberg's avatar
   
Werner Lemberg committed
148
149
          blend->privates[nn]   = blend->privates  [nn - 1] + 1;
          blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
150
151
        }
        
Werner Lemberg's avatar
   
Werner Lemberg committed
152
153
154
155
156
        blend->num_designs   = num_designs;
      }
      else if ( blend->num_designs != num_designs )
        goto Fail;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
157

Werner Lemberg's avatar
   
Werner Lemberg committed
158
159
160
161
162
    /* allocate axis data if needed */
    if ( num_axis > 0 )
    {
      if ( blend->num_axis != 0 && blend->num_axis != num_axis )
        goto Fail;
Werner Lemberg's avatar
   
Werner Lemberg committed
163

Werner Lemberg's avatar
   
Werner Lemberg committed
164
165
      blend->num_axis = num_axis;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
166

Werner Lemberg's avatar
   
Werner Lemberg committed
167
168
169
170
171
172
    /* allocate the blend design pos table if needed */
    num_designs = blend->num_designs;
    num_axis    = blend->num_axis;
    if ( num_designs && num_axis && blend->design_pos[0] == 0 )
    {
      FT_UInt  n;
Werner Lemberg's avatar
   
Werner Lemberg committed
173
174


Werner Lemberg's avatar
   
Werner Lemberg committed
175
176
177
      if ( ALLOC_ARRAY( blend->design_pos[0],
                        num_designs * num_axis, FT_Fixed ) )
        goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
178

Werner Lemberg's avatar
   
Werner Lemberg committed
179
180
181
      for ( n = 1; n < num_designs; n++ )
        blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
182

Werner Lemberg's avatar
   
Werner Lemberg committed
183
184
  Exit:
    return error;
Werner Lemberg's avatar
   
Werner Lemberg committed
185

Werner Lemberg's avatar
   
Werner Lemberg committed
186
187
188
  Fail:
    error = -1;
    goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
189
190
191
  }


Werner Lemberg's avatar
   
Werner Lemberg committed
192
193
194
195
196
197
198
  LOCAL_FUNC
  FT_Error  Z1_Get_Multi_Master( T1_Face           face,
                                 FT_Multi_Master*  master )
  {
    T1_Blend*  blend = face->blend;
    FT_UInt    n;
    FT_Error   error;
Werner Lemberg's avatar
   
Werner Lemberg committed
199
200


Werner Lemberg's avatar
   
Werner Lemberg committed
201
    error = T1_Err_Invalid_Argument;
Werner Lemberg's avatar
   
Werner Lemberg committed
202

Werner Lemberg's avatar
   
Werner Lemberg committed
203
204
205
206
    if ( blend )
    {
      master->num_axis    = blend->num_axis;
      master->num_designs = blend->num_designs;
Werner Lemberg's avatar
   
Werner Lemberg committed
207

Werner Lemberg's avatar
   
Werner Lemberg committed
208
209
210
211
      for ( n = 0; n < blend->num_axis; n++ )
      {
        FT_MM_Axis*    axis = master->axis + n;
        T1_DesignMap*  map = blend->design_map + n;
Werner Lemberg's avatar
   
Werner Lemberg committed
212
213


Werner Lemberg's avatar
   
Werner Lemberg committed
214
215
216
217
218
219
220
        axis->name    = blend->axis_names[n];
        axis->minimum = map->design_points[0];
        axis->maximum = map->design_points[map->num_points - 1];
      }
      error = 0;
    }
    return error;
Werner Lemberg's avatar
   
Werner Lemberg committed
221
222
223
  }


Werner Lemberg's avatar
   
Werner Lemberg committed
224
225
226
227
228
229
230
231
  LOCAL_FUNC
  FT_Error  Z1_Set_MM_Blend( T1_Face    face,
                             FT_UInt    num_coords,
                             FT_Fixed*  coords )
  {
    T1_Blend*  blend = face->blend;
    FT_Error   error;
    FT_UInt    n, m;
Werner Lemberg's avatar
   
Werner Lemberg committed
232

Werner Lemberg's avatar
   
Werner Lemberg committed
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248

    error = T1_Err_Invalid_Argument;

    if ( blend && blend->num_axis == num_coords )
    {
      /* recompute the weight vector from the blend coordinates */
      error = FT_Err_Ok;

      for ( n = 0; n < blend->num_designs; n++ )
      {
        FT_Fixed  result = 0x10000L;  /* 1.0 fixed */


        for ( m = 0; m < blend->num_axis; m++ )
        {
          FT_Fixed  factor;
Werner Lemberg's avatar
   
Werner Lemberg committed
249

Werner Lemberg's avatar
   
Werner Lemberg committed
250
251
252
253
254

          /* get current blend axis position */
          factor = coords[m];
          if ( factor < 0 )        factor = 0;
          if ( factor > 0x10000L ) factor = 0x10000L;
Werner Lemberg's avatar
   
Werner Lemberg committed
255

Werner Lemberg's avatar
   
Werner Lemberg committed
256
257
          if ( ( n & ( 1 << m ) ) == 0 )
            factor = 0x10000L - factor;
Werner Lemberg's avatar
   
Werner Lemberg committed
258

Werner Lemberg's avatar
   
Werner Lemberg committed
259
260
261
262
263
264
265
266
267
          result = FT_MulFix( result, factor );
        }
        blend->weight_vector[n] = result;
      }

      error = FT_Err_Ok;
    }
    return error;
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
268
269


Werner Lemberg's avatar
   
Werner Lemberg committed
270
271
272
273
274
275
276
277
  LOCAL_FUNC
  FT_Error  Z1_Set_MM_Design( T1_Face   face,
                              FT_UInt   num_coords,
                              FT_Long*  coords )
  {
    T1_Blend*  blend = face->blend;
    FT_Error   error;
    FT_UInt    n, p;
278

Werner Lemberg's avatar
   
Werner Lemberg committed
279

Werner Lemberg's avatar
   
Werner Lemberg committed
280
281
282
283
284
    error = T1_Err_Invalid_Argument;
    if ( blend && blend->num_axis == num_coords )
    {
      /* compute the blend coordinates through the blend design map */
      FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
Werner Lemberg's avatar
   
Werner Lemberg committed
285

286

Werner Lemberg's avatar
   
Werner Lemberg committed
287
288
289
290
291
292
293
294
      for ( n = 0; n < blend->num_axis; n++ )
      {
        FT_Long        design  = coords[n];
        FT_Fixed       the_blend;
        T1_DesignMap*  map     = blend->design_map + n;
        FT_Fixed*      designs = map->design_points;
        FT_Fixed*      blends  = map->blend_points;
        FT_Int         before  = -1, after = -1;
Werner Lemberg's avatar
   
Werner Lemberg committed
295

Werner Lemberg's avatar
   
Werner Lemberg committed
296
297
298
        for ( p = 0; p < map->num_points; p++ )
        {
          FT_Fixed  p_design = designs[p];
Werner Lemberg's avatar
   
Werner Lemberg committed
299

Werner Lemberg's avatar
   
Werner Lemberg committed
300
301
302
303
304
305
306

          /* exact match ? */
          if ( design == p_design )
          {
            the_blend = blends[p];
            goto Found;
          }
Werner Lemberg's avatar
   
Werner Lemberg committed
307

Werner Lemberg's avatar
   
Werner Lemberg committed
308
309
310
311
312
          if ( design < p_design )
          {
            after = p;
            break;
          }
Werner Lemberg's avatar
   
Werner Lemberg committed
313

Werner Lemberg's avatar
   
Werner Lemberg committed
314
315
          before = p;
        }
Werner Lemberg's avatar
   
Werner Lemberg committed
316

Werner Lemberg's avatar
   
Werner Lemberg committed
317
318
319
        /* now, interpolate if needed */
        if ( before < 0 )
          the_blend = blends[0];
Werner Lemberg's avatar
   
Werner Lemberg committed
320

Werner Lemberg's avatar
   
Werner Lemberg committed
321
322
        else if ( after < 0 )
          the_blend = blends[map->num_points - 1];
Werner Lemberg's avatar
   
Werner Lemberg committed
323

Werner Lemberg's avatar
   
Werner Lemberg committed
324
325
326
327
328
329
330
331
        else
          the_blend = FT_MulDiv( design         - designs[before],
                                 blends [after] - blends [before],
                                 designs[after] - designs[before] );

      Found:
        final_blends[n] = the_blend;
      }
Werner Lemberg's avatar
   
Werner Lemberg committed
332
333

      error = Z1_Set_MM_Blend( face, num_coords, final_blends );
Werner Lemberg's avatar
   
Werner Lemberg committed
334
335
336
337
    }

    return error;
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
338
339


Werner Lemberg's avatar
   
Werner Lemberg committed
340
341
342
343
344
  LOCAL_FUNC
  void  Z1_Done_Blend( T1_Face  face )
  {
    FT_Memory  memory = face->root.memory;
    T1_Blend*  blend  = face->blend;
Werner Lemberg's avatar
   
Werner Lemberg committed
345

Werner Lemberg's avatar
   
Werner Lemberg committed
346
347
348
349
350
351

    if ( blend )
    {
      FT_UInt  num_designs = blend->num_designs;
      FT_UInt  num_axis    = blend->num_axis;
      FT_UInt  n;
Werner Lemberg's avatar
   
Werner Lemberg committed
352

Werner Lemberg's avatar
   
Werner Lemberg committed
353
354
355
356
357

      /* release design pos table */
      FREE( blend->design_pos[0] );
      for ( n = 1; n < num_designs; n++ )
        blend->design_pos[n] = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
358

Werner Lemberg's avatar
   
Werner Lemberg committed
359
360
361
      /* release blend `private' and `font info' dictionaries */
      FREE( blend->privates[1] );
      FREE( blend->font_infos[1] );
362

Werner Lemberg's avatar
   
Werner Lemberg committed
363
364
365
366
367
      for ( n = 0; n < num_designs; n++ )
      {
        blend->privates  [n] = 0;
        blend->font_infos[n] = 0;
      }
Werner Lemberg's avatar
   
Werner Lemberg committed
368

Werner Lemberg's avatar
   
Werner Lemberg committed
369
370
371
      /* release weight vectors */
      FREE( blend->weight_vector );
      blend->default_weight_vector = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
372

Werner Lemberg's avatar
   
Werner Lemberg committed
373
374
375
      /* release axis names */
      for ( n = 0; n < num_axis; n++ )
        FREE( blend->axis_names[n] );
Werner Lemberg's avatar
   
Werner Lemberg committed
376

Werner Lemberg's avatar
   
Werner Lemberg committed
377
378
379
380
      /* release design map */
      for ( n = 0; n < num_axis; n++ )
      {
        T1_DesignMap*  dmap = blend->design_map + n;
381

Werner Lemberg's avatar
   
Werner Lemberg committed
382
383
384
385

        FREE( dmap->design_points );
        dmap->num_points = 0;
      }
Werner Lemberg's avatar
   
Werner Lemberg committed
386

Werner Lemberg's avatar
   
Werner Lemberg committed
387
388
389
      FREE( face->blend );
    }
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
390
391


Werner Lemberg's avatar
   
Werner Lemberg committed
392
393
394
395
  static
  void  parse_blend_axis_types( T1_Face     face,
                                Z1_Loader*  loader )
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
396
397
398
399
400
    T1_Token   axis_tokens[ T1_MAX_MM_AXIS ];
    FT_Int     n, num_axis;
    FT_Error   error = 0;
    T1_Blend*  blend;
    FT_Memory  memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
401

402

Werner Lemberg's avatar
   
Werner Lemberg committed
403
404
405
406
407
408
409
410
411
412
    /* take an array of objects */
    Z1_ToTokenArray( &loader->parser, axis_tokens,
                     T1_MAX_MM_AXIS, &num_axis );
    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
    {
      FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
                 num_axis ));
      error = T1_Err_Invalid_File_Format;
      goto Exit;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
413

Werner Lemberg's avatar
   
Werner Lemberg committed
414
415
416
417
    /* allocate blend if necessary */
    error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
    if ( error )
      goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
418

Werner Lemberg's avatar
   
Werner Lemberg committed
419
420
    blend  = face->blend;
    memory = face->root.memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
421

Werner Lemberg's avatar
   
Werner Lemberg committed
422
423
424
    /* each token is an immediate containing the name of the axis */
    for ( n = 0; n < num_axis; n++ )
    {
David Turner's avatar
David Turner committed
425
      T1_Token*  token = axis_tokens + n;
Werner Lemberg's avatar
   
Werner Lemberg committed
426
427
      FT_Byte*   name;
      FT_Int     len;
Werner Lemberg's avatar
   
Werner Lemberg committed
428

Werner Lemberg's avatar
   
Werner Lemberg committed
429
430
431
      /* skip first slash, if any */
      if (token->start[0] == '/')
        token->start++;
Werner Lemberg's avatar
   
Werner Lemberg committed
432

Werner Lemberg's avatar
   
Werner Lemberg committed
433
434
435
436
437
438
      len = token->limit - token->start;
      if ( len <= 0 )
      {
        error = T1_Err_Invalid_File_Format;
        goto Exit;
      }
Werner Lemberg's avatar
   
Werner Lemberg committed
439

Werner Lemberg's avatar
   
Werner Lemberg committed
440
441
      if ( ALLOC( blend->axis_names[n], len + 1 ) )
        goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
442

Werner Lemberg's avatar
   
Werner Lemberg committed
443
444
445
446
      name = (FT_Byte*)blend->axis_names[n];
      MEM_Copy( name, token->start, len );
      name[len] = 0;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
447
448

  Exit:
David Turner's avatar
David Turner committed
449
    loader->parser.root.error = error;
Werner Lemberg's avatar
   
Werner Lemberg committed
450
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
451
452


Werner Lemberg's avatar
   
Werner Lemberg committed
453
454
455
456
  static
  void  parse_blend_design_positions( T1_Face     face,
                                      Z1_Loader*  loader )
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
457
458
459
460
    T1_Token    design_tokens[ T1_MAX_MM_DESIGNS ];
    FT_Int      num_designs;
    FT_Int      num_axis;
    Z1_Parser*  parser = &loader->parser;
Werner Lemberg's avatar
   
Werner Lemberg committed
461

Werner Lemberg's avatar
   
Werner Lemberg committed
462
463
    FT_Error    error = 0;
    T1_Blend*   blend;
Werner Lemberg's avatar
   
Werner Lemberg committed
464

Werner Lemberg's avatar
   
Werner Lemberg committed
465
466

    /* get the array of design tokens - compute number of designs */
Werner Lemberg's avatar
   
Werner Lemberg committed
467
468
469
470
471
472
473
474
475
    Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
    if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
    {
      FT_ERROR(( "parse_blend_design_positions:" ));
      FT_ERROR(( " incorrect number of designs: %d\n",
                 num_designs ));
      error = T1_Err_Invalid_File_Format;
      goto Exit;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
476

Werner Lemberg's avatar
   
Werner Lemberg committed
477
    {
David Turner's avatar
David Turner committed
478
479
      FT_Byte*  old_cursor = parser->root.cursor;
      FT_Byte*  old_limit  = parser->root.limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
480
      FT_UInt   n;
Werner Lemberg's avatar
   
Werner Lemberg committed
481

Werner Lemberg's avatar
   
Werner Lemberg committed
482
483
484
485
486
487

      blend    = face->blend;
      num_axis = 0;  /* make compiler happy */

      for ( n = 0; n < (FT_UInt)num_designs; n++ )
      {
David Turner's avatar
David Turner committed
488
489
490
        T1_Token   axis_tokens[ T1_MAX_MM_DESIGNS ];
        T1_Token*  token;
        FT_Int     axis, n_axis;
Werner Lemberg's avatar
   
Werner Lemberg committed
491

Werner Lemberg's avatar
   
Werner Lemberg committed
492
493
494

        /* read axis/coordinates tokens */
        token = design_tokens + n;
David Turner's avatar
David Turner committed
495
496
        parser->root.cursor = token->start - 1;
        parser->root.limit  = token->limit + 1;
Werner Lemberg's avatar
   
Werner Lemberg committed
497
        Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
Werner Lemberg's avatar
   
Werner Lemberg committed
498

Werner Lemberg's avatar
   
Werner Lemberg committed
499
500
501
502
503
504
505
506
507
508
509
510
511
512
        if ( n == 0 )
        {
          num_axis = n_axis;
          error = t1_allocate_blend( face, num_designs, num_axis );
          if ( error )
            goto Exit;
          blend = face->blend;
        }
        else if ( n_axis != num_axis )
        {
          FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
          error = T1_Err_Invalid_File_Format;
          goto Exit;
        }
Werner Lemberg's avatar
   
Werner Lemberg committed
513

Werner Lemberg's avatar
   
Werner Lemberg committed
514
515
516
        /* now, read each axis token into the design position */
        for ( axis = 0; axis < n_axis; axis++ )
        {
David Turner's avatar
David Turner committed
517
          T1_Token*  token2 = axis_tokens + axis;
Werner Lemberg's avatar
   
Werner Lemberg committed
518
519


David Turner's avatar
David Turner committed
520
521
          parser->root.cursor = token2->start;
          parser->root.limit  = token2->limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
522
523
524
          blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 );
        }
      }
Werner Lemberg's avatar
   
Werner Lemberg committed
525

David Turner's avatar
David Turner committed
526
527
      loader->parser.root.cursor = old_cursor;
      loader->parser.root.limit  = old_limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
528
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
529

Werner Lemberg's avatar
   
Werner Lemberg committed
530
  Exit:
David Turner's avatar
David Turner committed
531
    loader->parser.root.error = error;
Werner Lemberg's avatar
   
Werner Lemberg committed
532
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
533

Werner Lemberg's avatar
   
Werner Lemberg committed
534
535
536
537
538

  static
  void  parse_blend_design_map( T1_Face     face,
                                Z1_Loader*  loader )
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
539
540
541
542
543
544
545
546
    FT_Error    error  = 0;
    Z1_Parser*  parser = &loader->parser;
    T1_Blend*   blend;
    T1_Token    axis_tokens[ T1_MAX_MM_AXIS ];
    FT_Int      n, num_axis;
    FT_Byte*    old_cursor;
    FT_Byte*    old_limit;
    FT_Memory   memory = face->root.memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
547

Werner Lemberg's avatar
   
Werner Lemberg committed
548
549
550
551
552
553
554
555
556

    Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
    {
      FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
                 num_axis ));
      error = T1_Err_Invalid_File_Format;
      goto Exit;
    }
David Turner's avatar
David Turner committed
557
558
    old_cursor = parser->root.cursor;
    old_limit  = parser->root.limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
559

Werner Lemberg's avatar
   
Werner Lemberg committed
560
561
562
563
    error = t1_allocate_blend( face, 0, num_axis );
    if ( error )
      goto Exit;
    blend = face->blend;
Werner Lemberg's avatar
   
Werner Lemberg committed
564

Werner Lemberg's avatar
   
Werner Lemberg committed
565
566
567
    /* now, read each axis design map */
    for ( n = 0; n < num_axis; n++ )
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
568
569
570
      T1_DesignMap* map = blend->design_map + n;
      T1_Token*     token;
      FT_Int        p, num_points;
Werner Lemberg's avatar
   
Werner Lemberg committed
571

Werner Lemberg's avatar
   
Werner Lemberg committed
572
573

      token = axis_tokens + n;
David Turner's avatar
David Turner committed
574
575
      parser->root.cursor = token->start;
      parser->root.limit  = token->limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
576

Werner Lemberg's avatar
   
Werner Lemberg committed
577
578
      /* count the number of map points */
      {
Werner Lemberg's avatar
   
Werner Lemberg committed
579
        FT_Byte*  ptr   = token->start;
Werner Lemberg's avatar
   
Werner Lemberg committed
580
        FT_Byte*  limit = token->limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
581

Werner Lemberg's avatar
   
Werner Lemberg committed
582
583

        num_points = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
584
585
        for ( ; ptr < limit; ptr++ )
          if ( ptr[0] == '[' )
Werner Lemberg's avatar
   
Werner Lemberg committed
586
587
588
589
590
591
592
593
            num_points++;
      }
      if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
      {
        FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
        error = T1_Err_Invalid_File_Format;
        goto Exit;
      }
Werner Lemberg's avatar
   
Werner Lemberg committed
594

Werner Lemberg's avatar
   
Werner Lemberg committed
595
596
597
598
599
      /* allocate design map data */
      if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) )
        goto Exit;
      map->blend_points = map->design_points + num_points;
      map->num_points   = (FT_Byte)num_points;
Werner Lemberg's avatar
   
Werner Lemberg committed
600

Werner Lemberg's avatar
   
Werner Lemberg committed
601
602
603
604
605
      for ( p = 0; p < num_points; p++ )
      {
        map->design_points[p] = Z1_ToInt( parser );
        map->blend_points [p] = Z1_ToFixed( parser, 0 );
      }
Werner Lemberg's avatar
   
Werner Lemberg committed
606
607
    }

David Turner's avatar
David Turner committed
608
609
    parser->root.cursor = old_cursor;
    parser->root.limit  = old_limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
610
611

  Exit:
David Turner's avatar
David Turner committed
612
    parser->root.error = error;
Werner Lemberg's avatar
   
Werner Lemberg committed
613
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
614

Werner Lemberg's avatar
   
Werner Lemberg committed
615
616
617
618
619

  static
  void  parse_weight_vector( T1_Face     face,
                             Z1_Loader*  loader )
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
620
621
622
623
624
625
626
    FT_Error    error  = 0;
    Z1_Parser*  parser = &loader->parser;
    T1_Blend*   blend  = face->blend;
    T1_Token    master;
    FT_UInt     n;
    FT_Byte*    old_cursor;
    FT_Byte*    old_limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
627

Werner Lemberg's avatar
   
Werner Lemberg committed
628
629
630
631
632
633
634

    if ( !blend || blend->num_designs == 0 )
    {
      FT_ERROR(( "parse_weight_vector: too early!\n" ));
      error = T1_Err_Invalid_File_Format;
      goto Exit;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
635

Werner Lemberg's avatar
   
Werner Lemberg committed
636
    Z1_ToToken( parser, &master );
David Turner's avatar
David Turner committed
637
    if ( master.type != t1_token_array )
Werner Lemberg's avatar
   
Werner Lemberg committed
638
639
640
641
642
    {
      FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
      error = T1_Err_Invalid_File_Format;
      goto Exit;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
643

David Turner's avatar
David Turner committed
644
645
    old_cursor = parser->root.cursor;
    old_limit  = parser->root.limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
646

David Turner's avatar
David Turner committed
647
648
    parser->root.cursor = master.start;
    parser->root.limit  = master.limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
649
650
651
652
653
654

    for ( n = 0; n < blend->num_designs; n++ )
    {
      blend->default_weight_vector[n] =
      blend->weight_vector[n]         = Z1_ToFixed( parser, 0 );
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
655

David Turner's avatar
David Turner committed
656
657
    parser->root.cursor = old_cursor;
    parser->root.limit  = old_limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
658
659

  Exit:
David Turner's avatar
David Turner committed
660
    parser->root.error = error;
Werner Lemberg's avatar
   
Werner Lemberg committed
661
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
662

Werner Lemberg's avatar
   
Werner Lemberg committed
663
664
665
666
667
668
669
670
671
672

  /* the keyword `/shareddict' appears in some multiple master fonts   */
  /* with a lot of Postscript garbage behind it (that's completely out */
  /* of spec!); we detect it and terminate the parsing                 */
  /*                                                                   */
  static
  void  parse_shared_dict( T1_Face     face,
                           Z1_Loader*  loader )
  {
    Z1_Parser*  parser = &loader->parser;
Werner Lemberg's avatar
   
Werner Lemberg committed
673

Werner Lemberg's avatar
   
Werner Lemberg committed
674
    FT_UNUSED( face );
Werner Lemberg's avatar
   
Werner Lemberg committed
675

Werner Lemberg's avatar
   
Werner Lemberg committed
676

David Turner's avatar
David Turner committed
677
678
    parser->root.cursor = parser->root.limit;
    parser->root.error  = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
679
680
681
682
  }

#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */

Werner Lemberg's avatar
   
Werner Lemberg committed
683

Werner Lemberg's avatar
   
Werner Lemberg committed
684
685
686
687
688
689
690
691
692
693
694
695
  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                      TYPE 1 SYMBOL PARSING                    *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/


  /*************************************************************************/
  /*                                                                       */
  /* First of all, define the token field static variables.  This is a set */
Werner Lemberg's avatar
   
Werner Lemberg committed
696
  /* of T1_Field variables used later.                                     */
Werner Lemberg's avatar
   
Werner Lemberg committed
697
698
699
  /*                                                                       */
  /*************************************************************************/

700

Werner Lemberg's avatar
   
Werner Lemberg committed
701
  static
702
703
704
  FT_Error  t1_load_keyword( T1_Face     face,
                             Z1_Loader*  loader,
                             T1_Field*   field )
705
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
706
707
708
709
710
    FT_Error   error;
    void*      dummy_object;
    void**     objects;
    FT_UInt    max_objects;
    T1_Blend*  blend = face->blend;
Werner Lemberg's avatar
   
Werner Lemberg committed
711

Werner Lemberg's avatar
   
Werner Lemberg committed
712

713
    /* if the keyword has a dedicated callback, call it */
714
    if ( field->type == t1_field_callback )
715
    {
716
      field->reader( (FT_Face)face, loader );
David Turner's avatar
David Turner committed
717
      error = loader->parser.root.error;
718
719
      goto Exit;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
720

Werner Lemberg's avatar
   
Werner Lemberg committed
721
722
    /* now, the keyword is either a simple field, or a table of fields; */
    /* we are now going to take care of it                              */
723
    switch ( field->location )
724
    {
725
    case t1_field_font_info:
Werner Lemberg's avatar
   
Werner Lemberg committed
726
727
728
729
730
731
732
733
734
735
      dummy_object = &face->type1.font_info;
      objects      = &dummy_object;
      max_objects  = 0;

      if ( blend )
      {
        objects     = (void**)blend->font_infos;
        max_objects = blend->num_designs;
      }
      break;
Werner Lemberg's avatar
   
Werner Lemberg committed
736

737
    case t1_field_private:
Werner Lemberg's avatar
   
Werner Lemberg committed
738
739
740
741
742
743
744
745
746
747
      dummy_object = &face->type1.private_dict;
      objects      = &dummy_object;
      max_objects  = 0;

      if ( blend )
      {
        objects     = (void**)blend->privates;
        max_objects = blend->num_designs;
      }
      break;
Werner Lemberg's avatar
   
Werner Lemberg committed
748

Werner Lemberg's avatar
   
Werner Lemberg committed
749
750
751
752
    default:
      dummy_object = &face->type1;
      objects      = &dummy_object;
      max_objects  = 0;
753
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
754

755
756
757
    if ( field->type == t1_field_integer_array ||
         field->type == t1_field_fixed_array   )
      error = Z1_Load_Field_Table( &loader->parser, field,
Werner Lemberg's avatar
   
Werner Lemberg committed
758
                                   objects, max_objects, 0 );
759
    else
760
      error = Z1_Load_Field( &loader->parser, field,
Werner Lemberg's avatar
   
Werner Lemberg committed
761
                             objects, max_objects, 0 );
Werner Lemberg's avatar
   
Werner Lemberg committed
762

763
764
  Exit:
    return error;
Werner Lemberg's avatar
   
Werner Lemberg committed
765
  }
766
767
768


  static
David Turner's avatar
David Turner committed
769
  int  is_space( FT_Byte  c )
770
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
771
    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
772
773
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
774

775
  static
David Turner's avatar
David Turner committed
776
  int  is_alpha( FT_Byte  c )
777
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
778
    return ( isalnum( c ) || c == '.' || c == '_' );
779
780
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
781
782


783
  static
Werner Lemberg's avatar
   
Werner Lemberg committed
784
785
786
  int  read_binary_data( Z1_Parser*  parser,
                         FT_Int*     size,
                         FT_Byte**   base )
787
  {
788
    FT_Byte*  cur;
David Turner's avatar
David Turner committed
789
    FT_Byte*  limit = parser->root.limit;
790

Werner Lemberg's avatar
   
Werner Lemberg committed
791

792
793
    /* the binary data has the following format */
    /*                                          */
Werner Lemberg's avatar
   
Werner Lemberg committed
794
    /* `size' [white*] RD white ....... ND      */
795
    /*                                          */
796

David Turner's avatar
David Turner committed
797
798
    Z1_Skip_Spaces( parser );
    cur = parser->root.cursor;
799

Werner Lemberg's avatar
   
Werner Lemberg committed
800
    if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
801
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
802
      *size = Z1_ToInt( parser );
803

David Turner's avatar
David Turner committed
804
805
      Z1_Skip_Spaces( parser );
      Z1_Skip_Alpha ( parser );  /* `RD' or `-|' or something else */
806

807
      /* there is only one whitespace char after the */
Werner Lemberg's avatar
   
Werner Lemberg committed
808
      /* `RD' or `-|' token                          */
David Turner's avatar
David Turner committed
809
      *base = parser->root.cursor + 1;
810

Werner Lemberg's avatar
   
Werner Lemberg committed
811
      parser->root.cursor += *size + 1;
812
813
814
      return 1;
    }

Werner Lemberg's avatar
   
Werner Lemberg committed
815
    FT_ERROR(( "read_binary_data: invalid size field\n" ));
David Turner's avatar
David Turner committed
816
    parser->root.error = T1_Err_Invalid_File_Format;
817
818
819
820
821
    return 0;
  }


  /* we will now define the routines used to handle */
Werner Lemberg's avatar
   
Werner Lemberg committed
822
823
  /* the `/Encoding', `/Subrs', and `/CharStrings'  */
  /* dictionaries                                   */
824
825

  static
Werner Lemberg's avatar
   
Werner Lemberg committed
826
827
  void  parse_font_name( T1_Face     face,
                         Z1_Loader*  loader )
828
  {
829
    Z1_Parser*  parser = &loader->parser;
830
    FT_Error    error;
David Turner's avatar
David Turner committed
831
    FT_Memory   memory = parser->root.memory;
832
833
834
835
    FT_Int      len;
    FT_Byte*    cur;
    FT_Byte*    cur2;
    FT_Byte*    limit;
836

Werner Lemberg's avatar
   
Werner Lemberg committed
837

David Turner's avatar
David Turner committed
838
    Z1_Skip_Spaces( parser );
Werner Lemberg's avatar
   
Werner Lemberg committed
839

David Turner's avatar
David Turner committed
840
841
    cur   = parser->root.cursor;
    limit = parser->root.limit;
Werner Lemberg's avatar
   
Werner Lemberg committed
842
843
844

    if ( cur >= limit - 1 || *cur != '/' )
      return;
845

846
847
    cur++;
    cur2 = cur;
Werner Lemberg's avatar
   
Werner Lemberg committed
848
849
850
851
852
    while ( cur2 < limit && is_alpha( *cur2 ) )
      cur2++;

    len = cur2 - cur;
    if ( len > 0 )
853
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
854
      if ( ALLOC( face->type1.font_name, len + 1 ) )
855
      {
David Turner's avatar
David Turner committed
856
        parser->root.error = error;
857
858
        return;
      }
859

860
861
862
      MEM_Copy( face->type1.font_name, cur, len );
      face->type1.font_name[len] = '\0';
    }
David Turner's avatar
David Turner committed
863
    parser->root.cursor = cur2;
864
865
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
866

867
  static
Werner Lemberg's avatar
   
Werner Lemberg committed
868
869
  void  parse_font_bbox( T1_Face     face,
                         Z1_Loader*  loader )
870
  {
871
    Z1_Parser*  parser = &loader->parser;
872
    FT_Short    temp[4];
Werner Lemberg's avatar
   
Werner Lemberg committed
873
874
    FT_BBox*    bbox   = &face->type1.font_bbox;

875

876
    (void)Z1_ToCoordArray( parser, 4, temp );
877
878
879
880
881
882
    bbox->xMin = temp[0];
    bbox->yMin = temp[1];
    bbox->xMax = temp[2];
    bbox->yMax = temp[3];
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
883

884
  static
Werner Lemberg's avatar
   
Werner Lemberg committed
885
886
  void  parse_font_matrix( T1_Face     face,
                           Z1_Loader*  loader )
887
  {
888
    Z1_Parser*  parser = &loader->parser;
889
    FT_Matrix*  matrix = &face->type1.font_matrix;
David Turner's avatar
David Turner committed
890
891
    FT_Vector*  offset = &face->type1.font_offset;
    FT_Fixed    temp[6];
892

Werner Lemberg's avatar
   
Werner Lemberg committed
893

894
895
896
897
    if ( matrix->xx || matrix->yx )
      /*  with synthetic fonts, it's possible we get here twice  */
      return;

David Turner's avatar
David Turner committed
898
899
900
    (void)Z1_ToFixedArray( parser, 6, temp, 3 );

    /* we need to scale the values by 1.0/temp[3] */
Werner Lemberg's avatar
   
Werner Lemberg committed
901
    if ( temp[3] != 0x10000L )
David Turner's avatar
David Turner committed
902
903
904
905
906
907
    {
      temp[0] = FT_DivFix( temp[0], temp[3] );
      temp[1] = FT_DivFix( temp[1], temp[3] );
      temp[2] = FT_DivFix( temp[2], temp[3] );
      temp[4] = FT_DivFix( temp[4], temp[3] );
      temp[5] = FT_DivFix( temp[5], temp[3] );
Werner Lemberg's avatar
   
Werner Lemberg committed
908
      temp[3] = 0x10000L;
David Turner's avatar
David Turner committed
909
910
    }

911
912
913
914
    matrix->xx = temp[0];
    matrix->yx = temp[1];
    matrix->xy = temp[2];
    matrix->yy = temp[3];
David Turner's avatar
David Turner committed
915
    
Werner Lemberg's avatar
   
Werner Lemberg committed
916
    /* note that the offsets must be expressed in integer font units */
David Turner's avatar
David Turner committed
917
918
    offset->x  = temp[4] >> 16;
    offset->y  = temp[5] >> 16;
919
920
921
  }


922
  static
Werner Lemberg's avatar
   
Werner Lemberg committed
923
924
  void  parse_encoding( T1_Face     face,
                        Z1_Loader*  loader )
925
  {
926
    Z1_Parser*  parser = &loader->parser;
David Turner's avatar
David Turner committed
927
928
929
930
    FT_Byte*    cur   = parser->root.cursor;
    FT_Byte*    limit = parser->root.limit;
    
    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
931

Werner Lemberg's avatar
   
Werner Lemberg committed
932

933
    /* skip whitespace */
Werner Lemberg's avatar
   
Werner Lemberg committed
934
    while ( is_space( *cur ) )
935
936
    {
      cur++;
Werner Lemberg's avatar
   
Werner Lemberg committed
937
      if ( cur >= limit )
938
      {
Werner Lemberg's avatar
   
Werner Lemberg committed
939
        FT_ERROR(( "parse_encoding: out of bounds!\n" ));
David Turner's avatar
David Turner committed
940
        parser->root.error = T1_Err_Invalid_File_Format;
941
942
943
        return;
      }
    }
944

945
946
    /* if we have a number, then the encoding is an array, */
    /* and we must load it now                             */
Werner Lemberg's avatar
   
Werner Lemberg committed
947
    if ( (FT_Byte)( *cur - '0' ) < 10 )
948
949
    {
      T1_Encoding*  encode     = &face->type1.encoding;
950
      FT_Int        count, n;
David Turner's avatar
David Turner committed
951
952
      PS_Table*     char_table = &loader->encoding_table;
      FT_Memory     memory     = parser->root.memory;
953
      FT_Error      error;
954

Werner Lemberg's avatar
   
Werner Lemberg committed
955

956
      /* read the number of entries in the encoding, should be 256 */
957
      count = Z1_ToInt( parser );
David Turner's avatar
David Turner committed
958
      if ( parser->root.error )
Werner Lemberg's avatar
   
Werner Lemberg committed
959
        return;
960

961
      /* we use a Z1_Table to store our charnames */
962
      encode->num_chars = count;
Werner Lemberg's avatar
   
Werner Lemberg committed
963
964
965
966
      if ( ALLOC_ARRAY( encode->char_index, count, FT_Short   ) ||
           ALLOC_ARRAY( encode->char_name,  count, FT_String* ) ||
           ( error = psaux->ps_table_funcs->init(
                       char_table, count, memory ) ) != 0       )
967
      {
David Turner's avatar
David Turner committed
968
        parser->root.error = error;
969
970
        return;
      }
971

Werner Lemberg's avatar
   
Werner Lemberg committed
972
      /* Now, we will need to read a record of the form         */
973
974
      /* ... charcode /charname ... for each entry in our table */
      /*                                                        */
Werner Lemberg's avatar
   
Werner Lemberg committed
975
976
977
      /* We simply look for a number followed by an immediate   */
      /* name.  Note that this ignores correctly the sequence   */
      /* that is often seen in type1 fonts:                     */
978
979
980
      /*                                                        */
      /*   0 1 255 { 1 index exch /.notdef put } for dup        */
      /*                                                        */
Werner Lemberg's avatar
   
Werner Lemberg committed
981
      /* used to clean the encoding array before anything else. */
982
      /*                                                        */
Werner Lemberg's avatar
   
Werner Lemberg committed
983
      /* We stop when we encounter a `def'.                     */
984

David Turner's avatar
David Turner committed
985
986
      cur   = parser->root.cursor;
      limit = parser->root.limit;
987
988
989
990
      n     = 0;

      for ( ; cur < limit; )
      {
991
        FT_Byte  c;
992

Werner Lemberg's avatar
   
Werner Lemberg committed
993

994
        c = *cur;
995

Werner Lemberg's avatar
   
Werner Lemberg committed
996
997
        /* we stop when we encounter a `def' */
        if ( c == 'd' && cur + 3 < limit )
998
999
1000
        {
          if ( cur[1] == 'e' &&
               cur[2] == 'f' &&