~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/cff/cffgload.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

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, 2003, 2004 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->root.internal;
 
255
        builder->hints_funcs   = glyph->root.internal->glyph_hints;
 
256
      }
 
257
    }
 
258
 
 
259
    if ( size )
 
260
    {
 
261
      builder->scale_x = size->root.metrics.x_scale;
 
262
      builder->scale_y = size->root.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_decoder_init                                                   */
 
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_decoder_init( CFF_Decoder*    decoder,
 
350
                    TT_Face         face,
 
351
                    CFF_Size        size,
 
352
                    CFF_GlyphSlot   slot,
 
353
                    FT_Bool         hinting,
 
354
                    FT_Render_Mode  hint_mode )
 
355
  {
 
356
    CFF_Font  cff = (CFF_Font)face->extra.data;
 
357
 
 
358
 
 
359
    /* clear everything */
 
360
    FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
 
361
 
 
362
    /* initialize builder */
 
363
    cff_builder_init( &decoder->builder, face, size, slot, hinting );
 
364
 
 
365
    /* initialize Type2 decoder */
 
366
    decoder->num_globals  = cff->num_global_subrs;
 
367
    decoder->globals      = cff->global_subrs;
 
368
    decoder->globals_bias = cff_compute_bias( decoder->num_globals );
 
369
 
 
370
    decoder->hint_mode    = hint_mode;
 
371
  }
 
372
 
 
373
 
 
374
  /* this function is used to select the locals subrs array */
 
375
  FT_LOCAL_DEF( void )
 
376
  cff_decoder_prepare( CFF_Decoder*  decoder,
 
377
                       FT_UInt       glyph_index )
 
378
  {
 
379
    CFF_Font     cff = (CFF_Font)decoder->builder.face->extra.data;
 
380
    CFF_SubFont  sub = &cff->top_font;
 
381
 
 
382
 
 
383
    /* manage CID fonts */
 
384
    if ( cff->num_subfonts >= 1 )
 
385
    {
 
386
      FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
 
387
 
 
388
 
 
389
      sub = cff->subfonts[fd_index];
 
390
    }
 
391
 
 
392
    decoder->num_locals    = sub->num_local_subrs;
 
393
    decoder->locals        = sub->local_subrs;
 
394
    decoder->locals_bias   = cff_compute_bias( decoder->num_locals );
 
395
 
 
396
    decoder->glyph_width   = sub->private_dict.default_width;
 
397
    decoder->nominal_width = sub->private_dict.nominal_width;
 
398
  }
 
399
 
 
400
 
 
401
  /* check that there is enough space for `count' more points */
 
402
  static FT_Error
 
403
  check_points( CFF_Builder*  builder,
 
404
                FT_Int        count )
 
405
  {
 
406
    return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
 
407
  }
 
408
 
 
409
 
 
410
  /* add a new point, do not check space */
 
411
  static void
 
412
  cff_builder_add_point( CFF_Builder*  builder,
 
413
                         FT_Pos        x,
 
414
                         FT_Pos        y,
 
415
                         FT_Byte       flag )
 
416
  {
 
417
    FT_Outline*  outline = builder->current;
 
418
 
 
419
 
 
420
    if ( builder->load_points )
 
421
    {
 
422
      FT_Vector*  point   = outline->points + outline->n_points;
 
423
      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
 
424
 
 
425
 
 
426
      point->x = x >> 16;
 
427
      point->y = y >> 16;
 
428
      *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
 
429
 
 
430
      builder->last = *point;
 
431
    }
 
432
 
 
433
    outline->n_points++;
 
434
  }
 
435
 
 
436
 
 
437
  /* check space for a new on-curve point, then add it */
 
438
  static FT_Error
 
439
  cff_builder_add_point1( CFF_Builder*  builder,
 
440
                          FT_Pos        x,
 
441
                          FT_Pos        y )
 
442
  {
 
443
    FT_Error  error;
 
444
 
 
445
 
 
446
    error = check_points( builder, 1 );
 
447
    if ( !error )
 
448
      cff_builder_add_point( builder, x, y, 1 );
 
449
 
 
450
    return error;
 
451
  }
 
452
 
 
453
 
 
454
  /* check space for a new contour, then add it */
 
455
  static FT_Error
 
456
  cff_builder_add_contour( CFF_Builder*  builder )
 
457
  {
 
458
    FT_Outline*  outline = builder->current;
 
459
    FT_Error     error;
 
460
 
 
461
 
 
462
    if ( !builder->load_points )
 
463
    {
 
464
      outline->n_contours++;
 
465
      return CFF_Err_Ok;
 
466
    }
 
467
 
 
468
    error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
 
469
    if ( !error )
 
470
    {
 
471
      if ( outline->n_contours > 0 )
 
472
        outline->contours[outline->n_contours - 1] =
 
473
          (short)( outline->n_points - 1 );
 
474
 
 
475
      outline->n_contours++;
 
476
    }
 
477
 
 
478
    return error;
 
479
  }
 
480
 
 
481
 
 
482
  /* if a path was begun, add its first on-curve point */
 
483
  static FT_Error
 
484
  cff_builder_start_point( CFF_Builder*  builder,
 
485
                           FT_Pos        x,
 
486
                           FT_Pos        y )
 
487
  {
 
488
    FT_Error  error = CFF_Err_Ok;
 
489
 
 
490
 
 
491
    /* test whether we are building a new contour */
 
492
    if ( !builder->path_begun )
 
493
    {
 
494
      builder->path_begun = 1;
 
495
      error = cff_builder_add_contour( builder );
 
496
      if ( !error )
 
497
        error = cff_builder_add_point1( builder, x, y );
 
498
    }
 
499
 
 
500
    return error;
 
501
  }
 
502
 
 
503
 
 
504
  /* close the current contour */
 
505
  static void
 
506
  cff_builder_close_contour( CFF_Builder*  builder )
 
507
  {
 
508
    FT_Outline*  outline = builder->current;
 
509
 
 
510
 
 
511
    /* XXXX: We must not include the last point in the path if it */
 
512
    /*       is located on the first point.                       */
 
513
    if ( outline->n_points > 1 )
 
514
    {
 
515
      FT_Int      first   = 0;
 
516
      FT_Vector*  p1      = outline->points + first;
 
517
      FT_Vector*  p2      = outline->points + outline->n_points - 1;
 
518
      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
 
519
 
 
520
 
 
521
      if ( outline->n_contours > 1 )
 
522
      {
 
523
        first = outline->contours[outline->n_contours - 2] + 1;
 
524
        p1    = outline->points + first;
 
525
      }
 
526
 
 
527
      /* `delete' last point only if it coincides with the first    */
 
528
      /* point and if it is not a control point (which can happen). */
 
529
      if ( p1->x == p2->x && p1->y == p2->y )
 
530
        if ( *control == FT_CURVE_TAG_ON )
 
531
          outline->n_points--;
 
532
    }
 
533
 
 
534
    if ( outline->n_contours > 0 )
 
535
      outline->contours[outline->n_contours - 1] =
 
536
        (short)( outline->n_points - 1 );
 
537
  }
 
538
 
 
539
 
 
540
  static FT_Int
 
541
  cff_lookup_glyph_by_stdcharcode( CFF_Font  cff,
 
542
                                   FT_Int    charcode )
 
543
  {
 
544
    FT_UInt    n;
 
545
    FT_UShort  glyph_sid;
 
546
 
 
547
 
 
548
    /* CID-keyed fonts don't have glyph names */
 
549
    if ( !cff->charset.sids )
 
550
      return -1;
 
551
 
 
552
    /* check range of standard char code */
 
553
    if ( charcode < 0 || charcode > 255 )
 
554
      return -1;
 
555
 
 
556
    /* Get code to SID mapping from `cff_standard_encoding'. */
 
557
    glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
 
558
 
 
559
    for ( n = 0; n < cff->num_glyphs; n++ )
 
560
    {
 
561
      if ( cff->charset.sids[n] == glyph_sid )
 
562
        return n;
 
563
    }
 
564
 
 
565
    return -1;
 
566
  }
 
567
 
 
568
 
 
569
  static FT_Error
 
570
  cff_get_glyph_data( TT_Face    face,
 
571
                      FT_UInt    glyph_index,
 
572
                      FT_Byte**  pointer,
 
573
                      FT_ULong*  length )
 
574
  {
 
575
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
576
    /* For incremental fonts get the character data using the */
 
577
    /* callback function.                                     */
 
578
    if ( face->root.internal->incremental_interface )
 
579
    {
 
580
      FT_Data   data;
 
581
      FT_Error  error =
 
582
                  face->root.internal->incremental_interface->funcs->get_glyph_data(
 
583
                    face->root.internal->incremental_interface->object,
 
584
                    glyph_index, &data );
 
585
 
 
586
 
 
587
      *pointer = (FT_Byte*)data.pointer;
 
588
      *length = data.length;
 
589
 
 
590
      return error;
 
591
    }
 
592
    else
 
593
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
594
 
 
595
    {
 
596
      CFF_Font  cff  = (CFF_Font)(face->extra.data);
 
597
 
 
598
 
 
599
      return cff_index_access_element( &cff->charstrings_index, glyph_index,
 
600
                                       pointer, length );
 
601
    }
 
602
  }
 
603
 
 
604
 
 
605
  static void
 
606
  cff_free_glyph_data( TT_Face    face,
 
607
                       FT_Byte**  pointer,
 
608
                       FT_ULong   length )
 
609
  {
 
610
#ifndef FT_CONFIG_OPTION_INCREMENTAL
 
611
    FT_UNUSED( length );
 
612
#endif
 
613
 
 
614
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
615
    /* For incremental fonts get the character data using the */
 
616
    /* callback function.                                     */
 
617
    if ( face->root.internal->incremental_interface )
 
618
    {
 
619
      FT_Data data;
 
620
 
 
621
 
 
622
      data.pointer = *pointer;
 
623
      data.length  = length;
 
624
 
 
625
      face->root.internal->incremental_interface->funcs->free_glyph_data(
 
626
        face->root.internal->incremental_interface->object,&data );
 
627
    }
 
628
    else
 
629
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
630
 
 
631
    {
 
632
      CFF_Font  cff = (CFF_Font)(face->extra.data);
 
633
 
 
634
 
 
635
      cff_index_forget_element( &cff->charstrings_index, pointer );
 
636
    }
 
637
  }
 
638
 
 
639
 
 
640
  static FT_Error
 
641
  cff_operator_seac( CFF_Decoder*  decoder,
 
642
                     FT_Pos        adx,
 
643
                     FT_Pos        ady,
 
644
                     FT_Int        bchar,
 
645
                     FT_Int        achar )
 
646
  {
 
647
    FT_Error      error;
 
648
    CFF_Builder*  builder = &decoder->builder;
 
649
    FT_Int        bchar_index, achar_index;
 
650
    TT_Face       face = decoder->builder.face;
 
651
    FT_Vector     left_bearing, advance;
 
652
    FT_Byte*      charstring;
 
653
    FT_ULong      charstring_len;
 
654
 
 
655
 
 
656
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
657
    /* Incremental fonts don't necessarily have valid charsets.        */
 
658
    /* They use the character code, not the glyph index, in this case. */
 
659
    if ( face->root.internal->incremental_interface )
 
660
    {
 
661
      bchar_index = bchar;
 
662
      achar_index = achar;
 
663
    }
 
664
    else
 
665
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
666
    {
 
667
      CFF_Font cff = (CFF_Font)(face->extra.data);
 
668
 
 
669
 
 
670
      bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
 
671
      achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
 
672
    }
 
673
 
 
674
    if ( bchar_index < 0 || achar_index < 0 )
 
675
    {
 
676
      FT_ERROR(( "cff_operator_seac:" ));
 
677
      FT_ERROR(( " invalid seac character code arguments\n" ));
 
678
      return CFF_Err_Syntax_Error;
 
679
    }
 
680
 
 
681
    /* If we are trying to load a composite glyph, do not load the */
 
682
    /* accent character and return the array of subglyphs.         */
 
683
    if ( builder->no_recurse )
 
684
    {
 
685
      FT_GlyphSlot    glyph  = (FT_GlyphSlot)builder->glyph;
 
686
      FT_GlyphLoader  loader = glyph->internal->loader;
 
687
      FT_SubGlyph     subg;
 
688
 
 
689
 
 
690
      /* reallocate subglyph array if necessary */
 
691
      error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
 
692
      if ( error )
 
693
        goto Exit;
 
694
 
 
695
      subg = loader->current.subglyphs;
 
696
 
 
697
      /* subglyph 0 = base character */
 
698
      subg->index = bchar_index;
 
699
      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
 
700
                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
 
701
      subg->arg1  = 0;
 
702
      subg->arg2  = 0;
 
703
      subg++;
 
704
 
 
705
      /* subglyph 1 = accent character */
 
706
      subg->index = achar_index;
 
707
      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
 
708
      subg->arg1  = (FT_Int)( adx >> 16 );
 
709
      subg->arg2  = (FT_Int)( ady >> 16 );
 
710
 
 
711
      /* set up remaining glyph fields */
 
712
      glyph->num_subglyphs = 2;
 
713
      glyph->subglyphs     = loader->base.subglyphs;
 
714
      glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
 
715
 
 
716
      loader->current.num_subglyphs = 2;
 
717
    }
 
718
 
 
719
    FT_GlyphLoader_Prepare( builder->loader );
 
720
 
 
721
    /* First load `bchar' in builder */
 
722
    error = cff_get_glyph_data( face, bchar_index,
 
723
                                &charstring, &charstring_len );
 
724
    if ( !error )
 
725
    {
 
726
      error = cff_decoder_parse_charstrings( decoder, charstring,
 
727
                                             charstring_len );
 
728
 
 
729
      if ( error )
 
730
        goto Exit;
 
731
 
 
732
      cff_free_glyph_data( face, &charstring, charstring_len );
 
733
    }
 
734
 
 
735
    /* Save the left bearing and width of the base character */
 
736
    /* as they will be erased by the next load.              */
 
737
 
 
738
    left_bearing = builder->left_bearing;
 
739
    advance      = builder->advance;
 
740
 
 
741
    builder->left_bearing.x = 0;
 
742
    builder->left_bearing.y = 0;
 
743
 
 
744
    builder->pos_x = adx;
 
745
    builder->pos_y = ady;
 
746
 
 
747
    /* Now load `achar' on top of the base outline. */
 
748
    error = cff_get_glyph_data( face, achar_index,
 
749
                                &charstring, &charstring_len );
 
750
    if ( !error )
 
751
    {
 
752
      error = cff_decoder_parse_charstrings( decoder, charstring,
 
753
                                             charstring_len );
 
754
 
 
755
      if ( error )
 
756
        goto Exit;
 
757
 
 
758
      cff_free_glyph_data( face, &charstring, charstring_len );
 
759
    }
 
760
 
 
761
    /* Restore the left side bearing and advance width */
 
762
    /* of the base character.                          */
 
763
    builder->left_bearing = left_bearing;
 
764
    builder->advance      = advance;
 
765
 
 
766
    builder->pos_x = 0;
 
767
    builder->pos_y = 0;
 
768
 
 
769
  Exit:
 
770
    return error;
 
771
  }
 
772
 
 
773
 
 
774
  /*************************************************************************/
 
775
  /*                                                                       */
 
776
  /* <Function>                                                            */
 
777
  /*    cff_decoder_parse_charstrings                                      */
 
778
  /*                                                                       */
 
779
  /* <Description>                                                         */
 
780
  /*    Parses a given Type 2 charstrings program.                         */
 
781
  /*                                                                       */
 
782
  /* <InOut>                                                               */
 
783
  /*    decoder         :: The current Type 1 decoder.                     */
 
784
  /*                                                                       */
 
785
  /* <Input>                                                               */
 
786
  /*    charstring_base :: The base of the charstring stream.              */
 
787
  /*                                                                       */
 
788
  /*    charstring_len  :: The length in bytes of the charstring stream.   */
 
789
  /*                                                                       */
 
790
  /* <Return>                                                              */
 
791
  /*    FreeType error code.  0 means success.                             */
 
792
  /*                                                                       */
 
793
  FT_LOCAL_DEF( FT_Error )
 
794
  cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
 
795
                                 FT_Byte*      charstring_base,
 
796
                                 FT_ULong      charstring_len )
 
