~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/extras/freetype2/src/cff/cffgload.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  cffgload.c                                                             */
 
4
/*                                                                         */
 
5
/*    OpenType Glyph Loader (body).                                        */
 
6
/*                                                                         */
 
7
/*  Copyright 1996-2001, 2002 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
#include <ft2build.h>
 
20
#include FT_INTERNAL_DEBUG_H
 
21
#include FT_INTERNAL_CALC_H
 
22
#include FT_INTERNAL_STREAM_H
 
23
#include FT_INTERNAL_SFNT_H
 
24
#include FT_OUTLINE_H
 
25
#include FT_TRUETYPE_TAGS_H
 
26
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
 
27
 
 
28
#include "cffobjs.h"
 
29
#include "cffload.h"
 
30
#include "cffgload.h"
 
31
 
 
32
#include "cfferrs.h"
 
33
 
 
34
 
 
35
  /*************************************************************************/
 
36
  /*                                                                       */
 
37
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 
38
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 
39
  /* messages during execution.                                            */
 
40
  /*                                                                       */
 
41
#undef  FT_COMPONENT
 
42
#define FT_COMPONENT  trace_cffgload
 
43
 
 
44
 
 
45
  typedef enum  CFF_Operator_
 
46
  {
 
47
    cff_op_unknown = 0,
 
48
 
 
49
    cff_op_rmoveto,
 
50
    cff_op_hmoveto,
 
51
    cff_op_vmoveto,
 
52
 
 
53
    cff_op_rlineto,
 
54
    cff_op_hlineto,
 
55
    cff_op_vlineto,
 
56
 
 
57
    cff_op_rrcurveto,
 
58
    cff_op_hhcurveto,
 
59
    cff_op_hvcurveto,
 
60
    cff_op_rcurveline,
 
61
    cff_op_rlinecurve,
 
62
    cff_op_vhcurveto,
 
63
    cff_op_vvcurveto,
 
64
 
 
65
    cff_op_flex,
 
66
    cff_op_hflex,
 
67
    cff_op_hflex1,
 
68
    cff_op_flex1,
 
69
 
 
70
    cff_op_endchar,
 
71
 
 
72
    cff_op_hstem,
 
73
    cff_op_vstem,
 
74
    cff_op_hstemhm,
 
75
    cff_op_vstemhm,
 
76
 
 
77
    cff_op_hintmask,
 
78
    cff_op_cntrmask,
 
79
    cff_op_dotsection,  /* deprecated, acts as no-op */
 
80
 
 
81
    cff_op_abs,
 
82
    cff_op_add,
 
83
    cff_op_sub,
 
84
    cff_op_div,
 
85
    cff_op_neg,
 
86
    cff_op_random,
 
87
    cff_op_mul,
 
88
    cff_op_sqrt,
 
89
 
 
90
    cff_op_blend,
 
91
 
 
92
    cff_op_drop,
 
93
    cff_op_exch,
 
94
    cff_op_index,
 
95
    cff_op_roll,
 
96
    cff_op_dup,
 
97
 
 
98
    cff_op_put,
 
99
    cff_op_get,
 
100
    cff_op_store,
 
101
    cff_op_load,
 
102
 
 
103
    cff_op_and,
 
104
    cff_op_or,
 
105
    cff_op_not,
 
106
    cff_op_eq,
 
107
    cff_op_ifelse,
 
108
 
 
109
    cff_op_callsubr,
 
110
    cff_op_callgsubr,
 
111
    cff_op_return,
 
112
 
 
113
    /* do not remove */
 
114
    cff_op_max
 
115
 
 
116
  } CFF_Operator;
 
117
 
 
118
 
 
119
#define CFF_COUNT_CHECK_WIDTH  0x80
 
120
#define CFF_COUNT_EXACT        0x40
 
121
#define CFF_COUNT_CLEAR_STACK  0x20
 
122
 
 
123
 
 
124
  static const FT_Byte  cff_argument_counts[] =
 
125
  {
 
126
    0,  /* unknown */
 
127
 
 
128
    2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
 
129
    1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
 
130
    1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
 
131
 
 
132
    0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
 
133
    0 | CFF_COUNT_CLEAR_STACK,
 
134
    0 | CFF_COUNT_CLEAR_STACK,
 
135
 
 
136
    0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
 
137
    0 | CFF_COUNT_CLEAR_STACK,
 
138
    0 | CFF_COUNT_CLEAR_STACK,
 
139
    0 | CFF_COUNT_CLEAR_STACK,
 
140
    0 | CFF_COUNT_CLEAR_STACK,
 
141
    0 | CFF_COUNT_CLEAR_STACK,
 
142
    0 | CFF_COUNT_CLEAR_STACK,
 
143
 
 
144
    13, /* flex */
 
145
    7,
 
146
    9,
 
147
    11,
 
148
 
 
149
    0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
 
150
 
 
151
    2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
 
152
    2 | CFF_COUNT_CHECK_WIDTH,
 
153
    2 | CFF_COUNT_CHECK_WIDTH,
 
154
    2 | CFF_COUNT_CHECK_WIDTH,
 
155
 
 
156
    0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
 
157
    0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
 
158
    0, /* dotsection */
 
159
 
 
160
    1, /* abs */
 
161
    2,
 
162
    2,
 
163
    2,
 
164
    1,
 
165
    0,
 
166
    2,
 
167
    1,
 
168
 
 
169
    1, /* blend */
 
170
 
 
171
    1, /* drop */
 
172
    2,
 
173
    1,
 
174
    2,
 
175
    1,
 
176
 
 
177
    2, /* put */
 
178
    1,
 
179
    4,
 
180
    3,
 
181
 
 
182
    2, /* and */
 
183
    2,
 
184
    1,
 
185
    2,
 
186
    4,
 
187
 
 
188
    1, /* callsubr */
 
189
    1,
 
190
    0
 
191
  };
 
192
 
 
193
 
 
194
  /*************************************************************************/
 
195
  /*************************************************************************/
 
196
  /*************************************************************************/
 
197
  /**********                                                      *********/
 
198
  /**********                                                      *********/
 
199
  /**********             GENERIC CHARSTRING PARSING               *********/
 
200
  /**********                                                      *********/
 
201
  /**********                                                      *********/
 
202
  /*************************************************************************/
 
203
  /*************************************************************************/
 
204
  /*************************************************************************/
 
205
 
 
206
 
 
207
  /*************************************************************************/
 
208
  /*                                                                       */
 
209
  /* <Function>                                                            */
 
210
  /*    CFF_Builder_Init                                                   */
 
211
  /*                                                                       */
 
212
  /* <Description>                                                         */
 
213
  /*    Initializes a given glyph builder.                                 */
 
214
  /*                                                                       */
 
215
  /* <InOut>                                                               */
 
216
  /*    builder :: A pointer to the glyph builder to initialize.           */
 
217
  /*                                                                       */
 
218
  /* <Input>                                                               */
 
219
  /*    face    :: The current face object.                                */
 
220
  /*                                                                       */
 
221
  /*    size    :: The current size object.                                */
 
222
  /*                                                                       */
 
223
  /*    glyph   :: The current glyph object.                               */
 
224
  /*                                                                       */
 
225
  static void
 
226
  CFF_Builder_Init( CFF_Builder*   builder,
 
227
                    TT_Face        face,
 
228
                    CFF_Size       size,
 
229
                    CFF_GlyphSlot  glyph,
 
230
                    FT_Bool        hinting )
 
231
  {
 
232
    builder->path_begun  = 0;
 
233
    builder->load_points = 1;
 
234
 
 
235
    builder->face   = face;
 
236
    builder->glyph  = glyph;
 
237
    builder->memory = face->root.memory;
 
238
 
 
239
    if ( glyph )
 
240
    {
 
241
      FT_GlyphLoader  loader = glyph->root.internal->loader;
 
242
 
 
243
 
 
244
      builder->loader  = loader;
 
245
      builder->base    = &loader->base.outline;
 
246
      builder->current = &loader->current.outline;
 
247
      FT_GlyphLoader_Rewind( loader );
 
248
 
 
249
      builder->hints_globals = 0;
 
250
      builder->hints_funcs   = 0;
 
251
 
 
252
      if ( hinting && size )
 
253
      {
 
254
        builder->hints_globals = size->internal;
 
255
        builder->hints_funcs   = glyph->root.internal->glyph_hints;
 
256
      }
 
257
    }
 
258
 
 
259
    if ( size )
 
260
    {
 
261
      builder->scale_x = size->metrics.x_scale;
 
262
      builder->scale_y = size->metrics.y_scale;
 
263
    }
 
264
 
 
265
    builder->pos_x = 0;
 
266
    builder->pos_y = 0;
 
267
 
 
268
    builder->left_bearing.x = 0;
 
269
    builder->left_bearing.y = 0;
 
270
    builder->advance.x      = 0;
 
271
    builder->advance.y      = 0;
 
272
  }
 
273
 
 
274
 
 
275
  /*************************************************************************/
 
276
  /*                                                                       */
 
277
  /* <Function>                                                            */
 
278
  /*    CFF_Builder_Done                                                   */
 
279
  /*                                                                       */
 
280
  /* <Description>                                                         */
 
281
  /*    Finalizes a given glyph builder.  Its contents can still be used   */
 
282
  /*    after the call, but the function saves important information       */
 
283
  /*    within the corresponding glyph slot.                               */
 
284
  /*                                                                       */
 
285
  /* <Input>                                                               */
 
286
  /*    builder :: A pointer to the glyph builder to finalize.             */
 
287
  /*                                                                       */
 
288
  static void
 
289
  CFF_Builder_Done( CFF_Builder*  builder )
 
290
  {
 
291
    CFF_GlyphSlot  glyph = builder->glyph;
 
292
 
 
293
 
 
294
    if ( glyph )
 
295
      glyph->root.outline = *builder->base;
 
296
  }
 
297
 
 
298
 
 
299
  /*************************************************************************/
 
300
  /*                                                                       */
 
301
  /* <Function>                                                            */
 
302
  /*    cff_compute_bias                                                   */
 
303
  /*                                                                       */
 
304
  /* <Description>                                                         */
 
305
  /*    Computes the bias value in dependence of the number of glyph       */
 
306
  /*    subroutines.                                                       */
 
307
  /*                                                                       */
 
308
  /* <Input>                                                               */
 
309
  /*    num_subrs :: The number of glyph subroutines.                      */
 
310
  /*                                                                       */
 
311
  /* <Return>                                                              */
 
312
  /*    The bias value.                                                    */
 
313
  static FT_Int
 
314
  cff_compute_bias( FT_UInt  num_subrs )
 