797
  {
 
798
    FT_Error           error;
 
799
    CFF_Decoder_Zone*  zone;
 
800
    FT_Byte*           ip;
 
801
    FT_Byte*           limit;
 
802
    CFF_Builder*       builder = &decoder->builder;
 
803
    FT_Pos             x, y;
 
804
    FT_Fixed           seed;
 
805
    FT_Fixed*          stack;
 
806
 
 
807
    T2_Hints_Funcs     hinter;
 
808
 
 
809
 
 
810
    /* set default width */
 
811
    decoder->num_hints  = 0;
 
812
    decoder->read_width = 1;
 
813
 
 
814
    /* compute random seed from stack address of parameter */
 
815
    seed = (FT_Fixed)(char*)&seed           ^
 
816
           (FT_Fixed)(char*)&decoder        ^
 
817
           (FT_Fixed)(char*)&charstring_base;
 
818
    seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
 
819
    if ( seed == 0 )
 
820
      seed = 0x7384;
 
821
 
 
822
    /* initialize the decoder */
 
823
    decoder->top  = decoder->stack;
 
824
    decoder->zone = decoder->zones;
 
825
    zone          = decoder->zones;
 
826
    stack         = decoder->top;
 
827
 
 
828
    hinter = (T2_Hints_Funcs)builder->hints_funcs;
 
829
 
 
830
    builder->path_begun = 0;
 
831
 
 
832
    zone->base           = charstring_base;
 
833
    limit = zone->limit  = charstring_base + charstring_len;
 
834
    ip    = zone->cursor = zone->base;
 
835
 
 
836
    error = CFF_Err_Ok;
 
837
 
 
838
    x = builder->pos_x;
 
839
    y = builder->pos_y;
 
840
 
 
841
    /* begin hints recording session, if any */
 
842
    if ( hinter )
 
843
      hinter->open( hinter->hints );
 
844
 
 
845
    /* now execute loop */
 
846
    while ( ip < limit )
 
847
    {
 
848
      CFF_Operator  op;
 
849
      FT_Byte       v;
 
850
 
 
851
 
 
852
      /********************************************************************/
 
853
      /*                                                                  */
 
854
      /* Decode operator or operand                                       */
 
855
      /*                                                                  */
 
856
      v = *ip++;
 
857
      if ( v >= 32 || v == 28 )
 
858
      {
 
859
        FT_Int    shift = 16;
 
860
        FT_Int32  val;
 
861
 
 
862
 
 
863
        /* this is an operand, push it on the stack */
 
864
        if ( v == 28 )
 
865
        {
 
866
          if ( ip + 1 >= limit )
 
867
            goto Syntax_Error;
 
868
          val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
 
869
          ip += 2;
 
870
        }
 
871
        else if ( v < 247 )
 
872
          val = (FT_Long)v - 139;
 
873
        else if ( v < 251 )
 
874
        {
 
875
          if ( ip >= limit )
 
876
            goto Syntax_Error;
 
877
          val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
 
878
        }
 
879
        else if ( v < 255 )
 
880
        {
 
881
          if ( ip >= limit )
 
882
            goto Syntax_Error;
 
883
          val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
 
884
        }
 
885
        else
 
886
        {
 
887
          if ( ip + 3 >= limit )
 
888
            goto Syntax_Error;
 
889
          val = ( (FT_Int32)ip[0] << 24 ) |
 
890
                ( (FT_Int32)ip[1] << 16 ) |
 
891
                ( (FT_Int32)ip[2] <<  8 ) |
 
892
                            ip[3];
 
893
          ip    += 4;
 
894
          shift  = 0;
 
895
        }
 
896
        if ( decoder->top - stack >= CFF_MAX_OPERANDS )
 
897
          goto Stack_Overflow;
 
898
 
 
899
        val           <<= shift;
 
900
        *decoder->top++ = val;
 
901
 
 
902
#ifdef FT_DEBUG_LEVEL_TRACE
 
903
        if ( !( val & 0xFFFFL ) )
 
904
          FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) ));
 
905
        else
 
906
          FT_TRACE4(( " %.2f", val / 65536.0 ));
 
907
#endif
 
908
 
 
909
      }
 
910
      else
 
911
      {
 
912
        FT_Fixed*  args     = decoder->top;
 
913
        FT_Int     num_args = (FT_Int)( args - decoder->stack );
 
914
        FT_Int     req_args;
 
915
 
 
916
 
 
917
        /* find operator */
 
918
        op = cff_op_unknown;
 
919
 
 
920
        switch ( v )
 
921
        {
 
922
        case 1:
 
923
          op = cff_op_hstem;
 
924
          break;
 
925
        case 3:
 
926
          op = cff_op_vstem;
 
927
          break;
 
928
        case 4:
 
929
          op = cff_op_vmoveto;
 
930
          break;
 
931
        case 5:
 
932
          op = cff_op_rlineto;
 
933
          break;
 
934
        case 6:
 
935
          op = cff_op_hlineto;
 
936
          break;
 
937
        case 7:
 
938
          op = cff_op_vlineto;
 
939
          break;
 
940
        case 8:
 
941
          op = cff_op_rrcurveto;
 
942
          break;
 
943
        case 10:
 
944
          op = cff_op_callsubr;
 
945
          break;
 
946
        case 11:
 
947
          op = cff_op_return;
 
948
          break;
 
949
        case 12:
 
950
          {
 
951
            if ( ip >= limit )
 
952
              goto Syntax_Error;
 
953
            v = *ip++;
 
954
 
 
955
            switch ( v )
 
956
            {
 
957
            case 0:
 
958
              op = cff_op_dotsection;
 
959
              break;
 
960
            case 3:
 
961
              op = cff_op_and;
 
962
              break;
 
963
            case 4:
 
964
              op = cff_op_or;
 
965
              break;
 
966
            case 5:
 
967
              op = cff_op_not;
 
968
              break;
 
969
            case 8:
 
970
              op = cff_op_store;
 
971
              break;
 
972
            case 9:
 
973
              op = cff_op_abs;
 
974
              break;
 
975
            case 10:
 
976
              op = cff_op_add;
 
977
              break;
 
978
            case 11:
 
979
              op = cff_op_sub;
 
980
              break;
 
981
            case 12:
 
982
              op = cff_op_div;
 
983
              break;
 
984
            case 13:
 
985
              op = cff_op_load;
 
986
              break;
 
987
            case 14:
 
988
              op = cff_op_neg;
 
989
              break;
 
990
            case 15:
 
991
              op = cff_op_eq;
 
992
              break;
 
993
            case 18:
 
994
              op = cff_op_drop;
 
995
              break;
 
996
            case 20:
 
997
              op = cff_op_put;
 
998
              break;
 
999
            case 21:
 
1000
              op = cff_op_get;
 
1001
              break;
 
1002
            case 22:
 
1003
              op = cff_op_ifelse;
 
1004
              break;
 
1005
            case 23:
 
1006
              op = cff_op_random;
 
1007
              break;
 
1008
            case 24:
 
1009
              op = cff_op_mul;
 
1010
              break;
 
1011
            case 26:
 
1012
              op = cff_op_sqrt;
 
1013
              break;
 
1014
            case 27:
 
1015
              op = cff_op_dup;
 
1016
              break;
 
1017
            case 28:
 
1018
              op = cff_op_exch;
 
1019
              break;
 
1020
            case 29:
 
1021
              op = cff_op_index;
 
1022
              break;
 
1023
            case 30:
 
1024
              op = cff_op_roll;
 
1025
              break;
 
1026
            case 34:
 
1027
              op = cff_op_hflex;
 
1028
              break;
 
1029
            case 35:
 
1030
              op = cff_op_flex;
 
1031
              break;
 
1032
            case 36:
 
1033
              op = cff_op_hflex1;
 
1034
              break;
 
1035
            case 37:
 
1036
              op = cff_op_flex1;
 
1037
              break;
 
1038
            default:
 
1039
              /* decrement ip for syntax error message */
 
1040
              ip--;
 
1041
            }
 
1042
          }
 
1043
          break;
 
1044
        case 14:
 
1045
          op = cff_op_endchar;
 
1046
          break;
 
1047
        case 16:
 
1048
          op = cff_op_blend;
 
1049
          break;
 
1050
        case 18:
 
1051
          op = cff_op_hstemhm;
 
1052
          break;
 
1053
        case 19:
 
1054
          op = cff_op_hintmask;
 
1055
          break;
 
1056
        case 20:
 
1057
          op = cff_op_cntrmask;
 
1058
          break;
 
1059
        case 21:
 
1060
          op = cff_op_rmoveto;
 
1061
          break;
 
1062
        case 22:
 
1063
          op = cff_op_hmoveto;
 
1064
          break;
 
1065
        case 23:
 
1066
          op = cff_op_vstemhm;
 
1067
          break;
 
1068
        case 24:
 
1069
          op = cff_op_rcurveline;
 
1070
          break;
 
1071
        case 25:
 
1072
          op = cff_op_rlinecurve;
 
1073
          break;
 
1074
        case 26:
 
1075
          op = cff_op_vvcurveto;
 
1076
          break;
 
1077
        case 27:
 
1078
          op = cff_op_hhcurveto;
 
1079
          break;
 
1080
        case 29:
 
1081
          op = cff_op_callgsubr;
 
1082
          break;
 
1083
        case 30:
 
1084
          op = cff_op_vhcurveto;
 
1085
          break;
 
1086
        case 31:
 
1087
          op = cff_op_hvcurveto;
 
1088
          break;
 
1089
        default:
 
1090
          ;
 
1091
        }
 
1092
        if ( op == cff_op_unknown )
 
1093
          goto Syntax_Error;
 
1094
 
 
1095
        /* check arguments */
 
1096
        req_args = cff_argument_counts[op];
 
1097
        if ( req_args & CFF_COUNT_CHECK_WIDTH )
 
1098
        {
 
1099
          args = stack;
 
1100
 
 
1101
          if ( num_args > 0 && decoder->read_width )
 
1102
          {
 
1103
            /* If `nominal_width' is non-zero, the number is really a      */
 
1104
            /* difference against `nominal_width'.  Else, the number here  */
 
1105
            /* is truly a width, not a difference against `nominal_width'. */
 
1106
            /* If the font does not set `nominal_width', then              */
 
1107
            /* `nominal_width' defaults to zero, and so we can set         */
 
1108
            /* `glyph_width' to `nominal_width' plus number on the stack   */
 
1109
            /* -- for either case.                                         */
 
1110
 
 
1111
            FT_Int  set_width_ok;
 
1112
 
 
1113
 
 
1114
            switch ( op )
 
1115
            {
 
1116
            case cff_op_hmoveto:
 
1117
            case cff_op_vmoveto:
 
1118
              set_width_ok = num_args & 2;
 
1119
              break;
 
1120
 
 
1121
            case cff_op_hstem:
 
1122
            case cff_op_vstem:
 
1123
            case cff_op_hstemhm:
 
1124
            case cff_op_vstemhm:
 
1125
            case cff_op_rmoveto:
 
1126
            case cff_op_hintmask:
 
1127
            case cff_op_cntrmask:
 
1128
              set_width_ok = num_args & 1;
 
1129
              break;
 
1130
 
 
1131
            case cff_op_endchar:
 
1132
              /* If there is a width specified for endchar, we either have */
 
1133
              /* 1 argument or 5 arguments.  We like to argue.             */
 
1134
              set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) );
 
1135
              break;
 
1136
 
 
1137
            default:
 
1138
              set_width_ok = 0;
 
1139
              break;
 
1140
            }
 
1141
 
 
1142
            if ( set_width_ok )
 
1143
            {
 
1144
              decoder->glyph_width = decoder->nominal_width +
 
1145
                                       ( stack[0] >> 16 );
 
1146
 
 
1147
              /* Consumed an argument. */
 
1148
              num_args--;
 
1149
              args++;
 
1150
            }
 
1151
          }
 
1152
 
 
1153
          decoder->read_width = 0;
 
1154
          req_args            = 0;
 
1155
        }
 
1156
 
 
1157
        req_args &= 15;
 
1158
        if ( num_args < req_args )
 
1159
          goto Stack_Underflow;
 
1160
        args     -= req_args;
 
1161
        num_args -= req_args;
 
1162
 
 
1163
        switch ( op )
 
1164
        {
 
1165
        case cff_op_hstem:
 
1166
        case cff_op_vstem:
 
1167
        case cff_op_hstemhm:
 
1168
        case cff_op_vstemhm:
 
1169
          /* the number of arguments is always even here */
 
1170
          FT_TRACE4(( op == cff_op_hstem   ? " hstem"   :
 
1171
                    ( op == cff_op_vstem   ? " vstem"   :
 
1172
                    ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) ));
 
1173
 
 
1174
          if ( hinter )
 
1175
            hinter->stems( hinter->hints,
 
1176
                           ( op == cff_op_hstem || op == cff_op_hstemhm ),
 
1177
                           num_args / 2,
 
1178
                           args );
 
1179
 
 
1180
          decoder->num_hints += num_args / 2;
 
1181
          args = stack;
 
1182
          break;
 
1183
 
 
1184
        case cff_op_hintmask:
 
1185
        case cff_op_cntrmask:
 
1186
          FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
 
1187
 
 
1188
          /* implement vstem when needed --                        */
 
1189
          /* the specification doesn't say it, but this also works */
 
1190
          /* with the 'cntrmask' operator                          */
 
1191
          /*                                                       */
 
1192
          if ( num_args > 0 )
 
1193
          {
 
1194
            if ( hinter )
 
1195
              hinter->stems( hinter->hints,
 
1196
                             0,
 
1197
                             num_args / 2,
 
1198
                             args );
 
1199
 
 
1200
            decoder->num_hints += num_args / 2;
 
1201
          }
 
1202
 
 
1203
          if ( hinter )
 
1204
          {
 
1205
            if ( op == cff_op_hintmask )
 
1206
              hinter->hintmask( hinter->hints,
 
1207
                                builder->current->n_points,
 
1208
                                decoder->num_hints,
 
1209
                                ip );
 
1210
            else
 
1211
              hinter->counter( hinter->hints,
 
1212
                               decoder->num_hints,
 
1213
                               ip );
 
1214
          }
 
1215
 
 
1216
#ifdef FT_DEBUG_LEVEL_TRACE
 
1217
          {
 
1218
            FT_UInt maskbyte;
 
1219
 
 
1220
 
 
1221
            FT_TRACE4(( " " ));
 
1222
 
 
1223
            for ( maskbyte = 0;
 
1224
                  maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3);
 
1225
                  maskbyte++, ip++ )
 
1226
              FT_TRACE4(( "0x%02X", *ip ));
 
1227
          }
 