315
  {
 
316
    FT_Int  result;
 
317
 
 
318
 
 
319
    if ( num_subrs < 1240 )
 
320
      result = 107;
 
321
    else if ( num_subrs < 33900U )
 
322
      result = 1131;
 
323
    else
 
324
      result = 32768U;
 
325
 
 
326
    return result;
 
327
  }
 
328
 
 
329
 
 
330
  /*************************************************************************/
 
331
  /*                                                                       */
 
332
  /* <Function>                                                            */
 
333
  /*    CFF_Init_Decoder                                                   */
 
334
  /*                                                                       */
 
335
  /* <Description>                                                         */
 
336
  /*    Initializes a given glyph decoder.                                 */
 
337
  /*                                                                       */
 
338
  /* <InOut>                                                               */
 
339
  /*    decoder :: A pointer to the glyph builder to initialize.           */
 
340
  /*                                                                       */
 
341
  /* <Input>                                                               */
 
342
  /*    face    :: The current face object.                                */
 
343
  /*                                                                       */
 
344
  /*    size    :: The current size object.                                */
 
345
  /*                                                                       */
 
346
  /*    slot    :: The current glyph object.                               */
 
347
  /*                                                                       */
 
348
  FT_LOCAL_DEF( void )
 
349
  CFF_Init_Decoder( CFF_Decoder*   decoder,
 
350
                    TT_Face        face,
 
351
                    CFF_Size       size,
 
352
                    CFF_GlyphSlot  slot,
 
353
                    FT_Bool        hinting )
 
354
  {
 
355
    CFF_Font  cff = (CFF_Font)face->extra.data;
 
356
 
 
357
 
 
358
    /* clear everything */
 
359
    FT_MEM_SET( decoder, 0, sizeof ( *decoder ) );
 
360
 
 
361
    /* initialize builder */
 
362
    CFF_Builder_Init( &decoder->builder, face, size, slot, hinting );
 
363
 
 
364
    /* initialize Type2 decoder */
 
365
    decoder->num_globals  = cff->num_global_subrs;
 
366
    decoder->globals      = cff->global_subrs;
 
367
    decoder->globals_bias = cff_compute_bias( decoder->num_globals );
 
368
  }
 
369
 
 
370
 
 
371
  /* this function is used to select the locals subrs array */
 
372
  FT_LOCAL_DEF( void )
 
373
  CFF_Prepare_Decoder( CFF_Decoder*  decoder,
 
374
                       FT_UInt       glyph_index )
 
375
  {
 
376
    CFF_Font     cff = (CFF_Font)decoder->builder.face->extra.data;
 
377
    CFF_SubFont  sub = &cff->top_font;
 
378
 
 
379
 
 
380
    /* manage CID fonts */
 
381
    if ( cff->num_subfonts >= 1 )
 
382
    {
 
383
      FT_Byte  fd_index = CFF_Get_FD( &cff->fd_select, glyph_index );
 
384
 
 
385
 
 
386
      sub = cff->subfonts[fd_index];
 
387
    }
 
388
 
 
389
    decoder->num_locals    = sub->num_local_subrs;
 
390
    decoder->locals        = sub->local_subrs;
 
391
    decoder->locals_bias   = cff_compute_bias( decoder->num_locals );
 
392
 
 
393
    decoder->glyph_width   = sub->private_dict.default_width;
 
394
    decoder->nominal_width = sub->private_dict.nominal_width;
 
395
  }
 
396
 
 
397
 
 
398
  /* check that there is enough room for `count' more points */
 
399
  static FT_Error
 
400
  check_points( CFF_Builder*  builder,
 
401
                FT_Int        count )
 
402
  {
 
403
    return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
 
404
  }
 
405
 
 
406
 
 
407
  /* add a new point, do not check space */
 
408
  static void
 
409
  add_point( CFF_Builder*  builder,
 
410
             FT_Pos        x,
 
411
             FT_Pos        y,
 
412
             FT_Byte       flag )
 