1228
#else
 
1229
          ip += ( decoder->num_hints + 7 ) >> 3;
 
1230
#endif
 
1231
          if ( ip >= limit )
 
1232
            goto Syntax_Error;
 
1233
          args = stack;
 
1234
          break;
 
1235
 
 
1236
        case cff_op_rmoveto:
 
1237
          FT_TRACE4(( " rmoveto" ));
 
1238
 
 
1239
          cff_builder_close_contour( builder );
 
1240
          builder->path_begun = 0;
 
1241
          x   += args[0];
 
1242
          y   += args[1];
 
1243
          args = stack;
 
1244
          break;
 
1245
 
 
1246
        case cff_op_vmoveto:
 
1247
          FT_TRACE4(( " vmoveto" ));
 
1248
 
 
1249
          cff_builder_close_contour( builder );
 
1250
          builder->path_begun = 0;
 
1251
          y   += args[0];
 
1252
          args = stack;
 
1253
          break;
 
1254
 
 
1255
        case cff_op_hmoveto:
 
1256
          FT_TRACE4(( " hmoveto" ));
 
1257
 
 
1258
          cff_builder_close_contour( builder );
 
1259
          builder->path_begun = 0;
 
1260
          x   += args[0];
 
1261
          args = stack;
 
1262
          break;
 
1263
 
 
1264
        case cff_op_rlineto:
 
1265
          FT_TRACE4(( " rlineto" ));
 
1266
 
 
1267
          if ( cff_builder_start_point ( builder, x, y ) ||
 
1268
               check_points( builder, num_args / 2 )     )
 
1269
            goto Fail;
 
1270
 
 
1271
          if ( num_args < 2 || num_args & 1 )
 
1272
            goto Stack_Underflow;
 
1273
 
 
1274
          args = stack;
 
1275
          while ( args < decoder->top )
 
1276
          {
 
1277
            x += args[0];
 
1278
            y += args[1];
 
1279
            cff_builder_add_point( builder, x, y, 1 );
 
1280
            args += 2;
 
1281
          }
 
1282
          args = stack;
 
1283
          break;
 
1284
 
 
1285
        case cff_op_hlineto:
 
1286
        case cff_op_vlineto:
 
1287
          {
 
1288
            FT_Int  phase = ( op == cff_op_hlineto );
 
1289
 
 
1290
 
 
1291
            FT_TRACE4(( op == cff_op_hlineto ? " hlineto"
 
1292
                                             : " vlineto" ));
 
1293
 
 
1294
            if ( cff_builder_start_point ( builder, x, y ) ||
 
1295
                 check_points( builder, num_args )         )
 
1296
              goto Fail;
 
1297
 
 
1298
            args = stack;
 
1299
            while (args < decoder->top )
 
1300
            {
 
1301
              if ( phase )
 
1302
                x += args[0];
 
1303
              else
 
1304
                y += args[0];
 
1305
 
 
1306
              if ( cff_builder_add_point1( builder, x, y ) )
 
1307
                goto Fail;
 
1308
 
 
1309
              args++;
 
1310
              phase ^= 1;
 
1311
            }
 
1312
            args = stack;
 
1313
          }
 
1314
          break;
 
1315
 
 
1316
        case cff_op_rrcurveto:
 
1317
          FT_TRACE4(( " rrcurveto" ));
 
1318
 
 
1319
          /* check number of arguments; must be a multiple of 6 */
 
1320
          if ( num_args % 6 != 0 )
 
1321
            goto Stack_Underflow;
 
1322
 
 
1323
          if ( cff_builder_start_point ( builder, x, y ) ||
 
1324
               check_points( builder, num_args / 2 )     )
 
1325
            goto Fail;
 
1326
 
 
1327
          args = stack;
 
1328
          while ( args < decoder->top )
 
1329
          {
 
1330
            x += args[0];
 
1331
            y += args[1];
 
1332
            cff_builder_add_point( builder, x, y, 0 );
 
1333
            x += args[2];
 
1334
            y += args[3];
 
1335
            cff_builder_add_point( builder, x, y, 0 );
 
1336
            x += args[4];
 
1337
            y += args[5];
 
1338
            cff_builder_add_point( builder, x, y, 1 );
 
1339
            args += 6;
 
1340
          }
 
1341
          args = stack;
 
1342
          break;
 
1343
 
 
1344
        case cff_op_vvcurveto:
 
1345
          FT_TRACE4(( " vvcurveto" ));
 
1346
 
 
1347
          if ( cff_builder_start_point( builder, x, y ) )
 
1348
            goto Fail;
 
1349
 
 
1350
          args = stack;
 
1351
          if ( num_args & 1 )
 
1352
          {
 
1353
            x += args[0];
 
1354
            args++;
 
1355
            num_args--;
 
1356
          }
 
1357
 
 
1358
          if ( num_args % 4 != 0 )
 
1359
            goto Stack_Underflow;
 
1360
 
 
1361
          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
 
1362
            goto Fail;
 
1363
 
 
1364
          while ( args < decoder->top )
 
1365
          {
 
1366
            y += args[0];
 
1367
            cff_builder_add_point( builder, x, y, 0 );
 
1368
            x += args[1];
 
1369
            y += args[2];
 
1370
            cff_builder_add_point( builder, x, y, 0 );
 
1371
            y += args[3];
 
1372
            cff_builder_add_point( builder, x, y, 1 );
 
1373
            args += 4;
 
1374
          }
 
1375
          args = stack;
 
1376
          break;
 
1377
 
 
1378
        case cff_op_hhcurveto:
 
1379
          FT_TRACE4(( " hhcurveto" ));
 
1380
 
 
1381
          if ( cff_builder_start_point( builder, x, y ) )
 
1382
            goto Fail;
 
1383
 
 
1384
          args = stack;
 
1385
          if ( num_args & 1 )
 
1386
          {
 
1387
            y += args[0];
 
1388
            args++;
 
1389
            num_args--;
 
1390
          }
 
1391
 
 
1392
          if ( num_args % 4 != 0 )
 
1393
            goto Stack_Underflow;
 
1394
 
 
1395
          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
 
1396
            goto Fail;
 
1397
 
 
1398
          while ( args < decoder->top )
 
1399
          {
 
1400
            x += args[0];
 
1401
            cff_builder_add_point( builder, x, y, 0 );
 
1402
            x += args[1];
 
1403
            y += args[2];
 
1404
            cff_builder_add_point( builder, x, y, 0 );
 
1405
            x += args[3];
 
1406
            cff_builder_add_point( builder, x, y, 1 );
 
1407
            args += 4;
 
1408
          }
 
1409
          args = stack;
 
1410
          break;
 
1411
 
 
1412
        case cff_op_vhcurveto:
 
1413
        case cff_op_hvcurveto:
 
1414
          {
 
1415
            FT_Int  phase;
 
1416
 
 
1417
 
 
1418
            FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto"
 
1419
                                               : " hvcurveto" ));
 
1420
 
 
1421
            if ( cff_builder_start_point( builder, x, y ) )
 
1422
              goto Fail;
 
1423
 
 
1424
            args = stack;
 
1425
            if (num_args < 4 || ( num_args % 4 ) > 1 )
 
1426
              goto Stack_Underflow;
 
1427
 
 
1428
            if ( check_points( builder, ( num_args / 4 ) * 3 ) )
 
1429
              goto Stack_Underflow;
 
1430
 
 
1431
            phase = ( op == cff_op_hvcurveto );
 
1432
 
 
1433
            while ( num_args >= 4 )
 
1434
            {
 
1435
              num_args -= 4;
 
1436
              if ( phase )
 
1437
              {
 
1438
                x += args[0];
 
1439
                cff_builder_add_point( builder, x, y, 0 );
 
1440
                x += args[1];
 
1441
                y += args[2];
 
1442
                cff_builder_add_point( builder, x, y, 0 );
 
1443
                y += args[3];
 
1444
                if ( num_args == 1 )
 
1445
                  x += args[4];
 
1446
                cff_builder_add_point( builder, x, y, 1 );
 
1447
              }
 
1448
              else
 
1449
              {
 
1450
                y += args[0];
 
1451
                cff_builder_add_point( builder, x, y, 0 );
 
1452
                x += args[1];
 
1453
                y += args[2];
 
1454
                cff_builder_add_point( builder, x, y, 0 );
 
1455
                x += args[3];
 
1456
                if ( num_args == 1 )
 
1457
                  y += args[4];
 
1458
                cff_builder_add_point( builder, x, y, 1 );
 
1459
              }
 
1460
              args  += 4;
 
1461
              phase ^= 1;
 
1462
            }
 
1463
            args = stack;
 
1464
          }
 
1465
          break;
 
1466
 
 
1467
        case cff_op_rlinecurve:
 
1468
          {
 
1469
            FT_Int  num_lines = ( num_args - 6 ) / 2;
 
1470
 
 
1471
 
 
1472
            FT_TRACE4(( " rlinecurve" ));
 
1473
 
 
1474
            if ( num_args < 8 || ( num_args - 6 ) & 1 )
 
1475
              goto Stack_Underflow;
 
1476
 
 
1477
            if ( cff_builder_start_point( builder, x, y ) ||
 
1478
                 check_points( builder, num_lines + 3 )   )
 
1479
              goto Fail;
 
1480
 
 
1481
            args = stack;
 
1482
 
 
1483
            /* first, add the line segments */
 
1484
            while ( num_lines > 0 )
 
1485
            {
 
1486
              x += args[0];
 
1487
              y += args[1];
 
1488
              cff_builder_add_point( builder, x, y, 1 );
 
1489
              args += 2;
 
1490
              num_lines--;
 
1491
            }
 
1492
 
 
1493
            /* then the curve */
 
1494
            x += args[0];
 
1495
            y += args[1];
 
1496
            cff_builder_add_point( builder, x, y, 0 );
 
1497
            x += args[2];
 
1498
            y += args[3];
 
1499
            cff_builder_add_point( builder, x, y, 0 );
 
1500
            x += args[4];
 
1501
            y += args[5];
 
1502
            cff_builder_add_point( builder, x, y, 1 );
 
1503
            args = stack;
 
1504
          }
 