413
  {
 
414
    FT_Outline*  outline = builder->current;
 
415
 
 
416
 
 
417
    if ( builder->load_points )
 
418
    {
 
419
      FT_Vector*  point   = outline->points + outline->n_points;
 
420
      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
 
421
 
 
422
 
 
423
      point->x = x >> 16;
 
424
      point->y = y >> 16;
 
425
      *control = (FT_Byte)( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
 
426
 
 
427
      builder->last = *point;
 
428
    }
 
429
 
 
430
    outline->n_points++;
 
431
  }
 
432
 
 
433
 
 
434
  /* check space for a new on-curve point, then add it */
 
435
  static FT_Error
 
436
  add_point1( CFF_Builder*  builder,
 
437
              FT_Pos        x,
 
438
              FT_Pos        y )
 
439
  {
 
440
    FT_Error  error;
 
441
 
 
442
 
 
443
    error = check_points( builder, 1 );
 
444
    if ( !error )
 
445
      add_point( builder, x, y, 1 );
 
446
 
 
447
    return error;
 
448
  }
 
449
 
 
450
 
 
451
  /* check room for a new contour, then add it */
 
452
  static FT_Error
 
453
  add_contour( CFF_Builder*  builder )
 
454
  {
 
455
    FT_Outline*  outline = builder->current;
 
456
    FT_Error     error;
 
457
 
 
458
 
 
459
    if ( !builder->load_points )
 
460
    {
 
461
      outline->n_contours++;
 
462
      return CFF_Err_Ok;
 
463
    }
 
464
 
 
465
    error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
 
466
    if ( !error )
 
467
    {
 
468
      if ( outline->n_contours > 0 )
 
469
        outline->contours[outline->n_contours - 1] =
 
470
          (short)( outline->n_points - 1 );
 
471
 
 
472
      outline->n_contours++;
 
473
    }
 
474
 
 
475
    return error;
 
476
  }
 
477
 
 
478
 
 
479
  /* if a path was begun, add its first on-curve point */
 
480
  static FT_Error
 
481
  start_point( CFF_Builder*  builder,
 
482
               FT_Pos        x,
 
483
               FT_Pos        y )
 
484
  {
 
485
    FT_Error  error = 0;
 
486
 
 
487
 
 
488
    /* test whether we are building a new contour */
 
489
    if ( !builder->path_begun )
 
490
    {
 
491
      builder->path_begun = 1;
 
492
      error = add_contour( builder );
 
493
      if ( !error )
 
494
        error = add_point1( builder, x, y );
 
495
    }
 
496
 
 
497
    return error;
 
498
  }
 
499
 
 
500
 
 
501
  /* close the current contour */
 
502
  static void
 
503
  close_contour( CFF_Builder*  builder )
 
504
  {
 
505
    FT_Outline*  outline = builder->current;
 
506
 
 
507
 
 
508
    /* XXXX: We must not include the last point in the path if it */
 
509
    /*       is located on the first point.                       */
 
510
    if ( outline->n_points > 1 )
 
511
    {
 
512
      FT_Int      first   = 0;
 
513
      FT_Vector*  p1      = outline->points + first;
 
514
      FT_Vector*  p2      = outline->points + outline->n_points - 1;
 
515
      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
 
516
 
 
517
 
 
518
      if ( outline->n_contours > 1 )
 
519
      {
 
520
        first = outline->contours[outline->n_contours - 2] + 1;
 
521
        p1    = outline->points + first;
 
522
      }
 
523
 
 
524
      /* `delete' last point only if it coincides with the first    */
 
525
      /* point and if it is not a control point (which can happen). */
 
526
      if ( p1->x == p2->x && p1->y == p2->y )
 
527
        if ( *control == FT_Curve_Tag_On )
 
528
          outline->n_points--;
 
529
    }
 
530
 
 
531
    if ( outline->n_contours > 0 )
 
532
      outline->contours[outline->n_contours - 1] =
 
533
        (short)( outline->n_points - 1 );
 
534
  }
 
535
 
 
536
 
 
537
  static FT_Int
 
538
  cff_lookup_glyph_by_stdcharcode( CFF_Font  cff,
 
539
                                   FT_Int    charcode )
 
540
  {
 
541
    FT_UInt    n;
 
542
    FT_UShort  glyph_sid;
 
543
 
 
544
 
 
545
    /* check range of standard char code */
 
546
    if ( charcode < 0 || charcode > 255 )
 
547
      return -1;
 
548
 
 
549
    /* Get code to SID mapping from `cff_standard_encoding'. */
 
550
    glyph_sid = CFF_Get_Standard_Encoding( (FT_UInt)charcode );
 
551
 
 
552
    for ( n = 0; n < cff->num_glyphs; n++ )
 
553
    {
 
554
      if ( cff->charset.sids[n] == glyph_sid )
 
555
        return n;
 
556
    }
 
557
 
 
558
    return -1;
 
559
  }
 
560
 
 
561
 
 
562
  static FT_Error
 
563
  cff_operator_seac( CFF_Decoder*  decoder,
 
564
                     FT_Pos        adx,
 
565
                     FT_Pos        ady,
 
566
                     FT_Int        bchar,
 
567
                     FT_Int        achar )
 
568
  {
 
569
    FT_Error     error;
 
570
    FT_Int       bchar_index, achar_index, n_base_points;
 
571
    FT_Outline*  base = decoder->builder.base;
 
572
    TT_Face      face = decoder->builder.face;
 
573
    CFF_Font     cff  = (CFF_Font)(face->extra.data);
 
574
    FT_Vector    left_bearing, advance;
 
575
    FT_Byte*     charstring;
 
576
    FT_ULong     charstring_len;
 
577
 
 
578
 
 
579
    bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
 
580
    achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
 
581
 
 
582
    if ( bchar_index < 0 || achar_index < 0 )
 
583
    {
 
584
      FT_ERROR(( "cff_operator_seac:" ));
 
585
      FT_ERROR(( " invalid seac character code arguments\n" ));
 
586
      return CFF_Err_Syntax_Error;
 
587
    }
 
588
 
 
589
    /* If we are trying to load a composite glyph, do not load the */
 
590
    /* accent character and return the array of subglyphs.         */
 
591
    if ( decoder->builder.no_recurse )
 
592
    {
 
593
      FT_GlyphSlot    glyph  = (FT_GlyphSlot)decoder->builder.glyph;
 
594
      FT_GlyphLoader  loader = glyph->internal->loader;
 
595
      FT_SubGlyph     subg;
 
596
 
 
597
 
 
598
      /* reallocate subglyph array if necessary */
 
599
      error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
 
600
      if ( error )
 
601
        goto Exit;
 
602
 
 
603
      subg = loader->current.subglyphs;
 
604
 
 
605
      /* subglyph 0 = base character */
 
606
      subg->index = bchar_index;
 
607
      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
 
608
                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
 
609
      subg->arg1  = 0;
 
610
      subg->arg2  = 0;
 
611
      subg++;
 
612
 
 
613
      /* subglyph 1 = accent character */
 
614
      subg->index = achar_index;
 
615
      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
 
616
      subg->arg1  = adx;
 
617
      subg->arg2  = ady;
 
618
 
 
619
      /* set up remaining glyph fields */
 
620
      glyph->num_subglyphs = 2;
 
621
      glyph->subglyphs     = loader->base.subglyphs;
 
622
      glyph->format        = ft_glyph_format_composite;
 
623
 
 
624
      loader->current.num_subglyphs = 2;
 
625
    }
 
626
 
 
627
    /* First load `bchar' in builder */
 
628
    error = CFF_Access_Element( &cff->charstrings_index, bchar_index,
 
629
                                &charstring, &charstring_len );
 
630
    if ( !error )
 
631
    {
 
632
      error = CFF_Parse_CharStrings( decoder, charstring, charstring_len );
 
633
 
 
634
      if ( error )
 
635
        goto Exit;
 
636
 
 
637
      CFF_Forget_Element( &cff->charstrings_index, &charstring );
 
638
    }
 
639
 
 
640
    n_base_points = base->n_points;
 
641
 
 
642
    /* Save the left bearing and width of the base character */
 
643
    /* as they will be erased by the next load.              */
 
644
 
 
645
    left_bearing = decoder->builder.left_bearing;
 
646
    advance      = decoder->builder.advance;
 
647
 
 
648
    decoder->builder.left_bearing.x = 0;
 
649
    decoder->builder.left_bearing.y = 0;
 
650
 
 
651
    /* Now load `achar' on top of the base outline. */
 
652
    error = CFF_Access_Element( &cff->charstrings_index, achar_index,
 
653
                                &charstring, &charstring_len );
 
654
    if ( !error )
 
655
    {
 
656
      error = CFF_Parse_CharStrings( decoder, charstring, charstring_len );
 
657
 
 
658
      if ( error )
 
659
        goto Exit;
 
660
 
 
661
      CFF_Forget_Element( &cff->charstrings_index, &charstring );
 
662
    }
 
663
 
 
664
    /* Restore the left side bearing and advance width */
 
665
    /* of the base character.                          */
 
666
    decoder->builder.left_bearing = left_bearing;
 
667
    decoder->builder.advance      = advance;
 
668
 
 
669
    /* Finally, move the accent. */
 
670
    if ( decoder->builder.load_points )
 
671
    {
 
672
      FT_Outline  dummy;
 
673
 
 
674
 
 
675
      dummy.n_points = (short)( base->n_points - n_base_points );
 
676
      dummy.points   = base->points   + n_base_points;
 
677
 
 
678
      FT_Outline_Translate( &dummy, adx, ady );
 
679
    }
 
680
 
 
681
  Exit:
 
682
    return error;
 
683
  }
 
684
 
 
685
 
 
686
  /*************************************************************************/
 
687
  /*                                                                       */
 
688
  /* <Function>                                                            */
 
689
  /*    CFF_Parse_CharStrings                                              */
 
690
  /*                                                                       */
 
691
  /* <Description>                                                         */
 
692
  /*    Parses a given Type 2 charstrings program.                         */
 
693
  /*                                                                       */
 
694
  /* <InOut>                                                               */
 
695
  /*    decoder         :: The current Type 1 decoder.                     */
 
696
  /*                                                                       */
 
697
  /* <Input>                                                               */
 
698
  /*    charstring_base :: The base of the charstring stream.              */
 
699
  /*                                                                       */
 
700
  /*    charstring_len  :: The length in bytes of the charstring stream.   */
 
701
  /*                                                                       */
 
702
  /* <Return>                                                              */
 
703
  /*    FreeType error code.  0 means success.                             */
 
704
  /*                                                                       */
 
705
  FT_LOCAL_DEF( FT_Error )
 
706
  CFF_Parse_CharStrings( CFF_Decoder*  decoder,
 
707
                         FT_Byte*      charstring_base,
 
708
                         FT_Int        charstring_len )
 
709
  {
 
710
    FT_Error           error;
 
711
    CFF_Decoder_Zone*  zone;
 
712
    FT_Byte*           ip;
 
713
    FT_Byte*           limit;
 
714
    CFF_Builder*       builder = &decoder->builder;
 
715
    FT_Pos             x, y;
 
716
    FT_Fixed           seed;
 
717
    FT_Fixed*          stack;
 
718
 
 
719
    T2_Hints_Funcs     hinter;
 
720
 
 
721
 
 
722
    /* set default width */
 
723
    decoder->num_hints  = 0;
 
724
    decoder->read_width = 1;
 
725
 
 
726
    /* compute random seed from stack address of parameter */
 
727
    seed = (FT_Fixed)(char*)&seed           ^
 
728
           (FT_Fixed)(char*)&decoder        ^
 
729
           (FT_Fixed)(char*)&charstring_base;
 
730
    seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFF;
 
731
    if ( seed == 0 )
 
732
      seed = 0x7384;
 
733
 
 
734
    /* initialize the decoder */
 
735
    decoder->top  = decoder->stack;
 
736
    decoder->zone = decoder->zones;
 
737
    zone          = decoder->zones;
 
738
    stack         = decoder->top;
 
739
 
 
740
    hinter = (T2_Hints_Funcs) builder->hints_funcs;
 
741
 
 
742
    builder->path_begun = 0;
 
743
 
 
744
    zone->base           = charstring_base;
 
745
    limit = zone->limit  = charstring_base + charstring_len;
 
746
    ip    = zone->cursor = zone->base;
 
747
 
 
748
    error = CFF_Err_Ok;
 
749
 
 
750
    x = builder->pos_x;
 
751
    y = builder->pos_y;
 
752
 
 
753
    /* begin hints recording session, if any */
 
754
    if ( hinter )
 
755
      hinter->open( hinter->hints );
 
756
 
 
757
    /* now, execute loop */
 
758
    while ( ip < limit )
 
759
    {
 
760
      CFF_Operator  op;
 
761
      FT_Byte       v;
 
762
 
 
763
 
 
764
      /********************************************************************/
 
765
      /*                                                                  */
 
766
      /* Decode operator or operand                                       */
 
767
      /*                                                                  */
 
768
      v = *ip++;
 
769
      if ( v >= 32 || v == 28 )
 
770
      {
 
771
        FT_Int    shift = 16;
 
772
        FT_Int32  val;
 
773
 
 
774
 
 
775
        /* this is an operand, push it on the stack */
 
776
        if ( v == 28 )
 
777
        {
 
778
          if ( ip + 1 >= limit )
 
779
            goto Syntax_Error;
 
780
          val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
 
781
          ip += 2;
 
782
        }
 
783
        else if ( v < 247 )
 
784
          val = (FT_Long)v - 139;
 
785
        else if ( v < 251 )
 
786
        {
 
787
          if ( ip >= limit )
 
788
            goto Syntax_Error;
 
789
          val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
 
790
        }
 
791
        else if ( v < 255 )
 
792
        {
 
793
          if ( ip >= limit )
 
794
            goto Syntax_Error;
 
795
          val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
 
796
        }
 
797
        else
 
798
        {
 
799
          if ( ip + 3 >= limit )
 
800
            goto Syntax_Error;
 
801
          val = ( (FT_Int32)ip[0] << 24 ) |
 
802
                ( (FT_Int32)ip[1] << 16 ) |
 
803
                ( (FT_Int32)ip[2] <<  8 ) |
 
804
                            ip[3];
 
805
          ip    += 4;
 
806
          shift  = 0;
 
807
        }
 
808
        if ( decoder->top - stack >= CFF_MAX_OPERANDS )
 
809
          goto Stack_Overflow;
 
810
 
 
811
        val           <<= shift;
 
812
        *decoder->top++ = val;
 
813
 
 
814
#ifdef FT_DEBUG_LEVEL_TRACE
 
815
        if ( !( val & 0xFFFF ) )
 
816
          FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) ));
 
817
        else
 
818
          FT_TRACE4(( " %.2f", val / 65536.0 ));
 
819
#endif
 
820
 
 
821
      }
 
822
      else
 
823
      {
 
824
        FT_Fixed*  args     = decoder->top;
 
825
        FT_Int     num_args = args - decoder->stack;
 
826
        FT_Int     req_args;
 
827
 
 
828
 
 
829
        /* find operator */
 
830
        op = cff_op_unknown;
 
831
 
 
832
        switch ( v )
 
833
        {
 
834
        case 1:
 
835
          op = cff_op_hstem;
 
836
          break;
 
837
        case 3:
 
838
          op = cff_op_vstem;
 
839
          break;
 
840
        case 4:
 
841
          op = cff_op_vmoveto;
 
842
          break;
 
843
        case 5:
 
844
          op = cff_op_rlineto;
 
845
          break;
 
846
        case 6:
 
847
          op = cff_op_hlineto;
 
848
          break;
 
849
        case 7:
 
850
          op = cff_op_vlineto;
 
851
          break;
 
852
        case 8:
 
853
          op = cff_op_rrcurveto;
 
854
          break;
 
855
        case 10:
 
856
          op = cff_op_callsubr;
 
857
          break;
 
858
        case 11:
 
859
          op = cff_op_return;
 
860
          break;
 
861
        case 12:
 
862
          {
 
863
            if ( ip >= limit )
 
864
              goto Syntax_Error;
 
865
            v = *ip++;
 
866
 
 
867
            switch ( v )
 
868
            {
 
869
            case 0:
 
870
              op = cff_op_dotsection;
 
871
              break;
 
872
            case 3:
 
873
              op = cff_op_and;
 
874
              break;
 
875
            case 4:
 
876
              op = cff_op_or;
 
877
              break;
 
878
            case 5:
 
879
              op = cff_op_not;
 
880
              break;
 
881
            case 8:
 
882
              op = cff_op_store;
 
883
              break;
 
884
            case 9:
 
885
              op = cff_op_abs;
 
886
              break;
 
887
            case 10:
 
888
              op = cff_op_add;
 
889
              break;
 
890
            case 11:
 
891
              op = cff_op_sub;
 
892
              break;
 
893
            case 12:
 
894
              op = cff_op_div;
 
895
              break;
 
896
            case 13:
 
897
              op = cff_op_load;
 
898
              break;
 
899
            case 14:
 
900
              op = cff_op_neg;
 
901
              break;
 
902
            case 15:
 
903
              op = cff_op_eq;
 
904
              break;
 
905
            case 18:
 
906
              op = cff_op_drop;
 
907
              break;
 
908
            case 20:
 
909
              op = cff_op_put;
 
910
              break;
 
911
            case 21:
 
912
              op = cff_op_get;
 
913
              break;
 
914
            case 22:
 
915
              op = cff_op_ifelse;
 
916
              break;
 
917
            case 23:
 
918
              op = cff_op_random;
 
919
              break;
 
920
            case 24:
 
921
              op = cff_op_mul;
 
922
              break;
 
923
            case 26:
 
924
              op = cff_op_sqrt;
 
925
              break;
 
926
            case 27:
 
927
              op = cff_op_dup;
 
928
              break;
 
929
            case 28:
 
930
              op = cff_op_exch;
 
931
              break;
 
932
            case 29:
 
933
              op = cff_op_index;
 
934
              break;
 
935
            case 30:
 
936
              op = cff_op_roll;
 
937
              break;
 
938
            case 34:
 
939
              op = cff_op_hflex;
 
940
              break;
 
941
            case 35:
 
942
              op = cff_op_flex;
 
943
              break;
 
944
            case 36:
 
945
              op = cff_op_hflex1;
 
946
              break;
 
947
            case 37:
 
948
              op = cff_op_flex1;
 
949
              break;
 
950
            default:
 
951
              /* decrement ip for syntax error message */
 
952
              ip--;
 
953
            }
 
954
          }
 
955
          break;
 
956
        case 14:
 
957
          op = cff_op_endchar;
 
958
          break;
 
959
        case 16:
 
960
          op = cff_op_blend;
 
961
          break;
 
962
        case 18:
 
963
          op = cff_op_hstemhm;
 
964
          break;
 
965
        case 19:
 
966
          op = cff_op_hintmask;
 
967
          break;
 
968
        case 20:
 
969
          op = cff_op_cntrmask;
 
970
          break;
 
971
        case 21:
 
972
          op = cff_op_rmoveto;
 
973
          break;
 
974
        case 22:
 
975
          op = cff_op_hmoveto;
 
976
          break;
 
977
        case 23:
 
978
          op = cff_op_vstemhm;
 
979
          break;
 
980
        case 24:
 
981
          op = cff_op_rcurveline;
 
982
          break;
 
983
        case 25:
 
984
          op = cff_op_rlinecurve;
 
985
          break;
 
986
        case 26:
 
987
          op = cff_op_vvcurveto;
 
988
          break;
 
989
        case 27:
 
990
          op = cff_op_hhcurveto;
 
991
          break;
 
992
        case 29:
 
993
          op = cff_op_callgsubr;
 
994
          break;
 
995
        case 30:
 
996
          op = cff_op_vhcurveto;
 
997
          break;
 
998
        case 31:
 
999
          op = cff_op_hvcurveto;
 
1000
          break;
 
1001
        default:
 
1002
          ;
 
1003
        }
 
1004
        if ( op == cff_op_unknown )
 
1005
          goto Syntax_Error;
 
1006
 
 
1007
        /* check arguments */
 
1008
        req_args = cff_argument_counts[op];
 
1009
        if ( req_args & CFF_COUNT_CHECK_WIDTH )
 
1010
        {
 
1011
          args = stack;
 
1012
 
 
1013
          if ( num_args > 0 && decoder->read_width )
 
1014
          {
 
1015
            /* If `nominal_width' is non-zero, the number is really a      */
 
1016
            /* difference against `nominal_width'.  Else, the number here  */
 
1017
            /* is truly a width, not a difference against `nominal_width'. */
 
1018
            /* If the font does not set `nominal_width', then              */
 
1019
            /* `nominal_width' defaults to zero, and so we can set         */
 
1020
            /* `glyph_width' to `nominal_width' plus number on the stack   */
 
1021
            /* -- for either case.                                         */
 
1022
 
 
1023
            FT_Int set_width_ok;
 
1024
 
 
1025
 
 
1026
            switch ( op )
 
1027
            {
 
1028
            case cff_op_hmoveto:
 
1029
            case cff_op_vmoveto:
 
1030
              set_width_ok = num_args & 2;
 
1031
              break;
 
1032
 
 
1033
            case cff_op_hstem:
 
1034
            case cff_op_vstem:
 
1035
            case cff_op_hstemhm:
 
1036
            case cff_op_vstemhm:
 
1037
            case cff_op_rmoveto:
 
1038
              set_width_ok = num_args & 1;
 
1039
              break;
 
1040
 
 
1041
            case cff_op_endchar:
 
1042
              /* If there is a width specified for endchar, we either have */
 
1043
              /* 1 argument or 5 arguments.  We like to argue.             */
 
1044
              set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) );
 
1045
              break;
 
1046
 
 
1047
            default:
 
1048
              set_width_ok = 0;
 
1049
              break;
 
1050
            }
 
1051
 
 
1052
            if ( set_width_ok )
 
1053
            {
 
1054
              decoder->glyph_width = decoder->nominal_width +
 
1055
                                       ( stack[0] >> 16 );
 
1056
 
 
1057
              /* Consumed an argument. */
 
1058
              num_args--;
 
1059
              args++;
 
1060
            }
 
1061
          }
 
1062
 
 
1063
          decoder->read_width = 0;
 
1064
          req_args            = 0;
 
1065
        }
 
1066
 
 
1067
        req_args &= 15;
 
1068
        if ( num_args < req_args )
 
1069
          goto Stack_Underflow;
 
1070
        args     -= req_args;
 
1071
        num_args -= req_args;
 
1072
 
 
1073
        switch ( op )
 
1074
        {
 
1075
        case cff_op_hstem:
 
1076
        case cff_op_vstem:
 
1077
        case cff_op_hstemhm:
 
1078
        case cff_op_vstemhm:
 
1079
          /* the number of arguments is always even here */
 
1080
          FT_TRACE4(( op == cff_op_hstem   ? " hstem"   :
 
1081
                    ( op == cff_op_vstem   ? " vstem"   :
 
1082
                    ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) ));
 
1083
 
 
1084
          if ( hinter )
 
1085
            hinter->stems( hinter->hints,
 
1086
                           ( op == cff_op_hstem || op == cff_op_hstemhm ),
 
1087
                           num_args / 2,
 
1088
                           args );
 
1089
 
 
1090
          decoder->num_hints += num_args / 2;
 
1091
          args = stack;
 
1092
          break;
 
1093
 
 
1094
        case cff_op_hintmask:
 
1095
        case cff_op_cntrmask:
 
1096
          FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
 
1097
 
 
1098
          /* implement vstem when needed --                        */
 
1099
          /* the specification doesn't say it, but this also works */
 
1100
          /* with the 'cntrmask' operator                          */
 
1101
          /*                                                       */
 
1102
          if ( num_args > 0 )
 
1103
          {
 
1104
            if ( hinter )
 
1105
              hinter->stems( hinter->hints,
 
1106
                             0,
 
1107
                             num_args / 2,
 
1108
                             args );
 
1109
 
 
1110
            decoder->num_hints += num_args / 2;
 
1111
          }
 
1112
 
 
1113
          if ( hinter )
 
1114
          {
 
1115
            if ( op == cff_op_hintmask )
 
1116
              hinter->hintmask( hinter->hints,
 
1117
                                builder->current->n_points,
 
1118
                                decoder->num_hints,
 
1119
                                ip );
 
1120
            else
 
1121
              hinter->counter( hinter->hints,
 
1122
                               decoder->num_hints,
 
1123
                               ip );
 
1124
          }
 
1125
 
 
1126
#ifdef FT_DEBUG_LEVEL_TRACE
 
1127
          {
 
1128
            FT_UInt maskbyte;
 
1129
 
 
1130
 
 
1131
            FT_TRACE4(( " " ));
 
1132
 
 
1133
            for ( maskbyte = 0;
 
1134
                  maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3);
 
1135
                  maskbyte++, ip++ )
 
1136
              FT_TRACE4(( "%02X", *ip ));
 
1137
          }
 
1138
#else
 
1139
          ip += ( decoder->num_hints + 7 ) >> 3;
 
1140
#endif
 
1141
          if ( ip >= limit )
 
1142
            goto Syntax_Error;
 
1143
          args = stack;
 
1144
          break;
 
1145
 
 
1146
        case cff_op_rmoveto:
 
1147
          FT_TRACE4(( " rmoveto" ));
 
1148
 
 
1149
          close_contour( builder );
 
1150
          builder->path_begun = 0;
 
1151
          x   += args[0];
 
1152
          y   += args[1];
 
1153
          args = stack;
 
1154
          break;
 
1155
 
 
1156
        case cff_op_vmoveto:
 
1157
          FT_TRACE4(( " vmoveto" ));
 
1158
 
 
1159
          close_contour( builder );
 
1160
          builder->path_begun = 0;
 
1161
          y   += args[0];
 
1162
          args = stack;
 
1163
          break;
 
1164
 
 
1165
        case cff_op_hmoveto:
 
1166
          FT_TRACE4(( " hmoveto" ));
 
1167
 
 
1168
          close_contour( builder );
 
1169
          builder->path_begun = 0;
 
1170
          x   += args[0];
 
1171
          args = stack;
 
1172
          break;
 
1173
 
 
1174
        case cff_op_rlineto:
 
1175
          FT_TRACE4(( " rlineto" ));
 
1176
 
 
1177
          if ( start_point ( builder, x, y )         ||
 
1178
               check_points( builder, num_args / 2 ) )
 
1179
            goto Memory_Error;
 
1180
 
 
1181
          if ( num_args < 2 || num_args & 1 )
 
1182
            goto Stack_Underflow;
 
1183
 
 
1184
          args = stack;
 
1185
          while ( args < decoder->top )
 
1186
          {
 
1187
            x += args[0];
 
1188
            y += args[1];
 
1189
            add_point( builder, x, y, 1 );
 
1190
            args += 2;
 
1191
          }
 
1192
          args = stack;
 
1193
          break;
 
1194
 
 
1195
        case cff_op_hlineto:
 
1196
        case cff_op_vlineto:
 
1197
          {
 
1198
            FT_Int  phase = ( op == cff_op_hlineto );
 
1199
 
 
1200
 
 
1201
            FT_TRACE4(( op == cff_op_hlineto ? " hlineto"
 
1202
                                             : " vlineto" ));
 
1203
 
 
1204
            if ( start_point ( builder, x, y )     ||
 
1205
                 check_points( builder, num_args ) )
 
1206
              goto Memory_Error;
 
1207
 
 
1208
            args = stack;
 
1209
            while (args < decoder->top )
 
1210
            {
 
1211
              if ( phase )
 
1212
                x += args[0];
 
1213
              else
 
1214
                y += args[0];
 
1215
 
 
1216
              if ( add_point1( builder, x, y ) )
 
1217
                goto Memory_Error;
 
1218
 
 
1219
              args++;
 
1220
              phase ^= 1;
 
1221
            }
 
1222
            args = stack;
 
1223
          }
 