1505
          break;
 
1506
 
 
1507
        case cff_op_rcurveline:
 
1508
          {
 
1509
            FT_Int  num_curves = ( num_args - 2 ) / 6;
 
1510
 
 
1511
 
 
1512
            FT_TRACE4(( " rcurveline" ));
 
1513
 
 
1514
            if ( num_args < 8 || ( num_args - 2 ) % 6 )
 
1515
              goto Stack_Underflow;
 
1516
 
 
1517
            if ( cff_builder_start_point ( builder, x, y ) ||
 
1518
                 check_points( builder, num_curves*3 + 2 ) )
 
1519
              goto Fail;
 
1520
 
 
1521
            args = stack;
 
1522
 
 
1523
            /* first, add the curves */
 
1524
            while ( num_curves > 0 )
 
1525
            {
 
1526
              x += args[0];
 
1527
              y += args[1];
 
1528
              cff_builder_add_point( builder, x, y, 0 );
 
1529
              x += args[2];
 
1530
              y += args[3];
 
1531
              cff_builder_add_point( builder, x, y, 0 );
 
1532
              x += args[4];
 
1533
              y += args[5];
 
1534
              cff_builder_add_point( builder, x, y, 1 );
 
1535
              args += 6;
 
1536
              num_curves--;
 
1537
            }
 
1538
 
 
1539
            /* then the final line */
 
1540
            x += args[0];
 
1541
            y += args[1];
 
1542
            cff_builder_add_point( builder, x, y, 1 );
 
1543
            args = stack;
 
1544
          }
 
1545
          break;
 
1546
 
 
1547
        case cff_op_hflex1:
 
1548
          {
 
1549
            FT_Pos start_y;
 
1550
 
 
1551
 
 
1552
            FT_TRACE4(( " hflex1" ));
 
1553
 
 
1554
            args = stack;
 
1555
 
 
1556
            /* adding five more points; 4 control points, 1 on-curve point */
 
1557
            /* make sure we have enough space for the start point if it    */
 
1558
            /* needs to be added                                           */
 
1559
            if ( cff_builder_start_point( builder, x, y ) ||
 
1560
                 check_points( builder, 6 )               )
 
1561
              goto Fail;
 
1562
 
 
1563
            /* Record the starting point's y postion for later use */
 
1564
            start_y = y;
 
1565
 
 
1566
            /* first control point */
 
1567
            x += args[0];
 
1568
            y += args[1];
 
1569
            cff_builder_add_point( builder, x, y, 0 );
 
1570
 
 
1571
            /* second control point */
 
1572
            x += args[2];
 
1573
            y += args[3];
 
1574
            cff_builder_add_point( builder, x, y, 0 );
 
1575
 
 
1576
            /* join point; on curve, with y-value the same as the last */
 
1577
            /* control point's y-value                                 */
 
1578
            x += args[4];
 
1579
            cff_builder_add_point( builder, x, y, 1 );
 
1580
 
 
1581
            /* third control point, with y-value the same as the join */
 
1582
            /* point's y-value                                        */
 
1583
            x += args[5];
 
1584
            cff_builder_add_point( builder, x, y, 0 );
 
1585
 
 
1586
            /* fourth control point */
 
1587
            x += args[6];
 
1588
            y += args[7];
 
1589
            cff_builder_add_point( builder, x, y, 0 );
 
1590
 
 
1591
            /* ending point, with y-value the same as the start   */
 
1592
            x += args[8];
 
1593
            y  = start_y;
 
1594
            cff_builder_add_point( builder, x, y, 1 );
 
1595
 
 
1596
            args = stack;
 
1597
            break;
 
1598
          }
 
1599
 
 
1600
        case cff_op_hflex:
 
1601
          {
 
1602
            FT_Pos start_y;
 
1603
 
 
1604
 
 
1605
            FT_TRACE4(( " hflex" ));
 
1606
 
 
1607
            args = stack;
 
1608
 
 
1609
            /* adding six more points; 4 control points, 2 on-curve points */
 
1610
            if ( cff_builder_start_point( builder, x, y ) ||
 
1611
                 check_points( builder, 6 )               )
 
1612
              goto Fail;
 
1613
 
 
1614
            /* record the starting point's y-position for later use */
 
1615
            start_y = y;
 
1616
 
 
1617
            /* first control point */
 
1618
            x += args[0];
 
1619
            cff_builder_add_point( builder, x, y, 0 );
 
1620
 
 
1621
            /* second control point */
 
1622
            x += args[1];
 
1623
            y += args[2];
 
1624
            cff_builder_add_point( builder, x, y, 0 );
 
1625
 
 
1626
            /* join point; on curve, with y-value the same as the last */
 
1627
            /* control point's y-value                                 */
 
1628
            x += args[3];
 
1629
            cff_builder_add_point( builder, x, y, 1 );
 
1630
 
 
1631
            /* third control point, with y-value the same as the join */
 
1632
            /* point's y-value                                        */
 
1633
            x += args[4];
 
1634
            cff_builder_add_point( builder, x, y, 0 );
 
1635
 
 
1636
            /* fourth control point */
 
1637
            x += args[5];
 
1638
            y  = start_y;
 
1639
            cff_builder_add_point( builder, x, y, 0 );
 
1640
 
 
1641
            /* ending point, with y-value the same as the start point's */
 
1642
            /* y-value -- we don't add this point, though               */
 
1643
            x += args[6];
 
1644
            cff_builder_add_point( builder, x, y, 1 );
 
1645
 
 
1646
            args = stack;
 
1647
            break;
 
1648
          }
 
1649
 
 
1650
        case cff_op_flex1:
 
1651
          {
 
1652
            FT_Pos    start_x, start_y; /* record start x, y values for */
 
1653
                                        /* alter use                                */
 
1654
            FT_Fixed  dx = 0, dy = 0;   /* used in horizontal/vertical  */
 
1655
                                        /* algorithm below              */
 
1656
            FT_Int    horizontal, count;
 
1657
 
 
1658
 
 
1659
            FT_TRACE4(( " flex1" ));
 
1660
 
 
1661
            /* adding six more points; 4 control points, 2 on-curve points */
 
1662
            if ( cff_builder_start_point( builder, x, y ) ||
 
1663
                 check_points( builder, 6 )               )
 
1664
              goto Fail;
 
1665
 
 
1666
            /* record the starting point's x, y postion for later use */
 
1667
            start_x = x;
 
1668
            start_y = y;
 
1669
 
 
1670
            /* XXX: figure out whether this is supposed to be a horizontal */
 
1671
            /*      or vertical flex; the Type 2 specification is vague... */
 
1672
 
 
1673
            args = stack;
 
1674
 
 
1675
            /* grab up to the last argument */
 
1676
            for ( count = 5; count > 0; count-- )
 
1677
            {
 
1678
              dx += args[0];
 
1679
              dy += args[1];
 
1680
              args += 2;
 
1681
            }
 
1682
 
 
1683
            /* rewind */
 
1684
            args = stack;
 
1685
 
 
1686
            if ( dx < 0 ) dx = -dx;
 
1687
            if ( dy < 0 ) dy = -dy;
 
1688
 
 
1689
            /* strange test, but here it is... */
 
1690
            horizontal = ( dx > dy );
 
1691
 
 
1692
            for ( count = 5; count > 0; count-- )
 
1693
            {
 
1694
              x += args[0];
 
1695
              y += args[1];
 
1696
              cff_builder_add_point( builder, x, y, (FT_Bool)( count == 3 ) );
 
1697
              args += 2;
 
1698
            }
 
1699
 
 
1700
            /* is last operand an x- or y-delta? */
 
1701
            if ( horizontal )
 
1702
            {
 
1703
              x += args[0];
 
1704
              y  = start_y;
 
1705
            }
 
1706
            else
 
1707
            {
 
1708
              x  = start_x;
 
1709
              y += args[0];
 
1710
            }
 
1711
 
 
1712
            cff_builder_add_point( builder, x, y, 1 );
 
1713
 
 
1714
            args = stack;
 
1715
            break;
 
1716
           }
 
1717
 
 
1718
        case cff_op_flex:
 
1719
          {
 
1720
            FT_UInt  count;
 
1721
 
 
1722
 
 
1723
            FT_TRACE4(( " flex" ));
 
1724
 
 
1725
            if ( cff_builder_start_point( builder, x, y ) ||
 
1726
                 check_points( builder, 6 )               )
 
1727
              goto Fail;
 
1728
 
 
1729
            args = stack;
 
1730
            for ( count = 6; count > 0; count-- )
 
1731
            {
 
1732
              x += args[0];
 
1733
              y += args[1];
 
1734
              cff_builder_add_point( builder, x, y,
 
1735
                                     (FT_Bool)( count == 4 || count == 1 ) );
 
1736
              args += 2;
 
1737
            }
 
1738
 
 
1739
            args = stack;
 
1740
          }
 
1741
          break;
 
1742
 
 
1743
        case cff_op_endchar:
 
1744
          FT_TRACE4(( " endchar" ));
 
1745
 
 
1746
          /* We are going to emulate the seac operator. */
 
1747
          if ( num_args == 4 )
 
1748
          {
 
1749
            /* Save glyph width so that the subglyphs don't overwrite it. */
 
1750
            FT_Pos  glyph_width = decoder->glyph_width;
 
1751
 
 
1752
 
 
1753
            error = cff_operator_seac( decoder,
 
1754
                                       args[0],
 
1755
                                       args[1],
 
1756
                                       (FT_Int)( args[2] >> 16 ),
 
1757
                                       (FT_Int)( args[3] >> 16 ) );
 
1758
            args += 4;
 
1759
 
 
1760
            decoder->glyph_width = glyph_width;
 
1761
          }
 
1762
          else
 
1763
          {
 
1764
            if ( !error )
 
1765
              error = CFF_Err_Ok;
 
1766
 
 
1767
            cff_builder_close_contour( builder );
 
1768
 
 
1769
            /* close hints recording session */
 
1770
            if ( hinter )
 
1771
            {
 
1772
              if (hinter->close( hinter->hints, builder->current->n_points ) )
 
1773
                goto Syntax_Error;
 
1774
 
 
1775
              /* apply hints to the loaded glyph outline now */
 
1776
              hinter->apply( hinter->hints,
 
1777
                             builder->current,
 
1778
                             (PSH_Globals)builder->hints_globals,
 
1779
                             decoder->hint_mode );
 
1780
            }
 
1781
 
 
1782
            /* add current outline to the glyph slot */
 
1783
            FT_GlyphLoader_Add( builder->loader );
 
1784
          }
 