1224
          break;
 
1225
 
 
1226
        case cff_op_rrcurveto:
 
1227
          FT_TRACE4(( " rrcurveto" ));
 
1228
 
 
1229
          /* check number of arguments; must be a multiple of 6 */
 
1230
          if ( num_args % 6 != 0 )
 
1231
            goto Stack_Underflow;
 
1232
 
 
1233
          if ( start_point ( builder, x, y )         ||
 
1234
               check_points( builder, num_args / 2 ) )
 
1235
            goto Memory_Error;
 
1236
 
 
1237
          args = stack;
 
1238
          while ( args < decoder->top )
 
1239
          {
 
1240
            x += args[0];
 
1241
            y += args[1];
 
1242
            add_point( builder, x, y, 0 );
 
1243
            x += args[2];
 
1244
            y += args[3];
 
1245
            add_point( builder, x, y, 0 );
 
1246
            x += args[4];
 
1247
            y += args[5];
 
1248
            add_point( builder, x, y, 1 );
 
1249
            args += 6;
 
1250
          }
 
1251
          args = stack;
 
1252
          break;
 
1253
 
 
1254
        case cff_op_vvcurveto:
 
1255
          FT_TRACE4(( " vvcurveto" ));
 
1256
 
 
1257
          if ( start_point ( builder, x, y ) )
 
1258
            goto Memory_Error;
 
1259
 
 
1260
          args = stack;
 
1261
          if ( num_args & 1 )
 
1262
          {
 
1263
            x += args[0];
 
1264
            args++;
 
1265
            num_args--;
 
1266
          }
 
1267
 
 
1268
          if ( num_args % 4 != 0 )
 
1269
            goto Stack_Underflow;
 
1270
 
 
1271
          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
 
1272
            goto Memory_Error;
 
1273
 
 
1274
          while ( args < decoder->top )
 
1275
          {
 
1276
            y += args[0];
 
1277
            add_point( builder, x, y, 0 );
 
1278
            x += args[1];
 
1279
            y += args[2];
 
1280
            add_point( builder, x, y, 0 );
 
1281
            y += args[3];
 
1282
            add_point( builder, x, y, 1 );
 
1283
            args += 4;
 
1284
          }
 
1285
          args = stack;
 
1286
          break;
 
1287
 
 
1288
        case cff_op_hhcurveto:
 
1289
          FT_TRACE4(( " hhcurveto" ));
 
1290
 
 
1291
          if ( start_point ( builder, x, y ) )
 
1292
            goto Memory_Error;
 
1293
 
 
1294
          args = stack;
 
1295
          if ( num_args & 1 )
 
1296
          {
 
1297
            y += args[0];
 
1298
            args++;
 
1299
            num_args--;
 
1300
          }
 
1301
 
 
1302
          if ( num_args % 4 != 0 )
 
1303
            goto Stack_Underflow;
 
1304
 
 
1305
          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
 
1306
            goto Memory_Error;
 
1307
 
 
1308
          while ( args < decoder->top )
 
1309
          {
 
1310
            x += args[0];
 
1311
            add_point( builder, x, y, 0 );
 
1312
            x += args[1];
 
1313
            y += args[2];
 
1314
            add_point( builder, x, y, 0 );
 
1315
            x += args[3];
 
1316
            add_point( builder, x, y, 1 );
 
1317
            args += 4;
 
1318
          }
 
1319
          args = stack;
 
1320
          break;
 
1321
 
 
1322
        case cff_op_vhcurveto:
 
1323
        case cff_op_hvcurveto:
 
1324
          {
 
1325
            FT_Int  phase;
 
1326
 
 
1327
 
 
1328
            FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto"
 
1329
                                               : " hvcurveto" ));
 
1330
 
 
1331
            if ( start_point ( builder, x, y ) )
 
1332
              goto Memory_Error;
 
1333
 
 
1334
            args = stack;
 
1335
            if (num_args < 4 || ( num_args % 4 ) > 1 )
 
1336
              goto Stack_Underflow;
 
1337
 
 
1338
            if ( check_points( builder, ( num_args / 4 ) * 3 ) )
 
1339
              goto Stack_Underflow;
 
1340
 
 
1341
            phase = ( op == cff_op_hvcurveto );
 
1342
 
 
1343
            while ( num_args >= 4 )
 
1344
            {
 
1345
              num_args -= 4;
 
1346
              if ( phase )
 
1347
              {
 
1348
                x += args[0];
 
1349
                add_point( builder, x, y, 0 );
 
1350
                x += args[1];
 
1351
                y += args[2];
 
1352
                add_point( builder, x, y, 0 );
 
1353
                y += args[3];
 
1354
                if ( num_args == 1 )
 
1355
                  x += args[4];
 
1356
                add_point( builder, x, y, 1 );
 
1357
              }
 
1358
              else
 
1359
              {
 
1360
                y += args[0];
 
1361
                add_point( builder, x, y, 0 );
 
1362
                x += args[1];
 
1363
                y += args[2];
 
1364
                add_point( builder, x, y, 0 );
 
1365
                x += args[3];
 
1366
                if ( num_args == 1 )
 
1367
                  y += args[4];
 
1368
                add_point( builder, x, y, 1 );
 
1369
              }
 
1370
              args  += 4;
 
1371
              phase ^= 1;
 
1372
            }
 
1373
            args = stack;
 
1374
          }
 
1375
          break;
 
1376
 
 
1377
        case cff_op_rlinecurve:
 
1378
          {
 
1379
            FT_Int  num_lines = ( num_args - 6 ) / 2;
 
1380
 
 
1381
 
 
1382
            FT_TRACE4(( " rlinecurve" ));
 
1383
 
 
1384
            if ( num_args < 8 || ( num_args - 6 ) & 1 )
 
1385
              goto Stack_Underflow;
 
1386
 
 
1387
            if ( start_point( builder, x, y )           ||
 
1388
                 check_points( builder, num_lines + 3 ) )
 
1389
              goto Memory_Error;
 
1390
 
 
1391
            args = stack;
 
1392
 
 
1393
            /* first, add the line segments */
 
1394
            while ( num_lines > 0 )
 
1395
            {
 
1396
              x += args[0];
 
1397
              y += args[1];
 
1398
              add_point( builder, x, y, 1 );
 
1399
              args += 2;
 
1400
              num_lines--;
 
1401
            }
 
1402
 
 
1403
            /* then the curve */
 
1404
            x += args[0];
 
1405
            y += args[1];
 
1406
            add_point( builder, x, y, 0 );
 
1407
            x += args[2];
 
1408
            y += args[3];
 
1409
            add_point( builder, x, y, 0 );
 
1410
            x += args[4];
 
1411
            y += args[5];
 
1412
            add_point( builder, x, y, 1 );
 
1413
            args = stack;
 
1414
          }
 
1415
          break;
 
1416
 
 
1417
        case cff_op_rcurveline:
 
1418
          {
 
1419
            FT_Int  num_curves = ( num_args - 2 ) / 6;
 
1420
 
 
1421
 
 
1422
            FT_TRACE4(( " rcurveline" ));
 
1423
 
 
1424
            if ( num_args < 8 || ( num_args - 2 ) % 6 )
 
1425
              goto Stack_Underflow;
 
1426
 
 
1427
            if ( start_point ( builder, x, y )             ||
 
1428
                 check_points( builder, num_curves*3 + 2 ) )
 
1429
              goto Memory_Error;
 
1430
 
 
1431
            args = stack;
 
1432
 
 
1433
            /* first, add the curves */
 
1434
            while ( num_curves > 0 )
 
1435
            {
 
1436
              x += args[0];
 
1437
              y += args[1];
 
1438
              add_point( builder, x, y, 0 );
 
1439
              x += args[2];
 
1440
              y += args[3];
 
1441
              add_point( builder, x, y, 0 );
 
1442
              x += args[4];
 
1443
              y += args[5];
 
1444
              add_point( builder, x, y, 1 );
 
1445
              args += 6;
 
1446
              num_curves--;
 
1447
            }
 
1448
 
 
1449
            /* then the final line */
 
1450
            x += args[0];
 
1451
            y += args[1];
 
1452
            add_point( builder, x, y, 1 );
 
1453
            args = stack;
 
1454
          }
 
1455
          break;
 
1456
 
 
1457
        case cff_op_hflex1:
 
1458
          {
 
1459
            FT_Pos start_y;
 
1460
 
 
1461
 
 
1462
            FT_TRACE4(( " hflex1" ));
 
1463
 
 
1464
            args = stack;
 
1465
 
 
1466
            /* adding five more points; 4 control points, 1 on-curve point */
 
1467
            /* make sure we have enough space for the start point if it    */
 
1468
            /* needs to be added..                                         */
 
1469
            if ( start_point( builder, x, y ) ||
 
1470
                 check_points( builder, 6 )   )
 
1471
              goto Memory_Error;
 
1472
 
 
1473
            /* Record the starting point's y postion for later use */
 
1474
            start_y = y;
 
1475
 
 
1476
            /* first control point */
 
1477
            x += args[0];
 
1478
            y += args[1];
 
1479
            add_point( builder, x, y, 0 );
 
1480
 
 
1481
            /* second control point */
 
1482
            x += args[2];
 
1483
            y += args[3];
 
1484
            add_point( builder, x, y, 0 );
 
1485
 
 
1486
            /* join point; on curve, with y-value the same as the last */
 
1487
            /* control point's y-value                                 */
 
1488
            x += args[4];
 
1489
            add_point( builder, x, y, 1 );
 
1490
 
 
1491
            /* third control point, with y-value the same as the join */
 
1492
            /* point's y-value                                        */
 
1493
            x += args[5];
 
1494
            add_point( builder, x, y, 0 );
 
1495
 
 
1496
            /* fourth control point */
 
1497
            x += args[6];
 
1498
            y += args[7];
 
1499
            add_point( builder, x, y, 0 );
 
1500
 
 
1501
            /* ending point, with y-value the same as the start   */
 
1502
            x += args[8];
 
1503
            y  = start_y;
 
1504
            add_point( builder, x, y, 1 );
 
1505
 
 
1506
            args = stack;
 
1507
            break;
 
1508
          }
 
1509
 
 
1510
        case cff_op_hflex:
 
1511
          {
 
1512
            FT_Pos start_y;
 
1513
 
 
1514
 
 
1515
            FT_TRACE4(( " hflex" ));
 
1516
 
 
1517
            args = stack;
 
1518
 
 
1519
            /* adding six more points; 4 control points, 2 on-curve points */
 
1520
            if ( start_point( builder, x, y ) ||
 
1521
                 check_points ( builder, 6 )  )
 
1522
              goto Memory_Error;
 
1523
 
 
1524
            /* record the starting point's y-position for later use */
 
1525
            start_y = y;
 
1526
 
 
1527
            /* first control point */
 
1528
            x += args[0];
 
1529
            add_point( builder, x, y, 0 );
 
1530
 
 
1531
            /* second control point */
 
1532
            x += args[1];
 
1533
            y += args[2];
 
1534
            add_point( builder, x, y, 0 );
 
1535
 
 
1536
            /* join point; on curve, with y-value the same as the last */
 
1537
            /* control point's y-value                                 */
 
1538
            x += args[3];
 
1539
            add_point( builder, x, y, 1 );
 
1540
 
 
1541
            /* third control point, with y-value the same as the join */
 
1542
            /* point's y-value                                        */
 
1543
            x += args[4];
 
1544
            add_point( builder, x, y, 0 );
 
1545
 
 
1546
            /* fourth control point */
 
1547
            x += args[5];
 
1548
            y  = start_y;
 
1549
            add_point( builder, x, y, 0 );
 
1550
 
 
1551
            /* ending point, with y-value the same as the start point's */
 
1552
            /* y-value -- we don't add this point, though               */
 
1553
            x += args[6];
 
1554
            add_point( builder, x, y, 1 );
 
1555
 
 
1556
            args = stack;
 
1557
            break;
 
1558
          }
 
1559
 
 
1560
        case cff_op_flex1:
 
1561
          {
 
1562
            FT_Pos  start_x, start_y; /* record start x, y values for alter */
 
1563
                                      /* use                                */
 
1564
            FT_Int  dx = 0, dy = 0;   /* used in horizontal/vertical        */
 
1565
                                      /* algorithm below                    */
 
1566
            FT_Int  horizontal, count;
 
1567
 
 
1568
 
 
1569
            FT_TRACE4(( " flex1" ));
 
1570
 
 
1571
            /* adding six more points; 4 control points, 2 on-curve points */
 
1572
            if ( start_point( builder, x, y ) ||
 
1573
                 check_points( builder, 6 )   )
 
1574
               goto Memory_Error;
 
1575
 
 
1576
            /* record the starting point's x, y postion for later use */
 
1577
            start_x = x;
 
1578
            start_y = y;
 
1579
 
 
1580
            /* XXX: figure out whether this is supposed to be a horizontal */
 
1581
            /*      or vertical flex; the Type 2 specification is vague... */
 
1582
 
 
1583
            args = stack;
 
1584
 
 
1585
            /* grab up to the last argument */
 
1586
            for ( count = 5; count > 0; count-- )
 
1587
            {
 
1588
              dx += args[0];
 
1589
              dy += args[1];
 
1590
              args += 2;
 
1591
            }
 
1592
 
 
1593
            /* rewind */
 
1594
            args = stack;
 
1595
 
 
1596
            if ( dx < 0 ) dx = -dx;
 
1597
            if ( dy < 0 ) dy = -dy;
 
1598
 
 
1599
            /* strange test, but here it is... */
 
1600
            horizontal = ( dx > dy );
 
1601
 
 
1602
            for ( count = 5; count > 0; count-- )
 
1603
            {
 
1604
              x += args[0];
 
1605
              y += args[1];
 
1606
              add_point( builder, x, y, (FT_Bool)( count == 3 ) );
 
1607
              args += 2;
 
1608
            }
 
1609
 
 
1610
            /* is last operand an x- or y-delta? */
 
1611
            if ( horizontal )
 
1612
            {
 
1613
              x += args[0];
 
1614
              y  = start_y;
 
1615
            }
 
1616
            else
 
1617
            {
 
1618
              x  = start_x;
 
1619
              y += args[0];
 
1620
            }
 
1621
 
 
1622
            add_point( builder, x, y, 1 );
 
1623
 
 
1624
            args = stack;
 
1625
            break;
 
1626
           }
 
1627
 
 
1628
        case cff_op_flex:
 
1629
          {
 
1630
            FT_UInt  count;
 
1631
 
 
1632
 
 
1633
            FT_TRACE4(( " flex" ));
 
1634
 
 
1635
            if ( start_point( builder, x, y ) ||
 
1636
                 check_points( builder, 6 )   )
 
1637
              goto Memory_Error;
 
1638
 
 
1639
            args = stack;
 
1640
            for ( count = 6; count > 0; count-- )
 
1641
            {
 
1642
              x += args[0];
 
1643
              y += args[1];
 
1644
              add_point( builder, x, y,
 
1645
                         (FT_Bool)( count == 3 || count == 0 ) );
 
1646
              args += 2;
 
1647
            }
 
1648
 
 
1649
            args = stack;
 
1650
          }
 
1651
          break;
 
1652
 
 
1653
        case cff_op_endchar:
 
1654
          FT_TRACE4(( " endchar" ));
 
1655
 
 
1656
          /* We are going to emulate the seac operator. */
 
1657
          if ( num_args == 4 )
 
1658
          {
 
1659
            error = cff_operator_seac( decoder,
 
1660
                                       args[0] >> 16, args[1] >> 16,
 
1661
                                       args[2] >> 16, args[3] >> 16 );
 
1662
            args += 4;
 
1663
          }
 
1664
 
 
1665
          if ( !error )
 
1666
            error = CFF_Err_Ok;
 
1667
 
 
1668
          close_contour( builder );
 
1669
 
 
1670
          /* close hints recording session */
 
1671
          if ( hinter )
 
1672
          {
 
1673
            if (hinter->close( hinter->hints, builder->current->n_points ) )
 
1674
              goto Syntax_Error;
 
1675
 
 
1676
            /* apply hints to the loaded glyph outline now */
 
1677
            hinter->apply( hinter->hints,
 
1678
                           builder->current,
 
1679
                           (PSH_Globals)builder->hints_globals );
 
1680
          }
 
1681
 
 
1682
          /* add current outline to the glyph slot */
 
1683
          FT_GlyphLoader_Add( builder->loader );
 
1684
 
 
1685
          /* return now! */
 
1686
          FT_TRACE4(( "\n\n" ));
 
1687
          return error;
 
1688
 
 
1689
        case cff_op_abs:
 
1690
          FT_TRACE4(( " abs" ));
 
1691
 
 
1692
          if ( args[0] < 0 )
 
1693
            args[0] = -args[0];
 
1694
          args++;
 
1695
          break;
 
1696
 
 
1697
        case cff_op_add:
 
1698
          FT_TRACE4(( " add" ));
 
1699
 
 
1700
          args[0] += args[1];
 
1701
          args++;
 
1702
          break;
 
1703
 
 
1704
        case cff_op_sub:
 
1705
          FT_TRACE4(( " sub" ));
 
1706
 
 
1707
          args[0] -= args[1];
 
1708
          args++;
 
1709
          break;
 
1710
 
 
1711
        case cff_op_div:
 
1712
          FT_TRACE4(( " div" ));
 
1713
 
 
1714
          args[0] = FT_DivFix( args[0], args[1] );
 
1715
          args++;
 
1716
          break;
 
1717
 
 
1718
        case cff_op_neg:
 
1719
          FT_TRACE4(( " neg" ));
 
1720
 
 
1721
          args[0] = -args[0];
 
1722
          args++;
 
1723
          break;
 
1724
 
 
1725
        case cff_op_random:
 
1726
          {
 
1727
            FT_Fixed  Rand;
 
1728
 
 
1729
 
 
1730
            FT_TRACE4(( " rand" ));
 
1731
 
 
1732
            Rand = seed;
 
1733
            if ( Rand >= 0x8000 )
 
1734
              Rand++;
 
1735
 
 
1736
            args[0] = Rand;
 
1737
            seed    = FT_MulFix( seed, 0x10000L - seed );
 
1738
            if ( seed == 0 )
 
1739
              seed += 0x2873;
 
1740
            args++;
 
1741
          }
 
1742
          break;
 
1743
 
 
1744
        case cff_op_mul:
 
1745
          FT_TRACE4(( " mul" ));
 
1746
 
 
1747
          args[0] = FT_MulFix( args[0], args[1] );
 
1748
          args++;
 
1749
          break;
 
1750
 
 
1751
        case cff_op_sqrt:
 
1752
          FT_TRACE4(( " sqrt" ));
 
1753
 
 
1754
          if ( args[0] > 0 )
 
1755
          {
 
1756
            FT_Int    count = 9;
 
1757
            FT_Fixed  root  = args[0];
 
1758
            FT_Fixed  new_root;
 
1759
 
 
1760
 
 
1761
            for (;;)
 
1762
            {
 
1763
              new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
 
1764
              if ( new_root == root || count <= 0 )
 
1765
                break;
 
1766
              root = new_root;
 
1767
            }
 
1768
            args[0] = new_root;
 
1769
          }
 
1770
          else
 
1771
            args[0] = 0;
 
1772
          args++;
 
1773
          break;
 
1774
 
 
1775
        case cff_op_drop:
 
1776
          /* nothing */
 
1777
          FT_TRACE4(( " drop" ));
 
1778
 
 
1779
          break;
 
1780
 
 
1781
        case cff_op_exch:
 
1782
          {
 
1783
            FT_Fixed  tmp;
 
1784
 
 
1785
 
 
1786
            FT_TRACE4(( " exch" ));
 
1787
 
 
1788
            tmp     = args[0];
 
1789
            args[0] = args[1];
 
1790
            args[1] = tmp;
 
1791
            args   += 2;
 
1792
          }
 
1793
          break;
 
1794
 
 
1795
        case cff_op_index:
 
1796
          {
 
1797
            FT_Int  idx = args[0] >> 16;
 
1798
 
 
1799
 
 
1800
            FT_TRACE4(( " index" ));
 
1801
 
 
1802
            if ( idx < 0 )
 
1803
              idx = 0;
 
1804
            else if ( idx > num_args - 2 )
 
1805
              idx = num_args - 2;
 
1806
            args[0] = args[-( idx + 1 )];
 
1807
            args++;
 
1808
          }
 
1809
          break;
 
1810
 
 
1811
        case cff_op_roll:
 