1785
 
 
1786
          /* return now! */
 
1787
          FT_TRACE4(( "\n\n" ));
 
1788
          return error;
 
1789
 
 
1790
        case cff_op_abs:
 
1791
          FT_TRACE4(( " abs" ));
 
1792
 
 
1793
          if ( args[0] < 0 )
 
1794
            args[0] = -args[0];
 
1795
          args++;
 
1796
          break;
 
1797
 
 
1798
        case cff_op_add:
 
1799
          FT_TRACE4(( " add" ));
 
1800
 
 
1801
          args[0] += args[1];
 
1802
          args++;
 
1803
          break;
 
1804
 
 
1805
        case cff_op_sub:
 
1806
          FT_TRACE4(( " sub" ));
 
1807
 
 
1808
          args[0] -= args[1];
 
1809
          args++;
 
1810
          break;
 
1811
 
 
1812
        case cff_op_div:
 
1813
          FT_TRACE4(( " div" ));
 
1814
 
 
1815
          args[0] = FT_DivFix( args[0], args[1] );
 
1816
          args++;
 
1817
          break;
 
1818
 
 
1819
        case cff_op_neg:
 
1820
          FT_TRACE4(( " neg" ));
 
1821
 
 
1822
          args[0] = -args[0];
 
1823
          args++;
 
1824
          break;
 
1825
 
 
1826
        case cff_op_random:
 
1827
          {
 
1828
            FT_Fixed  Rand;
 
1829
 
 
1830
 
 
1831
            FT_TRACE4(( " rand" ));
 
1832
 
 
1833
            Rand = seed;
 
1834
            if ( Rand >= 0x8000L )
 
1835
              Rand++;
 
1836
 
 
1837
            args[0] = Rand;
 
1838
            seed    = FT_MulFix( seed, 0x10000L - seed );
 
1839
            if ( seed == 0 )
 
1840
              seed += 0x2873;
 
1841
            args++;
 
1842
          }
 
1843
          break;
 
1844
 
 
1845
        case cff_op_mul:
 
1846
          FT_TRACE4(( " mul" ));
 
1847
 
 
1848
          args[0] = FT_MulFix( args[0], args[1] );
 
1849
          args++;
 
1850
          break;
 
1851
 
 
1852
        case cff_op_sqrt:
 
1853
          FT_TRACE4(( " sqrt" ));
 
1854
 
 
1855
          if ( args[0] > 0 )
 
1856
          {
 
1857
            FT_Int    count = 9;
 
1858
            FT_Fixed  root  = args[0];
 
1859
            FT_Fixed  new_root;
 
1860
 
 
1861
 
 
1862
            for (;;)
 
1863
            {
 
1864
              new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
 
1865
              if ( new_root == root || count <= 0 )
 
1866
                break;
 
1867
              root = new_root;
 
1868
            }
 
1869
            args[0] = new_root;
 
1870
          }
 
1871
          else
 
1872
            args[0] = 0;
 
1873
          args++;
 
1874
          break;
 
1875
 
 
1876
        case cff_op_drop:
 
1877
          /* nothing */
 
1878
          FT_TRACE4(( " drop" ));
 
1879
 
 
1880
          break;
 
1881
 
 
1882
        case cff_op_exch:
 
1883
          {
 
1884
            FT_Fixed  tmp;
 
1885
 
 
1886
 
 
1887
            FT_TRACE4(( " exch" ));
 
1888
 
 
1889
            tmp     = args[0];
 
1890
            args[0] = args[1];
 
1891
            args[1] = tmp;
 
1892
            args   += 2;
 
1893
          }
 
1894
          break;
 
1895
 
 
1896
        case cff_op_index:
 
1897
          {
 
1898
            FT_Int  idx = (FT_Int)( args[0] >> 16 );
 
1899
 
 
1900
 
 
1901
            FT_TRACE4(( " index" ));
 
1902
 
 
1903
            if ( idx < 0 )
 
1904
              idx = 0;
 
1905
            else if ( idx > num_args - 2 )
 
1906
              idx = num_args - 2;
 
1907
            args[0] = args[-( idx + 1 )];
 
1908
            args++;
 
1909
          }
 
1910
          break;
 
1911
 
 
1912
        case cff_op_roll:
 
1913
          {
 
1914
            FT_Int  count = (FT_Int)( args[0] >> 16 );
 
1915
            FT_Int  idx   = (FT_Int)( args[1] >> 16 );
 
1916
 
 
1917
 
 
1918
            FT_TRACE4(( " roll" ));
 
1919
 
 
1920
            if ( count <= 0 )
 
1921
              count = 1;
 
1922
 
 
1923
            args -= count;
 
1924
            if ( args < stack )
 
1925
              goto Stack_Underflow;
 
1926
 
 
1927
            if ( idx >= 0 )
 
1928
            {
 
1929
              while ( idx > 0 )
 
1930
              {
 
1931
                FT_Fixed  tmp = args[count - 1];
 
1932
                FT_Int    i;
 
1933
 
 
1934
 
 
1935
                for ( i = count - 2; i >= 0; i-- )
 
1936
                  args[i + 1] = args[i];
 
1937
                args[0] = tmp;
 
1938
                idx--;
 
1939
              }
 
1940
            }
 
1941
            else
 
1942
            {
 
1943
              while ( idx < 0 )
 
1944
              {
 
1945
                FT_Fixed  tmp = args[0];
 
1946
                FT_Int    i;
 
1947
 
 
1948
 
 
1949
                for ( i = 0; i < count - 1; i++ )
 
1950
                  args[i] = args[i + 1];
 
1951
                args[count - 1] = tmp;
 
1952
                idx++;
 
1953
              }
 
1954
            }
 
1955
            args += count;
 
1956
          }
 
1957
          break;
 
1958
 
 
1959
        case cff_op_dup:
 
1960
          FT_TRACE4(( " dup" ));
 
1961
 
 
1962
          args[1] = args[0];
 
1963
          args++;
 
1964
          break;
 
1965
 
 
1966
        case cff_op_put:
 
1967
          {
 
1968
            FT_Fixed  val = args[0];
 
1969
            FT_Int    idx = (FT_Int)( args[1] >> 16 );
 
1970
 
 
1971
 
 
1972
            FT_TRACE4(( " put" ));
 
1973
 
 
1974
            if ( idx >= 0 && idx < decoder->len_buildchar )
 
1975
              decoder->buildchar[idx] = val;
 
1976
          }
 
1977
          break;
 
1978
 
 
1979
        case cff_op_get:
 
1980
          {
 
1981
            FT_Int    idx = (FT_Int)( args[0] >> 16 );
 
1982
            FT_Fixed  val = 0;
 
1983
 
 
1984
 
 
1985
            FT_TRACE4(( " get" ));
 
1986
 
 
1987
            if ( idx >= 0 && idx < decoder->len_buildchar )
 
1988
              val = decoder->buildchar[idx];
 
1989
 
 
1990
            args[0] = val;
 
1991
            args++;
 
1992
          }
 
1993
          break;
 
1994
 
 
1995
        case cff_op_store:
 
1996
          FT_TRACE4(( " store "));
 
1997
 
 
1998
          goto Unimplemented;
 
1999
 
 
2000
        case cff_op_load:
 
2001
          FT_TRACE4(( " load" ));
 
2002
 
 
2003
          goto Unimplemented;
 
2004
 
 
2005
        case cff_op_dotsection:
 
2006
          /* this operator is deprecated and ignored by the parser */
 
2007
          FT_TRACE4(( " dotsection" ));
 
2008
          break;
 
2009
 
 
2010
        case cff_op_and:
 
2011
          {
 
2012
            FT_Fixed  cond = args[0] && args[1];
 
2013
 
 
2014
 
 
2015
            FT_TRACE4(( " and" ));
 
2016
 
 
2017
            args[0] = cond ? 0x10000L : 0;
 
2018
            args++;
 
2019
          }
 
2020
          break;
 
2021
 
 
2022
        case cff_op_or:
 
2023
          {
 
2024
            FT_Fixed  cond = args[0] || args[1];
 
2025
 
 
2026
 
 
2027
            FT_TRACE4(( " or" ));
 
2028
 
 
2029
            args[0] = cond ? 0x10000L : 0;
 
2030
            args++;
 
2031
          }
 
2032
          break;
 
2033
 
 
2034
        case cff_op_eq:
 
2035
          {
 
2036
            FT_Fixed  cond = !args[0];
 
2037
 
 
2038
 
 
2039
            FT_TRACE4(( " eq" ));
 
2040
 
 
2041
            args[0] = cond ? 0x10000L : 0;
 
2042
            args++;
 
2043
          }
 
2044
          break;
 
2045
 
 
2046
        case cff_op_ifelse:
 
2047
          {
 
2048
            FT_Fixed  cond = (args[2] <= args[3]);
 
2049
 
 
2050
 
 
2051
            FT_TRACE4(( " ifelse" ));
 
2052
 
 
2053
            if ( !cond )
 
2054
              args[0] = args[1];
 
2055
            args++;
 
2056
          }
 
2057
          break;
 
2058
 
 
2059
        case cff_op_callsubr:
 
2060
          {
 
2061
            FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
 
2062
                                      decoder->locals_bias );
 
2063
 
 
2064
 
 
2065
            FT_TRACE4(( " callsubr(%d)", idx ));
 
2066
 
 
2067
            if ( idx >= decoder->num_locals )
 
2068
            {
 
2069
              FT_ERROR(( "cff_decoder_parse_charstrings:" ));
 
2070
              FT_ERROR(( "  invalid local subr index\n" ));
 
2071
              goto Syntax_Error;
 
2072
            }
 
2073
 
 
2074
            if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
 
2075
            {
 
2076
              FT_ERROR(( "cff_decoder_parse_charstrings:"
 
2077
                         " too many nested subrs\n" ));
 
2078
              goto Syntax_Error;
 
2079
            }
 
2080
 
 
2081
            zone->cursor = ip;  /* save current instruction pointer */
 
2082
 
 
2083
            zone++;
 
2084
            zone->base   = decoder->locals[idx];
 
2085
            zone->limit  = decoder->locals[idx + 1];
 
2086
            zone->cursor = zone->base;
 
2087
 
 
2088
            if ( !zone->base )
 
2089
            {
 
2090
              FT_ERROR(( "cff_decoder_parse_charstrings:"
 
2091
                         " invoking empty subrs!\n" ));
 
2092
              goto Syntax_Error;
 
2093
            }
 
2094
 
 
2095
            decoder->zone = zone;
 
2096
            ip            = zone->base;
 
2097
            limit         = zone->limit;
 
2098
          }
 
2099
          break;
 
2100
 
 
2101
        case cff_op_callgsubr:
 
2102
          {
 
2103
            FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
 
2104
                                      decoder->globals_bias );
 
2105
 
 
2106
 
 
2107
            FT_TRACE4(( " callgsubr(%d)", idx ));
 
2108
 
 
2109
            if ( idx >= decoder->num_globals )
 
2110
            {
 
2111
              FT_ERROR(( "cff_decoder_parse_charstrings:" ));
 
2112
              FT_ERROR(( " invalid global subr index\n" ));
 
2113
              goto Syntax_Error;
 
2114
            }
 
2115
 
 
2116
            if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
 
2117
            {
 
2118
              FT_ERROR(( "cff_decoder_parse_charstrings:"
 
2119
                         " too many nested subrs\n" ));
 
2120
              goto Syntax_Error;
 
2121
            }
 
2122
 
 
2123
            zone->cursor = ip;  /* save current instruction pointer */
 
2124
 
 
2125
            zone++;
 
2126
            zone->base   = decoder->globals[idx];
 
2127
            zone->limit  = decoder->globals[idx + 1];
 
2128
            zone->cursor = zone->base;
 
2129
 
 
2130
            if ( !zone->base )
 
2131
            {
 
2132
              FT_ERROR(( "cff_decoder_parse_charstrings:"
 
2133
                         " invoking empty subrs!\n" ));
 
2134
              goto Syntax_Error;
 
2135
            }
 
2136
 
 
2137
            decoder->zone = zone;
 
2138
            ip            = zone->base;
 
2139
            limit         = zone->limit;
 
2140
          }
 
2141
          break;
 
2142
 
 
2143
        case cff_op_return:
 
2144
          FT_TRACE4(( " return" ));
 
2145
 
 
2146
          if ( decoder->zone <= decoder->zones )
 
2147
          {
 
2148
            FT_ERROR(( "cff_decoder_parse_charstrings:"
 
2149
                       " unexpected return\n" ));
 
2150
            goto Syntax_Error;
 
2151
          }
 
2152
 
 
2153
          decoder->zone--;
 
2154
          zone  = decoder->zone;
 
2155
          ip    = zone->cursor;
 
2156
          limit = zone->limit;
 
2157
          break;
 
2158
 
 
2159
        default:
 
2160
        Unimplemented:
 
2161
          FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
 
2162
 
 
2163
          if ( ip[-1] == 12 )
 
2164
            FT_ERROR(( " %d", ip[0] ));
 
2165
          FT_ERROR(( "\n" ));
 
2166
 
 
2167
          return CFF_Err_Unimplemented_Feature;
 
2168
        }
 
2169
 
 
2170
      decoder->top = args;
 
2171
 
 
2172
      } /* general operator processing */
 
2173
 
 
2174
    } /* while ip < limit */
 
2175
 
 
2176
    FT_TRACE4(( "..end..\n\n" ));
 
2177
 
 
2178
  Fail:
 
2179
    return error;
 
2180
 
 
2181
  Syntax_Error:
 
2182
    FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error!" ));
 
2183
    return CFF_Err_Invalid_File_Format;
 
2184
 
 
2185
  Stack_Underflow:
 
2186
    FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow!" ));
 
2187
    return CFF_Err_Too_Few_Arguments;
 
2188
 
 
2189
  Stack_Overflow:
 
2190
    FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow!" ));
 
2191
    return CFF_Err_Stack_Overflow;
 
2192
  }
 
2193
 
 
2194
 
 
2195
  /*************************************************************************/
 
2196
  /*************************************************************************/
 
2197
  /*************************************************************************/
 
2198
  /**********                                                      *********/
 
2199
  /**********                                                      *********/
 
2200
  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
 
2201
  /**********                                                      *********/
 
2202
  /**********    The following code is in charge of computing      *********/
 
2203
  /**********    the maximum advance width of the font.  It        *********/
 
2204
  /**********    quickly processes each glyph charstring to        *********/
 
2205
  /**********    extract the value from either a `sbw' or `seac'   *********/
 
2206
  /**********    operator.                                         *********/
 
2207
  /**********                                                      *********/
 
2208
  /*************************************************************************/
 
2209
  /*************************************************************************/
 
2210
  /*************************************************************************/
 
2211
 
 
2212
 
 
2213
#if 0 /* unused until we support pure CFF fonts */
 
2214
 
 
2215
 
 
2216
  FT_LOCAL_DEF( FT_Error )
 
2217
  cff_compute_max_advance( TT_Face  face,
 
2218
                           FT_Int*  max_advance )
 
2219
  {
 
2220
    FT_Error     error = CFF_Err_Ok;
 
2221
    CFF_Decoder  decoder;
 
2222
    FT_Int       glyph_index;
 
2223
    CFF_Font     cff = (CFF_Font)face->other;
 
2224
 
 
2225
 
 
2226
    *max_advance = 0;
 
2227
 
 
2228
    /* Initialize load decoder */
 
2229
    cff_decoder_init( &decoder, face, 0, 0, 0, 0 );
 
2230
 
 
2231
    decoder.builder.metrics_only = 1;
 
2232
    decoder.builder.load_points  = 0;
 
2233
 
 
2234
    /* For each glyph, parse the glyph charstring and extract */
 
2235
    /* the advance width.                                     */
 
2236
    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
 
2237
          glyph_index++ )
 
2238
    {
 
2239
      FT_Byte*  charstring;
 
2240
      FT_ULong  charstring_len;
 
2241
 
 
2242
 
 
2243
      /* now get load the unscaled outline */
 
2244
      error = cff_get_glyph_data( face, glyph_index,
 
2245
                                  &charstring, &charstring_len );
 
2246
      if ( !error )
 
2247
      {
 
2248
        cff_decoder_prepare( &decoder, glyph_index );
 
2249
        error = cff_decoder_parse_charstrings( &decoder,
 
2250
                                               charstring, charstring_len );
 
2251
 
 
2252
        cff_free_glyph_data( face, &charstring, &charstring_len );
 
2253
      }
 
2254
 
 
2255
      /* ignore the error if one has occurred -- skip to next glyph */
 
2256
      error = CFF_Err_Ok;
 
2257
    }
 
2258
 
 
2259
    *max_advance = decoder.builder.advance.x;
 
2260
 
 
2261
    return CFF_Err_Ok;
 
2262
  }
 
2263
 
 
2264
 
 
2265
#endif /* 0 */
 
2266
 
 
2267
 
 
2268
  /*************************************************************************/
 
2269
  /*************************************************************************/
 
2270
  /*************************************************************************/
 
2271
  /**********                                                      *********/
 
2272
  /**********                                                      *********/
 
2273
  /**********               UNHINTED GLYPH LOADER                  *********/
 
2274
  /**********                                                      *********/
 
2275
  /**********    The following code is in charge of loading a      *********/
 
2276
  /**********    single outline.  It completely ignores hinting    *********/
 
2277
  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
 
2278
  /**********                                                      *********/
 
2279
  /*************************************************************************/
 
2280
  /*************************************************************************/
 
2281
  /*************************************************************************/
 
2282
 
 
2283
 
 
2284
  FT_LOCAL_DEF( FT_Error )
 
2285
  cff_slot_load( CFF_GlyphSlot  glyph,
 
2286
                 CFF_Size       size,
 
2287
                 FT_Int         glyph_index,
 
2288
                 FT_Int32       load_flags )
 