1812
          {
 
1813
            FT_Int  count = (FT_Int)( args[0] >> 16 );
 
1814
            FT_Int  idx   = (FT_Int)( args[1] >> 16 );
 
1815
 
 
1816
 
 
1817
            FT_TRACE4(( " roll" ));
 
1818
 
 
1819
            if ( count <= 0 )
 
1820
              count = 1;
 
1821
 
 
1822
            args -= count;
 
1823
            if ( args < stack )
 
1824
              goto Stack_Underflow;
 
1825
 
 
1826
            if ( idx >= 0 )
 
1827
            {
 
1828
              while ( idx > 0 )
 
1829
              {
 
1830
                FT_Fixed  tmp = args[count - 1];
 
1831
                FT_Int    i;
 
1832
 
 
1833
 
 
1834
                for ( i = count - 2; i >= 0; i-- )
 
1835
                  args[i + 1] = args[i];
 
1836
                args[0] = tmp;
 
1837
                idx--;
 
1838
              }
 
1839
            }
 
1840
            else
 
1841
            {
 
1842
              while ( idx < 0 )
 
1843
              {
 
1844
                FT_Fixed  tmp = args[0];
 
1845
                FT_Int    i;
 
1846
 
 
1847
 
 
1848
                for ( i = 0; i < count - 1; i++ )
 
1849
                  args[i] = args[i + 1];
 
1850
                args[count - 1] = tmp;
 
1851
                idx++;
 
1852
              }
 
1853
            }
 
1854
            args += count;
 
1855
          }
 
1856
          break;
 
1857
 
 
1858
        case cff_op_dup:
 
1859
          FT_TRACE4(( " dup" ));
 
1860
 
 
1861
          args[1] = args[0];
 
1862
          args++;
 
1863
          break;
 
1864
 
 
1865
        case cff_op_put:
 
1866
          {
 
1867
            FT_Fixed  val = args[0];
 
1868
            FT_Int    idx = (FT_Int)( args[1] >> 16 );
 
1869
 
 
1870
 
 
1871
            FT_TRACE4(( " put" ));
 
1872
 
 
1873
            if ( idx >= 0 && idx < decoder->len_buildchar )
 
1874
              decoder->buildchar[idx] = val;
 
1875
          }
 
1876
          break;
 
1877
 
 
1878
        case cff_op_get:
 
1879
          {
 
1880
            FT_Int    idx = (FT_Int)( args[0] >> 16 );
 
1881
            FT_Fixed  val = 0;
 
1882
 
 
1883
 
 
1884
            FT_TRACE4(( " get" ));
 
1885
 
 
1886
            if ( idx >= 0 && idx < decoder->len_buildchar )
 
1887
              val = decoder->buildchar[idx];
 
1888
 
 
1889
            args[0] = val;
 
1890
            args++;
 
1891
          }
 
1892
          break;
 
1893
 
 
1894
        case cff_op_store:
 
1895
          FT_TRACE4(( " store "));
 
1896
 
 
1897
          goto Unimplemented;
 
1898
 
 
1899
        case cff_op_load:
 
1900
          FT_TRACE4(( " load" ));
 
1901
 
 
1902
          goto Unimplemented;
 
1903
 
 
1904
        case cff_op_dotsection:
 
1905
          /* this operator is deprecated and ignored by the parser */
 
1906
          FT_TRACE4(( " dotsection" ));
 
1907
          break;
 
1908
 
 
1909
        case cff_op_and:
 
1910
          {
 
1911
            FT_Fixed  cond = args[0] && args[1];
 
1912
 
 
1913
 
 
1914
            FT_TRACE4(( " and" ));
 
1915
 
 
1916
            args[0] = cond ? 0x10000L : 0;
 
1917
            args++;
 
1918
          }
 
1919
          break;
 
1920
 
 
1921
        case cff_op_or:
 
1922
          {
 
1923
            FT_Fixed  cond = args[0] || args[1];
 
1924
 
 
1925
 
 
1926
            FT_TRACE4(( " or" ));
 
1927
 
 
1928
            args[0] = cond ? 0x10000L : 0;
 
1929
            args++;
 
1930
          }
 
1931
          break;
 
1932
 
 
1933
        case cff_op_eq:
 
1934
          {
 
1935
            FT_Fixed  cond = !args[0];
 
1936
 
 
1937
 
 
1938
            FT_TRACE4(( " eq" ));
 
1939
 
 
1940
            args[0] = cond ? 0x10000L : 0;
 
1941
            args++;
 
1942
          }
 
1943
          break;
 
1944
 
 
1945
        case cff_op_ifelse:
 
1946
          {
 
1947
            FT_Fixed  cond = (args[2] <= args[3]);
 
1948
 
 
1949
 
 
1950
            FT_TRACE4(( " ifelse" ));
 
1951
 
 
1952
            if ( !cond )
 
1953
              args[0] = args[1];
 
1954
            args++;
 
1955
          }
 
1956
          break;
 
1957
 
 
1958
        case cff_op_callsubr:
 
1959
          {
 
1960
            FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
 
1961
                                      decoder->locals_bias );
 
1962
 
 
1963
 
 
1964
            FT_TRACE4(( " callsubr(%d)", idx ));
 
1965
 
 
1966
            if ( idx >= decoder->num_locals )
 
1967
            {
 
1968
              FT_ERROR(( "CFF_Parse_CharStrings:" ));
 
1969
              FT_ERROR(( "  invalid local subr index\n" ));
 
1970
              goto Syntax_Error;
 
1971
            }
 
1972
 
 
1973
            if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
 
1974
            {
 
1975
              FT_ERROR(( "CFF_Parse_CharStrings: too many nested subrs\n" ));
 
1976
              goto Syntax_Error;
 
1977
            }
 
1978
 
 
1979
            zone->cursor = ip;  /* save current instruction pointer */
 
1980
 
 
1981
            zone++;
 
1982
            zone->base   = decoder->locals[idx];
 
1983
            zone->limit  = decoder->locals[idx + 1];
 
1984
            zone->cursor = zone->base;
 
1985
 
 
1986
            if ( !zone->base )
 
1987
            {
 
1988
              FT_ERROR(( "CFF_Parse_CharStrings: invoking empty subrs!\n" ));
 
1989
              goto Syntax_Error;
 
1990
            }
 
1991
 
 
1992
            decoder->zone = zone;
 
1993
            ip            = zone->base;
 
1994
            limit         = zone->limit;
 
1995
          }
 
1996
          break;
 
1997
 
 
1998
        case cff_op_callgsubr:
 
1999
          {
 
2000
            FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
 
2001
                                      decoder->globals_bias );
 
2002
 
 
2003
 
 
2004
            FT_TRACE4(( " callgsubr(%d)", idx ));
 
2005
 
 
2006
            if ( idx >= decoder->num_globals )
 
2007
            {
 
2008
              FT_ERROR(( "CFF_Parse_CharStrings:" ));
 
2009
              FT_ERROR(( " invalid global subr index\n" ));
 
2010
              goto Syntax_Error;
 
2011
            }
 
2012
 
 
2013
            if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
 
2014
            {
 
2015
              FT_ERROR(( "CFF_Parse_CharStrings: too many nested subrs\n" ));
 
2016
              goto Syntax_Error;
 
2017
            }
 
2018
 
 
2019
            zone->cursor = ip;  /* save current instruction pointer */
 
2020
 
 
2021
            zone++;
 
2022
            zone->base   = decoder->globals[idx];
 
2023
            zone->limit  = decoder->globals[idx + 1];
 
2024
            zone->cursor = zone->base;
 
2025
 
 
2026
            if ( !zone->base )
 
2027
            {
 
2028
              FT_ERROR(( "CFF_Parse_CharStrings: invoking empty subrs!\n" ));
 
2029
              goto Syntax_Error;
 
2030
            }
 
2031
 
 
2032
            decoder->zone = zone;
 
2033
            ip            = zone->base;
 
2034
            limit         = zone->limit;
 
2035
          }
 
2036
          break;
 
2037
 
 
2038
        case cff_op_return:
 
2039
          FT_TRACE4(( " return" ));
 
2040
 
 
2041
          if ( decoder->zone <= decoder->zones )
 
2042
          {
 
2043
            FT_ERROR(( "CFF_Parse_CharStrings: unexpected return\n" ));
 
2044
            goto Syntax_Error;
 
2045
          }
 
2046
 
 
2047
          decoder->zone--;
 
2048
          zone  = decoder->zone;
 
2049
          ip    = zone->cursor;
 
2050
          limit = zone->limit;
 
2051
          break;
 
2052
 
 
2053
        default:
 
2054
        Unimplemented:
 
2055
          FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
 
2056
 
 
2057
          if ( ip[-1] == 12 )
 
2058
            FT_ERROR(( " %d", ip[0] ));
 
2059
          FT_ERROR(( "\n" ));
 
2060
 
 
2061
          return CFF_Err_Unimplemented_Feature;
 
2062
        }
 
2063
 
 
2064
      decoder->top = args;
 
2065
 
 
2066
      } /* general operator processing */
 
2067
 
 
2068
    } /* while ip < limit */
 
2069
 
 
2070
    FT_TRACE4(( "..end..\n\n" ));
 
2071
 
 
2072
    return error;
 
2073
 
 
2074
  Syntax_Error:
 
2075
    FT_TRACE4(( "CFF_Parse_CharStrings: syntax error!" ));
 
2076
    return CFF_Err_Invalid_File_Format;
 
2077
 
 
2078
  Stack_Underflow:
 
2079
    FT_TRACE4(( "CFF_Parse_CharStrings: stack underflow!" ));
 
2080
    return CFF_Err_Too_Few_Arguments;
 
2081
 
 
2082
  Stack_Overflow:
 
2083
    FT_TRACE4(( "CFF_Parse_CharStrings: stack overflow!" ));
 
2084
    return CFF_Err_Stack_Overflow;
 
2085
 
 
2086
  Memory_Error:
 
2087
    return builder->error;
 
2088
  }
 
2089
 
 
2090
 
 
2091
  /*************************************************************************/
 
2092
  /*************************************************************************/
 
2093
  /*************************************************************************/
 
2094
  /**********                                                      *********/
 
2095
  /**********                                                      *********/
 
2096
  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
 
2097
  /**********                                                      *********/
 
2098
  /**********    The following code is in charge of computing      *********/
 
2099
  /**********    the maximum advance width of the font.  It        *********/
 
2100
  /**********    quickly processes each glyph charstring to        *********/
 
2101
  /**********    extract the value from either a `sbw' or `seac'   *********/
 
2102
  /**********    operator.                                         *********/
 
2103
  /**********                                                      *********/
 
2104
  /*************************************************************************/
 
2105
  /*************************************************************************/
 
2106
  /*************************************************************************/
 
2107
 
 
2108
 
 
2109
#if 0 /* unused until we support pure CFF fonts */
 
2110
 
 
2111
 
 
2112
  FT_LOCAL_DEF( FT_Error )
 