2289
  {
 
2290
    FT_Error      error;
 
2291
    CFF_Decoder   decoder;
 
2292
    TT_Face       face     = (TT_Face)glyph->root.face;
 
2293
    FT_Bool       hinting;
 
2294
    CFF_Font      cff      = (CFF_Font)face->extra.data;
 
2295
 
 
2296
    FT_Matrix     font_matrix;
 
2297
    FT_Vector     font_offset;
 
2298
 
 
2299
 
 
2300
    if ( load_flags & FT_LOAD_NO_RECURSE )
 
2301
      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
 
2302
 
 
2303
    glyph->x_scale = 0x10000L;
 
2304
    glyph->y_scale = 0x10000L;
 
2305
    if ( size )
 
2306
    {
 
2307
      glyph->x_scale = size->root.metrics.x_scale;
 
2308
      glyph->y_scale = size->root.metrics.y_scale;
 
2309
    }
 
2310
 
 
2311
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
2312
 
 
2313
    /* try to load embedded bitmap if any              */
 
2314
    /*                                                 */
 
2315
    /* XXX: The convention should be emphasized in     */
 
2316
    /*      the documents because it can be confusing. */
 
2317
    if ( size )
 
2318
    {
 
2319
      CFF_Face      cff_face = (CFF_Face)size->root.face;
 
2320
      SFNT_Service  sfnt     = (SFNT_Service)cff_face->sfnt;
 
2321
      FT_Stream     stream   = cff_face->root.stream;
 
2322
 
 
2323
 
 
2324
      if ( size->strike_index != 0xFFFFU           &&
 
2325
           sfnt->load_sbits                        &&
 
2326
           ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
 
2327
      {
 
2328
        TT_SBit_MetricsRec  metrics;
 
2329
 
 
2330
 
 
2331
        error = sfnt->load_sbit_image( face,
 
2332
                                       (FT_ULong)size->strike_index,
 
2333
                                       (FT_UInt)glyph_index,
 
2334
                                       (FT_Int)load_flags,
 
2335
                                       stream,
 
2336
                                       &glyph->root.bitmap,
 
2337
                                       &metrics );
 
2338
 
 
2339
        if ( !error )
 
2340
        {
 
2341
          glyph->root.outline.n_points   = 0;
 
2342
          glyph->root.outline.n_contours = 0;
 
2343
 
 
2344
          glyph->root.metrics.width  = (FT_Pos)metrics.width  << 6;
 
2345
          glyph->root.metrics.height = (FT_Pos)metrics.height << 6;
 
2346
 
 
2347
          glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
 
2348
          glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
 
2349
          glyph->root.metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
 
2350
 
 
2351
          glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
 
2352
          glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
 
2353
          glyph->root.metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
 
2354
 
 
2355
          glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
 
2356
 
 
2357
          if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
 
2358
          {
 
2359
            glyph->root.bitmap_left = metrics.vertBearingX;
 
2360
            glyph->root.bitmap_top  = metrics.vertBearingY;
 
2361
          }
 
2362
          else
 
2363
          {
 
2364
            glyph->root.bitmap_left = metrics.horiBearingX;
 
2365
            glyph->root.bitmap_top  = metrics.horiBearingY;
 
2366
          }
 
2367
          return error;
 
2368
        }
 
2369
      }
 
2370
    }
 
2371
 
 
2372
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
2373
 
 
2374
    /* return immediately if we only want the embedded bitmaps */
 
2375
    if ( load_flags & FT_LOAD_SBITS_ONLY )
 
2376
      return CFF_Err_Invalid_Argument;
 
2377
 
 
2378
    glyph->root.outline.n_points   = 0;
 
2379
    glyph->root.outline.n_contours = 0;
 
2380
 
 
2381
    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
 
2382
                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
 
2383
 
 
2384
    glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;  /* by default */
 
2385
 
 
2386
    {
 
2387
      FT_Byte*  charstring;
 
2388
      FT_ULong  charstring_len;
 
2389
 
 
2390
 
 
2391
      /* in a CID-keyed font, consider `glyph_index' as a CID and map */
 
2392
      /* it immediately to the real glyph_index -- if it isn't a      */
 
2393
      /* subsetted font, glyph_indices and CIDs are identical, though */
 
2394
      if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
 
2395
           cff->charset.cids )
 
2396
        glyph_index = cff->charset.cids[glyph_index];
 
2397
 
 
2398
      cff_decoder_init( &decoder, face, size, glyph, hinting,
 
2399
                        FT_LOAD_TARGET_MODE( load_flags ) );
 
2400
 
 
2401
      decoder.builder.no_recurse =
 
2402
        (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
 
2403
 
 
2404
      /* now load the unscaled outline */
 
2405
      error = cff_get_glyph_data( face, glyph_index,
 
2406
                                  &charstring, &charstring_len );
 
2407
      if ( !error )
 
2408
      {
 
2409
        cff_decoder_prepare( &decoder, glyph_index );
 
2410
        error = cff_decoder_parse_charstrings( &decoder,
 
2411
                                               charstring, charstring_len );
 
2412
 
 
2413
        cff_free_glyph_data( face, &charstring, charstring_len );
 
2414
 
 
2415
 
 
2416
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
2417
        /* Control data and length may not be available for incremental   */
 
2418
        /* fonts.                                                         */
 
2419
        if ( face->root.internal->incremental_interface )
 
2420
        {
 
2421
          glyph->root.control_data = 0;
 
2422
          glyph->root.control_len = 0;
 
2423
        }
 
2424
        else
 
2425
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
2426
 
 
2427
        /* We set control_data and control_len if charstrings is loaded.  */
 
2428
        /* See how charstring loads at cff_index_access_element() in      */
 
2429
        /* cffload.c.                                                     */
 
2430
        {
 
2431
          CFF_IndexRec csindex = cff->charstrings_index;
 
2432
 
 
2433
 
 
2434
          glyph->root.control_data =
 
2435
            csindex.bytes + csindex.offsets[glyph_index] - 1;
 
2436
          glyph->root.control_len =
 
2437
            charstring_len;
 
2438
        }
 
2439
      }
 
2440
 
 
2441
      /* save new glyph tables */
 
2442
      cff_builder_done( &decoder.builder );
 
2443
    }
 
2444
 
 
2445
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
2446
 
 
2447
    /* Incremental fonts can optionally override the metrics. */
 
2448
    if ( !error                                                              &&
 
2449
         face->root.internal->incremental_interface                          &&
 
2450
         face->root.internal->incremental_interface->funcs->get_glyph_metrics )
 
2451
    {
 
2452
      FT_Incremental_MetricsRec  metrics;
 
2453
 
 
2454
 
 
2455
      metrics.bearing_x = decoder.builder.left_bearing.x;
 
2456
      metrics.bearing_y = decoder.builder.left_bearing.y;
 
2457
      metrics.advance   = decoder.builder.advance.x;
 
2458
      error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
 
2459
                face->root.internal->incremental_interface->object,
 
2460
                glyph_index, FALSE, &metrics );
 
2461
      decoder.builder.left_bearing.x = metrics.bearing_x;
 
2462
      decoder.builder.left_bearing.y = metrics.bearing_y;
 
2463
      decoder.builder.advance.x      = metrics.advance;
 
2464
      decoder.builder.advance.y      = 0;
 
2465
    }
 
2466
 
 
2467
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
2468
 
 
2469
    font_matrix = cff->top_font.font_dict.font_matrix;
 
2470
    font_offset = cff->top_font.font_dict.font_offset;
 
2471
 
 
2472
    /* Now, set the metrics -- this is rather simple, as   */
 
2473
    /* the left side bearing is the xMin, and the top side */
 
2474
    /* bearing the yMax.                                   */
 
2475
    if ( !error )
 
2476
    {
 
2477
      /* For composite glyphs, return only left side bearing and */
 
2478
      /* advance width.                                          */
 
2479
      if ( load_flags & FT_LOAD_NO_RECURSE )
 
2480
      {
 
2481
        FT_Slot_Internal  internal = glyph->root.internal;
 
2482
 
 
2483
 
 
2484
        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
 
2485
        glyph->root.metrics.horiAdvance  = decoder.glyph_width;
 
2486
        internal->glyph_matrix           = font_matrix;
 
2487
        internal->glyph_delta            = font_offset;
 
2488
        internal->glyph_transformed      = 1;
 
2489
      }
 
2490
      else
 
2491
      {
 
2492
        FT_BBox            cbox;
 
2493
        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
 
2494
        FT_Vector          advance;
 
2495
 
 
2496
 
 
2497
        /* copy the _unscaled_ advance width */
 
2498
        metrics->horiAdvance                    = decoder.glyph_width;
 
2499
        glyph->root.linearHoriAdvance           = decoder.glyph_width;
 
2500
        glyph->root.internal->glyph_transformed = 0;
 
2501
 
 
2502
        /* make up vertical metrics */
 
2503
        metrics->vertBearingX = 0;
 
2504
        metrics->vertBearingY = 0;
 
2505
        metrics->vertAdvance  = 0;
 
2506
 
 
2507
        glyph->root.linearVertAdvance = 0;
 
2508
 
 
2509
        glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
 
2510
 
 
2511
        glyph->root.outline.flags = 0;
 
2512
        if ( size && size->root.metrics.y_ppem < 24 )
 
2513
          glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
 
2514
 
 
2515
        glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
 
2516
 
 
2517
        /* apply the font matrix */
 
2518
        FT_Outline_Transform( &glyph->root.outline, &font_matrix );
 
2519
 
 
2520
        FT_Outline_Translate( &glyph->root.outline,
 
2521
                              font_offset.x,
 
2522
                              font_offset.y );
 
2523
 
 
2524
        advance.x = metrics->horiAdvance;
 
2525
        advance.y = 0;
 
2526
        FT_Vector_Transform( &advance, &font_matrix );
 
2527
        metrics->horiAdvance = advance.x + font_offset.x;
 
2528
        advance.x = 0;
 
2529
        advance.y = metrics->vertAdvance;
 
2530
        FT_Vector_Transform( &advance, &font_matrix );
 
2531
        metrics->vertAdvance = advance.y + font_offset.y;
 
2532
 
 
2533
        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
 
2534
        {
 
2535
          /* scale the outline and the metrics */
 
2536
          FT_Int       n;
 
2537
          FT_Outline*  cur     = &glyph->root.outline;
 
2538
          FT_Vector*   vec     = cur->points;
 
2539
          FT_Fixed     x_scale = glyph->x_scale;
 
2540
          FT_Fixed     y_scale = glyph->y_scale;
 
2541
 
 
2542
 
 
2543
          /* First of all, scale the points */
 
2544
          if ( !hinting )
 
2545
            for ( n = cur->n_points; n > 0; n--, vec++ )
 
2546
            {
 
2547
              vec->x = FT_MulFix( vec->x, x_scale );
 
2548
              vec->y = FT_MulFix( vec->y, y_scale );
 
2549
            }
 
2550
 
 
2551
          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
 
2552
 
 
2553
          /* Then scale the metrics */
 
2554
          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
 
2555
          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
 
2556
 
 
2557
          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
 
2558
          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
 
2559
 
 
2560
          if ( hinting )
 
2561
          {
 
2562
            metrics->horiAdvance  = FT_PIX_ROUND( metrics->horiAdvance );
 
2563
            metrics->vertAdvance  = FT_PIX_ROUND( metrics->vertAdvance );
 
2564
 
 
2565
            metrics->vertBearingX = FT_PIX_ROUND( metrics->vertBearingX );
 
2566
            metrics->vertBearingY = FT_PIX_ROUND( metrics->vertBearingY );
 
2567
          }
 
2568
        }
 
2569
 
 
2570
        /* compute the other metrics */
 
2571
        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
 
2572
 
 
2573
        /* grid fit the bounding box if necessary */
 
2574
        if ( hinting )
 
2575
        {
 
2576
          cbox.xMin &= -64;
 
2577
          cbox.yMin &= -64;
 
2578
          cbox.xMax  = ( cbox.xMax + 63 ) & -64;
 
2579
          cbox.yMax  = ( cbox.yMax + 63 ) & -64;
 
2580
        }
 
2581
 
 
2582
        metrics->width  = cbox.xMax - cbox.xMin;
 
2583
        metrics->height = cbox.yMax - cbox.yMin;
 
2584
 
 
2585
        metrics->horiBearingX = cbox.xMin;
 
2586
        metrics->horiBearingY = cbox.yMax;
 
2587
      }
 
2588
    }
 
2589
 
 
2590
    return error;
 
2591
  }
 
2592
 
 
2593
 
 
2594
/* END */