2113
  CFF_Compute_Max_Advance( TT_Face  face,
 
2114
                           FT_Int*  max_advance )
 
2115
  {
 
2116
    FT_Error     error = 0;
 
2117
    CFF_Decoder  decoder;
 
2118
    FT_Int       glyph_index;
 
2119
    CFF_Font     cff = (CFF_Font)face->other;
 
2120
 
 
2121
 
 
2122
    *max_advance = 0;
 
2123
 
 
2124
    /* Initialize load decoder */
 
2125
    CFF_Init_Decoder( &decoder, face, 0, 0, 0 );
 
2126
 
 
2127
    decoder.builder.metrics_only = 1;
 
2128
    decoder.builder.load_points  = 0;
 
2129
 
 
2130
    /* For each glyph, parse the glyph charstring and extract */
 
2131
    /* the advance width.                                     */
 
2132
    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
 
2133
          glyph_index++ )
 
2134
    {
 
2135
      FT_Byte*  charstring;
 
2136
      FT_ULong  charstring_len;
 
2137
 
 
2138
 
 
2139
      /* now get load the unscaled outline */
 
2140
      error = CFF_Access_Element( &cff->charstrings_index, glyph_index,
 
2141
                                  &charstring, &charstring_len );
 
2142
      if ( !error )
 
2143
      {
 
2144
        CFF_Prepare_Decoder( &decoder, glyph_index );
 
2145
        error = CFF_Parse_CharStrings( &decoder, charstring, charstring_len );
 
2146
 
 
2147
        CFF_Forget_Element( &cff->charstrings_index, &charstring );
 
2148
      }
 
2149
 
 
2150
      /* ignore the error if one has occurred -- skip to next glyph */
 
2151
      error = 0;
 
2152
    }
 
2153
 
 
2154
    *max_advance = decoder.builder.advance.x;
 
2155
 
 
2156
    return CFF_Err_Ok;
 
2157
  }
 
2158
 
 
2159
 
 
2160
#endif /* 0 */
 
2161
 
 
2162
 
 
2163
  /*************************************************************************/
 
2164
  /*************************************************************************/
 
2165
  /*************************************************************************/
 
2166
  /**********                                                      *********/
 
2167
  /**********                                                      *********/
 
2168
  /**********               UNHINTED GLYPH LOADER                  *********/
 
2169
  /**********                                                      *********/
 
2170
  /**********    The following code is in charge of loading a      *********/
 
2171
  /**********    single outline.  It completely ignores hinting    *********/
 
2172
  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
 
2173
  /**********                                                      *********/
 
2174
  /*************************************************************************/
 
2175
  /*************************************************************************/
 
2176
  /*************************************************************************/
 
2177
 
 
2178
 
 
2179
  FT_LOCAL_DEF( FT_Error )
 
2180
  CFF_Load_Glyph( CFF_GlyphSlot  glyph,
 
2181
                  CFF_Size       size,
 
2182
                  FT_Int         glyph_index,
 
2183
                  FT_Int         load_flags )
 
2184
  {
 
2185
    FT_Error     error;
 
2186
    CFF_Decoder  decoder;
 
2187
    TT_Face      face = (TT_Face)glyph->root.face;
 
2188
    FT_Bool      hinting;
 
2189
    CFF_Font     cff = (CFF_Font)face->extra.data;
 
2190
 
 
2191
    FT_Matrix    font_matrix;
 
2192
    FT_Vector    font_offset;
 
2193
 
 
2194
 
 
2195
    if ( load_flags & FT_LOAD_NO_RECURSE )
 
2196
      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
 
2197
 
 
2198
    glyph->x_scale = 0x10000L;
 
2199
    glyph->y_scale = 0x10000L;
 
2200
    if ( size )
 
2201
    {
 
2202
      glyph->x_scale = size->metrics.x_scale;
 
2203
      glyph->y_scale = size->metrics.y_scale;
 
2204
    }
 
2205
 
 
2206
    glyph->root.outline.n_points   = 0;
 
2207
    glyph->root.outline.n_contours = 0;
 
2208
 
 
2209
    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
 
2210
                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
 
2211
 
 
2212
    glyph->root.format = ft_glyph_format_outline;  /* by default */
 
2213
 
 
2214
    {
 
2215
      FT_Byte*  charstring;
 
2216
      FT_ULong  charstring_len;
 
2217
 
 
2218
 
 
2219
      CFF_Init_Decoder( &decoder, face, size, glyph, hinting );
 
2220
 
 
2221
      decoder.builder.no_recurse =
 
2222
        (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
 
2223
 
 
2224
      /* now load the unscaled outline */
 
2225
      error = CFF_Access_Element( &cff->charstrings_index, glyph_index,
 
2226
                                  &charstring, &charstring_len );
 
2227
      if ( !error )
 
2228
      {
 
2229
        CFF_IndexRec csindex = cff->charstrings_index;
 
2230
 
 
2231
 
 
2232
        CFF_Prepare_Decoder( &decoder, glyph_index );
 
2233
        error = CFF_Parse_CharStrings( &decoder, charstring, charstring_len );
 
2234
 
 
2235
        CFF_Forget_Element( &cff->charstrings_index, &charstring );
 
2236
 
 
2237
        /* We set control_data and control_len if charstrings is loaded.  */
 
2238
        /* See how charstring loads at CFF_Access_Element() in cffload.c. */
 
2239
 
 
2240
        glyph->root.control_data =
 
2241
          csindex.bytes + csindex.offsets[glyph_index] - 1;
 
2242
        glyph->root.control_len =
 
2243
          charstring_len;
 
2244
      }
 
2245
 
 
2246
      /* save new glyph tables */
 
2247
      CFF_Builder_Done( &decoder.builder );
 
2248
    }
 
2249
 
 
2250
    font_matrix = cff->top_font.font_dict.font_matrix;
 
2251
    font_offset = cff->top_font.font_dict.font_offset;
 
2252
 
 
2253
    /* Now, set the metrics -- this is rather simple, as   */
 
2254
    /* the left side bearing is the xMin, and the top side */
 
2255
    /* bearing the yMax.                                   */
 
2256
    if ( !error )
 
2257
    {
 
2258
      /* For composite glyphs, return only left side bearing and */
 
2259
      /* advance width.                                          */
 
2260
      if ( load_flags & FT_LOAD_NO_RECURSE )
 
2261
      {
 
2262
        FT_Slot_Internal  internal = glyph->root.internal;
 
2263
 
 
2264
 
 
2265
        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
 
2266
        glyph->root.metrics.horiAdvance  = decoder.glyph_width;
 
2267
        internal->glyph_matrix           = font_matrix;
 
2268
        internal->glyph_delta            = font_offset;
 
2269
        internal->glyph_transformed      = 1;
 
2270
      }
 
2271
      else
 
2272
      {
 
2273
        FT_BBox            cbox;
 
2274
        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
 
2275
 
 
2276
 
 
2277
        /* copy the _unscaled_ advance width */
 
2278
        metrics->horiAdvance                    = decoder.glyph_width;
 
2279
        glyph->root.linearHoriAdvance           = decoder.glyph_width;
 
2280
        glyph->root.internal->glyph_transformed = 0;
 
2281
 
 
2282
        /* make up vertical metrics */
 
2283
        metrics->vertBearingX = 0;
 
2284
        metrics->vertBearingY = 0;
 
2285
        metrics->vertAdvance  = 0;
 
2286
 
 
2287
        glyph->root.linearVertAdvance = 0;
 
2288
 
 
2289
        glyph->root.format = ft_glyph_format_outline;
 
2290
 
 
2291
        glyph->root.outline.flags = 0;
 
2292
        if ( size && size->metrics.y_ppem < 24 )
 
2293
          glyph->root.outline.flags |= ft_outline_high_precision;
 
2294
 
 
2295
        glyph->root.outline.flags |= ft_outline_reverse_fill;
 
2296
 
 
2297
        /* apply the font matrix */
 
2298
        FT_Outline_Transform( &glyph->root.outline, &font_matrix );
 
2299
 
 
2300
        FT_Outline_Translate( &glyph->root.outline,
 
2301
                              font_offset.x,
 
2302
                              font_offset.y );
 
2303
 
 
2304
        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
 
2305
        {
 
2306
          /* scale the outline and the metrics */
 
2307
          FT_Int       n;
 
2308
          FT_Outline*  cur     = &glyph->root.outline;
 
2309
          FT_Vector*   vec     = cur->points;
 
2310
          FT_Fixed     x_scale = glyph->x_scale;
 
2311
          FT_Fixed     y_scale = glyph->y_scale;
 
2312
 
 
2313
 
 
2314
          /* First of all, scale the points */
 
2315
          if ( !hinting )
 
2316
            for ( n = cur->n_points; n > 0; n--, vec++ )
 
2317
            {
 
2318
              vec->x = FT_MulFix( vec->x, x_scale );
 
2319
              vec->y = FT_MulFix( vec->y, y_scale );
 
2320
            }
 
2321
 
 
2322
          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
 
2323
 
 
2324
          /* Then scale the metrics */
 
2325
          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
 
2326
          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
 
2327
 
 
2328
          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
 
2329
          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
 
2330
 
 
2331
          if ( hinting )
 
2332
          {
 
2333
            metrics->horiAdvance  = ( metrics->horiAdvance + 32 ) & -64;
 
2334
            metrics->vertAdvance  = ( metrics->vertAdvance + 32 ) & -64;
 
2335
 
 
2336
            metrics->vertBearingX = ( metrics->vertBearingX + 32 ) & -64;
 
2337
            metrics->vertBearingY = ( metrics->vertBearingY + 32 ) & -64;
 
2338
          }
 
2339
        }
 
2340
 
 
2341
        /* compute the other metrics */
 
2342
        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
 
2343
 
 
2344
        /* grid fit the bounding box if necessary */
 
2345
        if ( hinting )
 
2346
        {
 
2347
          cbox.xMin &= -64;
 
2348
          cbox.yMin &= -64;
 
2349
          cbox.xMax  = ( cbox.xMax + 63 ) & -64;
 
2350
          cbox.yMax  = ( cbox.yMax + 63 ) & -64;
 
2351
        }
 
2352
 
 
2353
        metrics->width  = cbox.xMax - cbox.xMin;
 
2354
        metrics->height = cbox.yMax - cbox.yMin;
 
2355
 
 
2356
        metrics->horiBearingX = cbox.xMin;
 
2357
        metrics->horiBearingY = cbox.yMax;
 
2358
      }
 
2359
    }
 
2360
 
 
2361
    return error;
 
2362
  }
 
2363
 
 
2364
 
 
2365
/* END */