Coverage Report

Created: 2021-08-22 09:07

/src/skia/third_party/externals/freetype/src/truetype/ttgload.c
Line
Count
Source (jump to first uncovered line)
1
/****************************************************************************
2
 *
3
 * ttgload.c
4
 *
5
 *   TrueType Glyph Loader (body).
6
 *
7
 * Copyright (C) 1996-2021 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 <freetype/internal/ftdebug.h>
21
#include FT_CONFIG_CONFIG_H
22
#include <freetype/internal/ftcalc.h>
23
#include <freetype/internal/ftstream.h>
24
#include <freetype/internal/sfnt.h>
25
#include <freetype/tttags.h>
26
#include <freetype/ftoutln.h>
27
#include <freetype/ftdriver.h>
28
#include <freetype/ftlist.h>
29
30
#include "ttgload.h"
31
#include "ttpload.h"
32
33
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
34
#include "ttgxvar.h"
35
#endif
36
37
#include "tterrors.h"
38
#include "ttsubpix.h"
39
40
41
  /**************************************************************************
42
   *
43
   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
44
   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
45
   * messages during execution.
46
   */
47
#undef  FT_COMPONENT
48
#define FT_COMPONENT  ttgload
49
50
51
  /**************************************************************************
52
   *
53
   * Simple glyph flags.
54
   */
55
0
#define ON_CURVE_POINT  0x01  /* same value as FT_CURVE_TAG_ON            */
56
0
#define X_SHORT_VECTOR  0x02
57
0
#define Y_SHORT_VECTOR  0x04
58
0
#define REPEAT_FLAG     0x08
59
0
#define X_POSITIVE      0x10  /* two meanings depending on X_SHORT_VECTOR */
60
0
#define SAME_X          0x10
61
0
#define Y_POSITIVE      0x20  /* two meanings depending on Y_SHORT_VECTOR */
62
0
#define SAME_Y          0x20
63
0
#define OVERLAP_SIMPLE  0x40  /* retained as FT_OUTLINE_OVERLAP           */
64
65
66
  /**************************************************************************
67
   *
68
   * Composite glyph flags.
69
   */
70
0
#define ARGS_ARE_WORDS             0x0001
71
0
#define ARGS_ARE_XY_VALUES         0x0002
72
0
#define ROUND_XY_TO_GRID           0x0004
73
0
#define WE_HAVE_A_SCALE            0x0008
74
/* reserved                        0x0010 */
75
0
#define MORE_COMPONENTS            0x0020
76
0
#define WE_HAVE_AN_XY_SCALE        0x0040
77
0
#define WE_HAVE_A_2X2              0x0080
78
0
#define WE_HAVE_INSTR              0x0100
79
0
#define USE_MY_METRICS             0x0200
80
0
#define OVERLAP_COMPOUND           0x0400  /* retained as FT_OUTLINE_OVERLAP */
81
0
#define SCALED_COMPONENT_OFFSET    0x0800
82
#define UNSCALED_COMPONENT_OFFSET  0x1000
83
84
85
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
86
#define IS_DEFAULT_INSTANCE( _face )             \
87
0
          ( !( FT_IS_NAMED_INSTANCE( _face ) ||  \
88
0
               FT_IS_VARIATION( _face )      ) )
89
#else
90
#define IS_DEFAULT_INSTANCE( _face )  1
91
#endif
92
93
94
  /**************************************************************************
95
   *
96
   * Return the horizontal metrics in font units for a given glyph.
97
   */
98
  FT_LOCAL_DEF( void )
99
  TT_Get_HMetrics( TT_Face     face,
100
                   FT_UInt     idx,
101
                   FT_Short*   lsb,
102
                   FT_UShort*  aw )
103
0
  {
104
0
    ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
105
106
0
    FT_TRACE5(( "  advance width (font units): %d\n", *aw ));
107
0
    FT_TRACE5(( "  left side bearing (font units): %d\n", *lsb ));
108
0
  }
109
110
111
  /**************************************************************************
112
   *
113
   * Return the vertical metrics in font units for a given glyph.
114
   * See function `tt_loader_set_pp' below for explanations.
115
   */
116
  FT_LOCAL_DEF( void )
117
  TT_Get_VMetrics( TT_Face     face,
118
                   FT_UInt     idx,
119
                   FT_Pos      yMax,
120
                   FT_Short*   tsb,
121
                   FT_UShort*  ah )
122
0
  {
123
0
    if ( face->vertical_info )
124
0
      ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
125
126
0
    else if ( face->os2.version != 0xFFFFU )
127
0
    {
128
0
      *tsb = (FT_Short)( face->os2.sTypoAscender - yMax );
129
0
      *ah  = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
130
0
                                face->os2.sTypoDescender );
131
0
    }
132
133
0
    else
134
0
    {
135
0
      *tsb = (FT_Short)( face->horizontal.Ascender - yMax );
136
0
      *ah  = (FT_UShort)FT_ABS( face->horizontal.Ascender -
137
0
                                face->horizontal.Descender );
138
0
    }
139
140
#ifdef FT_DEBUG_LEVEL_TRACE
141
    if ( !face->vertical_info )
142
      FT_TRACE5(( "  [vertical metrics missing, computing values]\n" ));
143
#endif
144
145
0
    FT_TRACE5(( "  advance height (font units): %d\n", *ah ));
146
0
    FT_TRACE5(( "  top side bearing (font units): %d\n", *tsb ));
147
0
  }
148
149
150
  static FT_Error
151
  tt_get_metrics( TT_Loader  loader,
152
                  FT_UInt    glyph_index )
153
0
  {
154
0
    TT_Face    face   = loader->face;
155
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
156
    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
157
#endif
158
159
0
    FT_Error   error;
160
0
    FT_Stream  stream = loader->stream;
161
162
0
    FT_Short   left_bearing = 0, top_bearing = 0;
163
0
    FT_UShort  advance_width = 0, advance_height = 0;
164
165
    /* we must preserve the stream position          */
166
    /* (which gets altered by the metrics functions) */
167
0
    FT_ULong  pos = FT_STREAM_POS();
168
169
170
0
    TT_Get_HMetrics( face, glyph_index,
171
0
                     &left_bearing,
172
0
                     &advance_width );
173
0
    TT_Get_VMetrics( face, glyph_index,
174
0
                     loader->bbox.yMax,
175
0
                     &top_bearing,
176
0
                     &advance_height );
177
178
0
    if ( FT_STREAM_SEEK( pos ) )
179
0
      return error;
180
181
0
    loader->left_bearing = left_bearing;
182
0
    loader->advance      = advance_width;
183
0
    loader->top_bearing  = top_bearing;
184
0
    loader->vadvance     = advance_height;
185
186
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
187
    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
188
         loader->exec                                             )
189
    {
190
      loader->exec->sph_tweak_flags = 0;
191
192
      /* This may not be the right place for this, but it works...  */
193
      /* Note that we have to unconditionally load the tweaks since */
194
      /* it is possible that glyphs individually switch ClearType's */
195
      /* backward compatibility mode on and off.                    */
196
      sph_set_tweaks( loader, glyph_index );
197
    }
198
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
199
200
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
201
    /* With the incremental interface, these values are set by  */
202
    /* a call to `tt_get_metrics_incremental'.                  */
203
0
    if ( face->root.internal->incremental_interface == NULL )
204
0
#endif
205
0
    {
206
0
      if ( !loader->linear_def )
207
0
      {
208
0
        loader->linear_def = 1;
209
0
        loader->linear     = advance_width;
210
0
      }
211
0
    }
212
213
0
    return FT_Err_Ok;
214
0
  }
215
216
217
#ifdef FT_CONFIG_OPTION_INCREMENTAL
218
219
  static void
220
  tt_get_metrics_incremental( TT_Loader  loader,
221
                              FT_UInt    glyph_index )
222
0
  {
223
0
    TT_Face  face = loader->face;
224
225
0
    FT_Short   left_bearing = 0, top_bearing = 0;
226
0
    FT_UShort  advance_width = 0, advance_height = 0;
227
228
229
    /* If this is an incrementally loaded font check whether there are */
230
    /* overriding metrics for this glyph.                              */
231
0
    if ( face->root.internal->incremental_interface                           &&
232
0
         face->root.internal->incremental_interface->funcs->get_glyph_metrics )
233
0
    {
234
0
      FT_Incremental_MetricsRec  incr_metrics;
235
0
      FT_Error                   error;
236
237
238
0
      incr_metrics.bearing_x = loader->left_bearing;
239
0
      incr_metrics.bearing_y = 0;
240
0
      incr_metrics.advance   = loader->advance;
241
0
      incr_metrics.advance_v = 0;
242
243
0
      error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
244
0
                face->root.internal->incremental_interface->object,
245
0
                glyph_index, FALSE, &incr_metrics );
246
0
      if ( error )
247
0
        goto Exit;
248
249
0
      left_bearing  = (FT_Short)incr_metrics.bearing_x;
250
0
      advance_width = (FT_UShort)incr_metrics.advance;
251
252
#if 0
253
254
      /* GWW: Do I do the same for vertical metrics? */
255
      incr_metrics.bearing_x = 0;
256
      incr_metrics.bearing_y = loader->top_bearing;
257
      incr_metrics.advance   = loader->vadvance;
258
259
      error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
260
                face->root.internal->incremental_interface->object,
261
                glyph_index, TRUE, &incr_metrics );
262
      if ( error )
263
        goto Exit;
264
265
      top_bearing    = (FT_Short)incr_metrics.bearing_y;
266
      advance_height = (FT_UShort)incr_metrics.advance;
267
268
#endif /* 0 */
269
270
0
      loader->left_bearing = left_bearing;
271
0
      loader->advance      = advance_width;
272
0
      loader->top_bearing  = top_bearing;
273
0
      loader->vadvance     = advance_height;
274
275
0
      if ( !loader->linear_def )
276
0
      {
277
0
        loader->linear_def = 1;
278
0
        loader->linear     = advance_width;
279
0
      }
280
0
    }
281
282
0
  Exit:
283
0
    return;
284
0
  }
285
286
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
287
288
289
  /**************************************************************************
290
   *
291
   * The following functions are used by default with TrueType fonts.
292
   * However, they can be replaced by alternatives if we need to support
293
   * TrueType-compressed formats (like MicroType) in the future.
294
   *
295
   */
296
297
  FT_CALLBACK_DEF( FT_Error )
298
  TT_Access_Glyph_Frame( TT_Loader  loader,
299
                         FT_UInt    glyph_index,
300
                         FT_ULong   offset,
301
                         FT_UInt    byte_count )
302
0
  {
303
0
    FT_Error   error;
304
0
    FT_Stream  stream = loader->stream;
305
306
0
    FT_UNUSED( glyph_index );
307
308
309
    /* the following line sets the `error' variable through macros! */
310
0
    if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
311
0
      return error;
312
313
0
    loader->cursor = stream->cursor;
314
0
    loader->limit  = stream->limit;
315
316
0
    return FT_Err_Ok;
317
0
  }
318
319
320
  FT_CALLBACK_DEF( void )
321
  TT_Forget_Glyph_Frame( TT_Loader  loader )
322
0
  {
323
0
    FT_Stream  stream = loader->stream;
324
325
326
0
    FT_FRAME_EXIT();
327
0
  }
328
329
330
  FT_CALLBACK_DEF( FT_Error )
331
  TT_Load_Glyph_Header( TT_Loader  loader )
332
0
  {
333
0
    FT_Byte*  p     = loader->cursor;
334
0
    FT_Byte*  limit = loader->limit;
335
336
337
0
    if ( p + 10 > limit )
338
0
      return FT_THROW( Invalid_Outline );
339
340
0
    loader->n_contours = FT_NEXT_SHORT( p );
341
342
0
    loader->bbox.xMin = FT_NEXT_SHORT( p );
343
0
    loader->bbox.yMin = FT_NEXT_SHORT( p );
344
0
    loader->bbox.xMax = FT_NEXT_SHORT( p );
345
0
    loader->bbox.yMax = FT_NEXT_SHORT( p );
346
347
0
    FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
348
0
    FT_TRACE5(( "  xMin: %4ld  xMax: %4ld\n", loader->bbox.xMin,
349
0
                                            loader->bbox.xMax ));
350
0
    FT_TRACE5(( "  yMin: %4ld  yMax: %4ld\n", loader->bbox.yMin,
351
0
                                            loader->bbox.yMax ));
352
0
    loader->cursor = p;
353
354
0
    return FT_Err_Ok;
355
0
  }
356
357
358
  FT_CALLBACK_DEF( FT_Error )
359
  TT_Load_Simple_Glyph( TT_Loader  load )
360
0
  {
361
0
    FT_Error        error;
362
0
    FT_Byte*        p          = load->cursor;
363
0
    FT_Byte*        limit      = load->limit;
364
0
    FT_GlyphLoader  gloader    = load->gloader;
365
0
    FT_Int          n_contours = load->n_contours;
366
0
    FT_Outline*     outline;
367
0
    FT_UShort       n_ins;
368
0
    FT_Int          n_points;
369
370
0
    FT_Byte         *flag, *flag_limit;
371
0
    FT_Byte         c, count;
372
0
    FT_Vector       *vec, *vec_limit;
373
0
    FT_Pos          x, y;
374
0
    FT_Short        *cont, *cont_limit, prev_cont;
375
0
    FT_Int          xy_size = 0;
376
377
378
    /* check that we can add the contours to the glyph */
379
0
    error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
380
0
    if ( error )
381
0
      goto Fail;
382
383
    /* reading the contours' endpoints & number of points */
384
0
    cont       = gloader->current.outline.contours;
385
0
    cont_limit = cont + n_contours;
386
387
    /* check space for contours array + instructions count */
388
0
    if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
389
0
      goto Invalid_Outline;
390
391
0
    prev_cont = FT_NEXT_SHORT( p );
392
393
0
    if ( n_contours > 0 )
394
0
      cont[0] = prev_cont;
395
396
0
    if ( prev_cont < 0 )
397
0
      goto Invalid_Outline;
398
399
0
    for ( cont++; cont < cont_limit; cont++ )
400
0
    {
401
0
      cont[0] = FT_NEXT_SHORT( p );
402
0
      if ( cont[0] <= prev_cont )
403
0
      {
404
        /* unordered contours: this is invalid */
405
0
        goto Invalid_Outline;
406
0
      }
407
0
      prev_cont = cont[0];
408
0
    }
409
410
0
    n_points = 0;
411
0
    if ( n_contours > 0 )
412
0
    {
413
0
      n_points = cont[-1] + 1;
414
0
      if ( n_points < 0 )
415
0
        goto Invalid_Outline;
416
0
    }
417
418
0
    FT_TRACE5(( "  # of points: %d\n", n_points ));
419
420
    /* note that we will add four phantom points later */
421
0
    error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
422
0
    if ( error )
423
0
      goto Fail;
424
425
    /* reading the bytecode instructions */
426
0
    load->glyph->control_len  = 0;
427
0
    load->glyph->control_data = NULL;
428
429
0
    if ( p + 2 > limit )
430
0
      goto Invalid_Outline;
431
432
0
    n_ins = FT_NEXT_USHORT( p );
433
434
0
    FT_TRACE5(( "  Instructions size: %u\n", n_ins ));
435
436
0
#ifdef TT_USE_BYTECODE_INTERPRETER
437
438
0
    if ( IS_HINTED( load->load_flags ) )
439
0
    {
440
0
      FT_ULong  tmp;
441
442
443
      /* check instructions size */
444
0
      if ( ( limit - p ) < n_ins )
445
0
      {
446
0
        FT_TRACE1(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
447
0
        error = FT_THROW( Too_Many_Hints );
448
0
        goto Fail;
449
0
      }
450
451
      /* we don't trust `maxSizeOfInstructions' in the `maxp' table */
452
      /* and thus update the bytecode array size by ourselves       */
453
454
0
      tmp   = load->exec->glyphSize;
455
0
      error = Update_Max( load->exec->memory,
456
0
                          &tmp,
457
0
                          sizeof ( FT_Byte ),
458
0
                          (void*)&load->exec->glyphIns,
459
0
                          n_ins );
460
461
0
      load->exec->glyphSize = (FT_UInt)tmp;
462
0
      if ( error )
463
0
        return error;
464
465
0
      load->glyph->control_len  = n_ins;
466
0
      load->glyph->control_data = load->exec->glyphIns;
467
468
0
      if ( n_ins )
469
0
        FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
470
0
    }
471
472
0
#endif /* TT_USE_BYTECODE_INTERPRETER */
473
474
0
    p += n_ins;
475
476
0
    outline = &gloader->current.outline;
477
478
    /* reading the point tags */
479
0
    flag       = (FT_Byte*)outline->tags;
480
0
    flag_limit = flag + n_points;
481
482
0
    FT_ASSERT( flag );
483
484
0
    while ( flag < flag_limit )
485
0
    {
486
0
      if ( p + 1 > limit )
487
0
        goto Invalid_Outline;
488
489
0
      *flag++ = c = FT_NEXT_BYTE( p );
490
0
      if ( c & REPEAT_FLAG )
491
0
      {
492
0
        if ( p + 1 > limit )
493
0
          goto Invalid_Outline;
494
495
0
        count = FT_NEXT_BYTE( p );
496
0
        if ( flag + (FT_Int)count > flag_limit )
497
0
          goto Invalid_Outline;
498
499
0
        for ( ; count > 0; count-- )
500
0
          *flag++ = c;
501
0
      }
502
0
    }
503
504
    /* retain the overlap flag */
505
0
    if ( n_points && outline->tags[0] & OVERLAP_SIMPLE )
506
0
      gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
507
508
    /* reading the X coordinates */
509
510
0
    vec       = outline->points;
511
0
    vec_limit = vec + n_points;
512
0
    flag      = (FT_Byte*)outline->tags;
513
0
    x         = 0;
514
515
0
    if ( p + xy_size > limit )
516
0
      goto Invalid_Outline;
517
518
0
    for ( ; vec < vec_limit; vec++, flag++ )
519
0
    {
520
0
      FT_Pos   delta = 0;
521
0
      FT_Byte  f     = *flag;
522
523
524
0
      if ( f & X_SHORT_VECTOR )
525
0
      {
526
0
        if ( p + 1 > limit )
527
0
          goto Invalid_Outline;
528
529
0
        delta = (FT_Pos)FT_NEXT_BYTE( p );
530
0
        if ( !( f & X_POSITIVE ) )
531
0
          delta = -delta;
532
0
      }
533
0
      else if ( !( f & SAME_X ) )
534
0
      {
535
0
        if ( p + 2 > limit )
536
0
          goto Invalid_Outline;
537
538
0
        delta = (FT_Pos)FT_NEXT_SHORT( p );
539
0
      }
540
541
0
      x     += delta;
542
0
      vec->x = x;
543
0
    }
544
545
    /* reading the Y coordinates */
546
547
0
    vec       = gloader->current.outline.points;
548
0
    vec_limit = vec + n_points;
549
0
    flag      = (FT_Byte*)outline->tags;
550
0
    y         = 0;
551
552
0
    for ( ; vec < vec_limit; vec++, flag++ )
553
0
    {
554
0
      FT_Pos   delta = 0;
555
0
      FT_Byte  f     = *flag;
556
557
558
0
      if ( f & Y_SHORT_VECTOR )
559
0
      {
560
0
        if ( p + 1 > limit )
561
0
          goto Invalid_Outline;
562
563
0
        delta = (FT_Pos)FT_NEXT_BYTE( p );
564
0
        if ( !( f & Y_POSITIVE ) )
565
0
          delta = -delta;
566
0
      }
567
0
      else if ( !( f & SAME_Y ) )
568
0
      {
569
0
        if ( p + 2 > limit )
570
0
          goto Invalid_Outline;
571
572
0
        delta = (FT_Pos)FT_NEXT_SHORT( p );
573
0
      }
574
575
0
      y     += delta;
576
0
      vec->y = y;
577
578
      /* the cast is for stupid compilers */
579
0
      *flag  = (FT_Byte)( f & ON_CURVE_POINT );
580
0
    }
581
582
0
    outline->n_points   = (FT_Short)n_points;
583
0
    outline->n_contours = (FT_Short)n_contours;
584
585
0
    load->cursor = p;
586
587
0
  Fail:
588
0
    return error;
589
590
0
  Invalid_Outline:
591
0
    error = FT_THROW( Invalid_Outline );
592
0
    goto Fail;
593
0
  }
594
595
596
  FT_CALLBACK_DEF( FT_Error )
597
  TT_Load_Composite_Glyph( TT_Loader  loader )
598
0
  {
599
0
    FT_Error        error;
600
0
    FT_Byte*        p          = loader->cursor;
601
0
    FT_Byte*        limit      = loader->limit;
602
0
    FT_GlyphLoader  gloader    = loader->gloader;
603
0
    FT_Long         num_glyphs = loader->face->root.num_glyphs;
604
0
    FT_SubGlyph     subglyph;
605
0
    FT_UInt         num_subglyphs;
606
607
608
0
    num_subglyphs = 0;
609
610
0
    do
611
0
    {
612
0
      FT_Fixed  xx, xy, yy, yx;
613
0
      FT_UInt   count;
614
615
616
      /* check that we can load a new subglyph */
617
0
      error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
618
0
      if ( error )
619
0
        goto Fail;
620
621
      /* check space */
622
0
      if ( p + 4 > limit )
623
0
        goto Invalid_Composite;
624
625
0
      subglyph = gloader->current.subglyphs + num_subglyphs;
626
627
0
      subglyph->arg1 = subglyph->arg2 = 0;
628
629
0
      subglyph->flags = FT_NEXT_USHORT( p );
630
0
      subglyph->index = FT_NEXT_USHORT( p );
631
632
      /* we reject composites that have components */
633
      /* with invalid glyph indices                */
634
0
      if ( subglyph->index >= num_glyphs )
635
0
        goto Invalid_Composite;
636
637
      /* check space */
638
0
      count = 2;
639
0
      if ( subglyph->flags & ARGS_ARE_WORDS )
640
0
        count += 2;
641
0
      if ( subglyph->flags & WE_HAVE_A_SCALE )
642
0
        count += 2;
643
0
      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
644
0
        count += 4;
645
0
      else if ( subglyph->flags & WE_HAVE_A_2X2 )
646
0
        count += 8;
647
648
0
      if ( p + count > limit )
649
0
        goto Invalid_Composite;
650
651
      /* read arguments */
652
0
      if ( subglyph->flags & ARGS_ARE_XY_VALUES )
653
0
      {
654
0
        if ( subglyph->flags & ARGS_ARE_WORDS )
655
0
        {
656
0
          subglyph->arg1 = FT_NEXT_SHORT( p );
657
0
          subglyph->arg2 = FT_NEXT_SHORT( p );
658
0
        }
659
0
        else
660
0
        {
661
0
          subglyph->arg1 = FT_NEXT_CHAR( p );
662
0
          subglyph->arg2 = FT_NEXT_CHAR( p );
663
0
        }
664
0
      }
665
0
      else
666
0
      {
667
0
        if ( subglyph->flags & ARGS_ARE_WORDS )
668
0
        {
669
0
          subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p );
670
0
          subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p );
671
0
        }
672
0
        else
673
0
        {
674
0
          subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p );
675
0
          subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p );
676
0
        }
677
0
      }
678
679
      /* read transform */
680
0
      xx = yy = 0x10000L;
681
0
      xy = yx = 0;
682
683
0
      if ( subglyph->flags & WE_HAVE_A_SCALE )
684
0
      {
685
0
        xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
686
0
        yy = xx;
687
0
      }
688
0
      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
689
0
      {
690
0
        xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
691
0
        yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
692
0
      }
693
0
      else if ( subglyph->flags & WE_HAVE_A_2X2 )
694
0
      {
695
0
        xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
696
0
        yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
697
0
        xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
698
0
        yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
699
0
      }
700
701
0
      subglyph->transform.xx = xx;
702
0
      subglyph->transform.xy = xy;
703
0
      subglyph->transform.yx = yx;
704
0
      subglyph->transform.yy = yy;
705
706
0
      num_subglyphs++;
707
708
0
    } while ( subglyph->flags & MORE_COMPONENTS );
709
710
0
    gloader->current.num_subglyphs = num_subglyphs;
711
0
    FT_TRACE5(( "  %d component%s\n",
712
0
                num_subglyphs,
713
0
                num_subglyphs > 1 ? "s" : "" ));
714
715
#ifdef FT_DEBUG_LEVEL_TRACE
716
    {
717
      FT_UInt  i;
718
719
720
      subglyph = gloader->current.subglyphs;
721
722
      for ( i = 0; i < num_subglyphs; i++ )
723
      {
724
        if ( num_subglyphs > 1 )
725
          FT_TRACE7(( "    subglyph %d:\n", i ));
726
727
        FT_TRACE7(( "      glyph index: %d\n", subglyph->index ));
728
729
        if ( subglyph->flags & ARGS_ARE_XY_VALUES )
730
          FT_TRACE7(( "      offset: x=%d, y=%d\n",
731
                      subglyph->arg1,
732
                      subglyph->arg2 ));
733
        else
734
          FT_TRACE7(( "      matching points: base=%d, component=%d\n",
735
                      subglyph->arg1,
736
                      subglyph->arg2 ));
737
738
        if ( subglyph->flags & WE_HAVE_A_SCALE )
739
          FT_TRACE7(( "      scaling: %f\n",
740
                      subglyph->transform.xx / 65536.0 ));
741
        else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
742
          FT_TRACE7(( "      scaling: x=%f, y=%f\n",
743
                      subglyph->transform.xx / 65536.0,
744
                      subglyph->transform.yy / 65536.0 ));
745
        else if ( subglyph->flags & WE_HAVE_A_2X2 )
746
        {
747
          FT_TRACE7(( "      scaling: xx=%f, yx=%f\n",
748
                      subglyph->transform.xx / 65536.0,
749
                      subglyph->transform.yx / 65536.0 ));
750
          FT_TRACE7(( "               xy=%f, yy=%f\n",
751
                      subglyph->transform.xy / 65536.0,
752
                      subglyph->transform.yy / 65536.0 ));
753
        }
754
755
        subglyph++;
756
      }
757
    }
758
#endif /* FT_DEBUG_LEVEL_TRACE */
759
760
0
#ifdef TT_USE_BYTECODE_INTERPRETER
761
762
0
    {
763
0
      FT_Stream  stream = loader->stream;
764
765
766
      /* we must undo the FT_FRAME_ENTER in order to point */
767
      /* to the composite instructions, if we find some.   */
768
      /* We will process them later.                       */
769
      /*                                                   */
770
0
      loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
771
0
                                    p - limit );
772
0
    }
773
774
0
#endif
775
776
0
    loader->cursor = p;
777
778
0
  Fail:
779
0
    return error;
780
781
0
  Invalid_Composite:
782
0
    error = FT_THROW( Invalid_Composite );
783
0
    goto Fail;
784
0
  }
785
786
787
  FT_LOCAL_DEF( void )
788
  TT_Init_Glyph_Loading( TT_Face  face )
789
204
  {
790
204
    face->access_glyph_frame   = TT_Access_Glyph_Frame;
791
204
    face->read_glyph_header    = TT_Load_Glyph_Header;
792
204
    face->read_simple_glyph    = TT_Load_Simple_Glyph;
793
204
    face->read_composite_glyph = TT_Load_Composite_Glyph;
794
204
    face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
795
204
  }
796
797
798
  static void
799
  tt_prepare_zone( TT_GlyphZone  zone,
800
                   FT_GlyphLoad  load,
801
                   FT_UInt       start_point,
802
                   FT_UInt       start_contour )
803
0
  {
804
0
    zone->n_points    = (FT_UShort)load->outline.n_points -
805
0
                          (FT_UShort)start_point;
806
0
    zone->n_contours  = load->outline.n_contours -
807
0
                          (FT_Short)start_contour;
808
0
    zone->org         = load->extra_points + start_point;
809
0
    zone->cur         = load->outline.points + start_point;
810
0
    zone->orus        = load->extra_points2 + start_point;
811
0
    zone->tags        = (FT_Byte*)load->outline.tags + start_point;
812
0
    zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
813
0
    zone->first_point = (FT_UShort)start_point;
814
0
  }
815
816
817
  /**************************************************************************
818
   *
819
   * @Function:
820
   *   TT_Hint_Glyph
821
   *
822
   * @Description:
823
   *   Hint the glyph using the zone prepared by the caller.  Note that
824
   *   the zone is supposed to include four phantom points.
825
   */
826
  static FT_Error
827
  TT_Hint_Glyph( TT_Loader  loader,
828
                 FT_Bool    is_composite )
829
0
  {
830
0
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
831
0
    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
832
0
    TT_Face    face   = loader->face;
833
0
    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
834
0
#endif
835
836
0
    TT_GlyphZone  zone = &loader->zone;
837
838
0
#ifdef TT_USE_BYTECODE_INTERPRETER
839
0
    FT_Long       n_ins;
840
#else
841
    FT_UNUSED( is_composite );
842
#endif
843
844
845
0
#ifdef TT_USE_BYTECODE_INTERPRETER
846
0
    n_ins = loader->glyph->control_len;
847
848
    /* save original point positions in `org' array */
849
0
    if ( n_ins > 0 )
850
0
      FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
851
852
    /* Reset graphics state. */
853
0
    loader->exec->GS = loader->size->GS;
854
855
    /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
856
    /*      completely refer to the (already) hinted subglyphs.     */
857
0
    if ( is_composite )
858
0
    {
859
0
      loader->exec->metrics.x_scale = 1 << 16;
860
0
      loader->exec->metrics.y_scale = 1 << 16;
861
862
0
      FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
863
0
    }
864
0
    else
865
0
    {
866
0
      loader->exec->metrics.x_scale = loader->size->metrics->x_scale;
867
0
      loader->exec->metrics.y_scale = loader->size->metrics->y_scale;
868
0
    }
869
0
#endif
870
871
    /* round phantom points */
872
0
    zone->cur[zone->n_points - 4].x =
873
0
      FT_PIX_ROUND( zone->cur[zone->n_points - 4].x );
874
0
    zone->cur[zone->n_points - 3].x =
875
0
      FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
876
0
    zone->cur[zone->n_points - 2].y =
877
0
      FT_PIX_ROUND( zone->cur[zone->n_points - 2].y );
878
0
    zone->cur[zone->n_points - 1].y =
879
0
      FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
880
881
0
#ifdef TT_USE_BYTECODE_INTERPRETER
882
883
0
    if ( n_ins > 0 )
884
0
    {
885
0
      FT_Error  error;
886
887
0
      FT_GlyphLoader  gloader         = loader->gloader;
888
0
      FT_Outline      current_outline = gloader->current.outline;
889
890
891
0
      TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
892
0
                        loader->exec->glyphIns, n_ins );
893
894
0
      loader->exec->is_composite = is_composite;
895
0
      loader->exec->pts          = *zone;
896
897
0
      error = TT_Run_Context( loader->exec );
898
0
      if ( error && loader->exec->pedantic_hinting )
899
0
        return error;
900
901
      /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
902
0
      current_outline.tags[0] |=
903
0
        ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
904
0
    }
905
906
0
#endif
907
908
0
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
909
    /* Save possibly modified glyph phantom points unless in v40 backward  */
910
    /* compatibility mode, where no movement on the x axis means no reason */
911
    /* to change bearings or advance widths.                               */
912
0
    if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
913
0
            loader->exec->backward_compatibility ) )
914
0
    {
915
0
#endif
916
0
      loader->pp1 = zone->cur[zone->n_points - 4];
917
0
      loader->pp2 = zone->cur[zone->n_points - 3];
918
0
      loader->pp3 = zone->cur[zone->n_points - 2];
919
0
      loader->pp4 = zone->cur[zone->n_points - 1];
920
0
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
921
0
    }
922
0
#endif
923
924
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
925
    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
926
    {
927
      if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
928
        FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 );
929
930
      else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
931
        FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
932
    }
933
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
934
935
0
    return FT_Err_Ok;
936
0
  }
937
938
939
  /**************************************************************************
940
   *
941
   * @Function:
942
   *   TT_Process_Simple_Glyph
943
   *
944
   * @Description:
945
   *   Once a simple glyph has been loaded, it needs to be processed.
946
   *   Usually, this means scaling and hinting through bytecode
947
   *   interpretation.
948
   */
949
  static FT_Error
950
  TT_Process_Simple_Glyph( TT_Loader  loader )
951
0
  {
952
0
    FT_GlyphLoader  gloader = loader->gloader;
953
0
    FT_Error        error   = FT_Err_Ok;
954
0
    FT_Outline*     outline;
955
0
    FT_Int          n_points;
956
957
0
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
958
0
    FT_Memory   memory    = loader->face->root.memory;
959
0
    FT_Vector*  unrounded = NULL;
960
0
#endif
961
962
963
0
    outline  = &gloader->current.outline;
964
0
    n_points = outline->n_points;
965
966
    /* set phantom points */
967
968
0
    outline->points[n_points    ] = loader->pp1;
969
0
    outline->points[n_points + 1] = loader->pp2;
970
0
    outline->points[n_points + 2] = loader->pp3;
971
0
    outline->points[n_points + 3] = loader->pp4;
972
973
0
    outline->tags[n_points    ] = 0;
974
0
    outline->tags[n_points + 1] = 0;
975
0
    outline->tags[n_points + 2] = 0;
976
0
    outline->tags[n_points + 3] = 0;
977
978
0
    n_points += 4;
979
980
0
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
981
982
0
    if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
983
0
    {
984
0
      if ( FT_NEW_ARRAY( unrounded, n_points ) )
985
0
        goto Exit;
986
987
      /* Deltas apply to the unscaled data. */
988
0
      error = TT_Vary_Apply_Glyph_Deltas( loader->face,
989
0
                                          loader->glyph_index,
990
0
                                          outline,
991
0
                                          unrounded,
992
0
                                          (FT_UInt)n_points );
993
994
      /* recalculate linear horizontal and vertical advances */
995
      /* if we don't have HVAR and VVAR, respectively        */
996
997
      /* XXX: change all FreeType modules to store `linear' and `vadvance' */
998
      /*      in 26.6 format before the `base' module scales them to 16.16 */
999
0
      if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
1000
0
        loader->linear = FT_PIX_ROUND( unrounded[n_points - 3].x -
1001
0
                                       unrounded[n_points - 4].x ) / 64;
1002
0
      if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
1003
0
        loader->vadvance = FT_PIX_ROUND( unrounded[n_points - 1].x -
1004
0
                                         unrounded[n_points - 2].x ) / 64;
1005
1006
0
      if ( error )
1007
0
        goto Exit;
1008
0
    }
1009
1010
0
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1011
1012
0
    if ( IS_HINTED( loader->load_flags ) )
1013
0
    {
1014
0
      tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
1015
1016
0
      FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
1017
0
                     loader->zone.n_points + 4 );
1018
0
    }
1019
1020
0
    {
1021
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1022
      TT_Face    face   = loader->face;
1023
      TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
1024
1025
      FT_String*  family         = face->root.family_name;
1026
      FT_UInt     ppem           = loader->size->metrics->x_ppem;
1027
      FT_String*  style          = face->root.style_name;
1028
      FT_UInt     x_scale_factor = 1000;
1029
#endif
1030
1031
0
      FT_Vector*  vec   = outline->points;
1032
0
      FT_Vector*  limit = outline->points + n_points;
1033
1034
0
      FT_Fixed  x_scale = 0; /* pacify compiler */
1035
0
      FT_Fixed  y_scale = 0;
1036
1037
0
      FT_Bool  do_scale = FALSE;
1038
1039
1040
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1041
1042
      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
1043
      {
1044
        /* scale, but only if enabled and only if TT hinting is being used */
1045
        if ( IS_HINTED( loader->load_flags ) )
1046
          x_scale_factor = sph_test_tweak_x_scaling( face,
1047
                                                     family,
1048
                                                     ppem,
1049
                                                     style,
1050
                                                     loader->glyph_index );
1051
        /* scale the glyph */
1052
        if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
1053
             x_scale_factor != 1000                         )
1054
        {
1055
          x_scale = FT_MulDiv( loader->size->metrics->x_scale,
1056
                               (FT_Long)x_scale_factor, 1000 );
1057
          y_scale = loader->size->metrics->y_scale;
1058
1059
          /* compensate for any scaling by de/emboldening; */
1060
          /* the amount was determined via experimentation */
1061
          if ( x_scale_factor != 1000 && ppem > 11 )
1062
          {
1063
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1064
            FT_Vector*  orig_points = outline->points;
1065
1066
1067
            if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
1068
              outline->points = unrounded;
1069
#endif
1070
            FT_Outline_EmboldenXY( outline,
1071
                                   FT_MulFix( 1280 * ppem,
1072
                                              1000 - x_scale_factor ),
1073
                                   0 );
1074
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1075
            if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
1076
              outline->points = orig_points;
1077
#endif
1078
          }
1079
          do_scale = TRUE;
1080
        }
1081
      }
1082
      else
1083
1084
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
1085
1086
0
      {
1087
        /* scale the glyph */
1088
0
        if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1089
0
        {
1090
0
          x_scale = loader->size->metrics->x_scale;
1091
0
          y_scale = loader->size->metrics->y_scale;
1092
1093
0
          do_scale = TRUE;
1094
0
        }
1095
0
      }
1096
1097
0
      if ( do_scale )
1098
0
      {
1099
0
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1100
0
        if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
1101
0
        {
1102
0
          FT_Vector*  u = unrounded;
1103
1104
1105
0
          for ( ; vec < limit; vec++, u++ )
1106
0
          {
1107
0
            vec->x = ( FT_MulFix( u->x, x_scale ) + 32 ) >> 6;
1108
0
            vec->y = ( FT_MulFix( u->y, y_scale ) + 32 ) >> 6;
1109
0
          }
1110
0
        }
1111
0
        else
1112
0
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1113
0
        {
1114
0
          for ( ; vec < limit; vec++ )
1115
0
          {
1116
0
            vec->x = FT_MulFix( vec->x, x_scale );
1117
0
            vec->y = FT_MulFix( vec->y, y_scale );
1118
0
          }
1119
0
        }
1120
0
      }
1121
1122
0
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1123
      /* if we have a HVAR table, `pp1' and/or `pp2' */
1124
      /* are already adjusted but unscaled           */
1125
0
      if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) &&
1126
0
           IS_HINTED( loader->load_flags )                                 )
1127
0
      {
1128
0
        loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1129
0
        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1130
        /* pp1.y and pp2.y are always zero */
1131
0
      }
1132
0
      else
1133
0
#endif
1134
0
      {
1135
0
        loader->pp1 = outline->points[n_points - 4];
1136
0
        loader->pp2 = outline->points[n_points - 3];
1137
0
      }
1138
1139
0
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1140
      /* if we have a VVAR table, `pp3' and/or `pp4' */
1141
      /* are already adjusted but unscaled           */
1142
0
      if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) &&
1143
0
           IS_HINTED( loader->load_flags )                                 )
1144
0
      {
1145
0
        loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1146
0
        loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1147
0
        loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1148
0
        loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1149
0
      }
1150
0
      else
1151
0
#endif
1152
0
      {
1153
0
        loader->pp3 = outline->points[n_points - 2];
1154
0
        loader->pp4 = outline->points[n_points - 1];
1155
0
      }
1156
0
    }
1157
1158
0
    if ( IS_HINTED( loader->load_flags ) )
1159
0
    {
1160
0
      loader->zone.n_points += 4;
1161
1162
0
      error = TT_Hint_Glyph( loader, 0 );
1163
0
    }
1164
1165
0
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1166
0
  Exit:
1167
0
    FT_FREE( unrounded );
1168
0
#endif
1169
1170
0
    return error;
1171
0
  }
1172
1173
1174
  /**************************************************************************
1175
   *
1176
   * @Function:
1177
   *   TT_Process_Composite_Component
1178
   *
1179
   * @Description:
1180
   *   Once a composite component has been loaded, it needs to be
1181
   *   processed.  Usually, this means transforming and translating.
1182
   */
1183
  static FT_Error
1184
  TT_Process_Composite_Component( TT_Loader    loader,
1185
                                  FT_SubGlyph  subglyph,
1186
                                  FT_UInt      start_point,
1187
                                  FT_UInt      num_base_points )
1188
0
  {
1189
0
    FT_GlyphLoader  gloader = loader->gloader;
1190
0
    FT_Outline      current;
1191
0
    FT_Bool         have_scale;
1192
0
    FT_Pos          x, y;
1193
1194
1195
0
    current.points   = gloader->base.outline.points +
1196
0
                         num_base_points;
1197
0
    current.n_points = gloader->base.outline.n_points -
1198
0
                         (short)num_base_points;
1199
1200
0
    have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
1201
0
                                              WE_HAVE_AN_XY_SCALE |
1202
0
                                              WE_HAVE_A_2X2       ) );
1203
1204
    /* perform the transform required for this subglyph */
1205
0
    if ( have_scale )
1206
0
      FT_Outline_Transform( &current, &subglyph->transform );
1207
1208
    /* get offset */
1209
0
    if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
1210
0
    {
1211
0
      FT_UInt     num_points = (FT_UInt)gloader->base.outline.n_points;
1212
0
      FT_UInt     k = (FT_UInt)subglyph->arg1;
1213
0
      FT_UInt     l = (FT_UInt)subglyph->arg2;
1214
0
      FT_Vector*  p1;
1215
0
      FT_Vector*  p2;
1216
1217
1218
      /* match l-th point of the newly loaded component to the k-th point */
1219
      /* of the previously loaded components.                             */
1220
1221
      /* change to the point numbers used by our outline */
1222
0
      k += start_point;
1223
0
      l += num_base_points;
1224
0
      if ( k >= num_base_points ||
1225
0
           l >= num_points      )
1226
0
        return FT_THROW( Invalid_Composite );
1227
1228
0
      p1 = gloader->base.outline.points + k;
1229
0
      p2 = gloader->base.outline.points + l;
1230
1231
0
      x = p1->x - p2->x;
1232
0
      y = p1->y - p2->y;
1233
0
    }
1234
0
    else
1235
0
    {
1236
0
      x = subglyph->arg1;
1237
0
      y = subglyph->arg2;
1238
1239
0
      if ( !x && !y )
1240
0
        return FT_Err_Ok;
1241
1242
      /* Use a default value dependent on                                  */
1243
      /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old */
1244
      /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit.            */
1245
1246
0
      if ( have_scale &&
1247
#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
1248
           !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
1249
#else
1250
0
            ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
1251
0
#endif
1252
0
      {
1253
1254
#if 0
1255
1256
        /********************************************************************
1257
         *
1258
         * This algorithm is what Apple documents.  But it doesn't work.
1259
         */
1260
        int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
1261
                                            : -subglyph->transform.xx;
1262
        int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
1263
                                            : -subglyph->transform.yx;
1264
        int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
1265
                                            : -subglyph->transform.xy;
1266
        int  d = subglyph->transform.yy > 0 ?  subglyph->transform.yy
1267
                                            : -subglyph->transform.yy;
1268
        int  m = a > b ? a : b;
1269
        int  n = c > d ? c : d;
1270
1271
1272
        if ( a - b <= 33 && a - b >= -33 )
1273
          m *= 2;
1274
        if ( c - d <= 33 && c - d >= -33 )
1275
          n *= 2;
1276
        x = FT_MulFix( x, m );
1277
        y = FT_MulFix( y, n );
1278
1279
#else /* 1 */
1280
1281
        /********************************************************************
1282
         *
1283
         * This algorithm is a guess and works much better than the above.
1284
         */
1285
0
        FT_Fixed  mac_xscale = FT_Hypot( subglyph->transform.xx,
1286
0
                                         subglyph->transform.xy );
1287
0
        FT_Fixed  mac_yscale = FT_Hypot( subglyph->transform.yy,
1288
0
                                         subglyph->transform.yx );
1289
1290
1291
0
        x = FT_MulFix( x, mac_xscale );
1292
0
        y = FT_MulFix( y, mac_yscale );
1293
1294
0
#endif /* 1 */
1295
1296
0
      }
1297
1298
0
      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1299
0
      {
1300
0
        FT_Fixed  x_scale = loader->size->metrics->x_scale;
1301
0
        FT_Fixed  y_scale = loader->size->metrics->y_scale;
1302
1303
1304
0
        x = FT_MulFix( x, x_scale );
1305
0
        y = FT_MulFix( y, y_scale );
1306
1307
0
        if ( subglyph->flags & ROUND_XY_TO_GRID )
1308
0
        {
1309
0
          TT_Face    face   = loader->face;
1310
0
          TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
1311
1312
1313
0
          if ( IS_HINTED( loader->load_flags ) )
1314
0
          {
1315
            /*
1316
             * We round the horizontal offset only if there is hinting along
1317
             * the x axis; this corresponds to integer advance width values.
1318
             *
1319
             * Theoretically, a glyph's bytecode can toggle ClearType's
1320
             * `backward compatibility' mode, which would allow modification
1321
             * of the advance width.  In reality, however, applications
1322
             * neither allow nor expect modified advance widths if subpixel
1323
             * rendering is active.
1324
             *
1325
             */
1326
0
            if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 )
1327
0
              x = FT_PIX_ROUND( x );
1328
1329
0
            y = FT_PIX_ROUND( y );
1330
0
          }
1331
0
        }
1332
0
      }
1333
0
    }
1334
1335
0
    if ( x || y )
1336
0
      FT_Outline_Translate( &current, x, y );
1337
1338
0
    return FT_Err_Ok;
1339
0
  }
1340
1341
1342
  /**************************************************************************
1343
   *
1344
   * @Function:
1345
   *   TT_Process_Composite_Glyph
1346
   *
1347
   * @Description:
1348
   *   This is slightly different from TT_Process_Simple_Glyph, in that
1349
   *   its sole purpose is to hint the glyph.  Thus this function is
1350
   *   only available when bytecode interpreter is enabled.
1351
   */
1352
  static FT_Error
1353
  TT_Process_Composite_Glyph( TT_Loader  loader,
1354
                              FT_UInt    start_point,
1355
                              FT_UInt    start_contour )
1356
0
  {
1357
0
    FT_Error     error;
1358
0
    FT_Outline*  outline;
1359
0
    FT_UInt      i;
1360
1361
1362
0
    outline = &loader->gloader->base.outline;
1363
1364
    /* make room for phantom points */
1365
0
    error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1366
0
                                         outline->n_points + 4,
1367
0
                                         0 );
1368
0
    if ( error )
1369
0
      return error;
1370
1371
0
    outline->points[outline->n_points    ] = loader->pp1;
1372
0
    outline->points[outline->n_points + 1] = loader->pp2;
1373
0
    outline->points[outline->n_points + 2] = loader->pp3;
1374
0
    outline->points[outline->n_points + 3] = loader->pp4;
1375
1376
0
    outline->tags[outline->n_points    ] = 0;
1377
0
    outline->tags[outline->n_points + 1] = 0;
1378
0
    outline->tags[outline->n_points + 2] = 0;
1379
0
    outline->tags[outline->n_points + 3] = 0;
1380
1381
0
#ifdef TT_USE_BYTECODE_INTERPRETER
1382
1383
0
    {
1384
0
      FT_Stream  stream = loader->stream;
1385
0
      FT_UShort  n_ins, max_ins;
1386
0
      FT_ULong   tmp;
1387
1388
1389
      /* TT_Load_Composite_Glyph only gives us the offset of instructions */
1390
      /* so we read them here                                             */
1391
0
      if ( FT_STREAM_SEEK( loader->ins_pos ) ||
1392
0
           FT_READ_USHORT( n_ins )           )
1393
0
        return error;
1394
1395
0
      FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
1396
1397
      /* check it */
1398
0
      max_ins = loader->face->max_profile.maxSizeOfInstructions;
1399
0
      if ( n_ins > max_ins )
1400
0
      {
1401
        /* don't trust `maxSizeOfInstructions'; */
1402
        /* only do a rough safety check         */
1403
0
        if ( (FT_Int)n_ins > loader->byte_len )
1404
0
        {
1405
0
          FT_TRACE1(( "TT_Process_Composite_Glyph:"
1406
0
                      " too many instructions (%d) for glyph with length %d\n",
1407
0
                      n_ins, loader->byte_len ));
1408
0
          return FT_THROW( Too_Many_Hints );
1409
0
        }
1410
1411
0
        tmp   = loader->exec->glyphSize;
1412
0
        error = Update_Max( loader->exec->memory,
1413
0
                            &tmp,
1414
0
                            sizeof ( FT_Byte ),
1415
0
                            (void*)&loader->exec->glyphIns,
1416
0
                            n_ins );
1417
1418
0
        loader->exec->glyphSize = (FT_UShort)tmp;
1419
0
        if ( error )
1420
0
          return error;
1421
0
      }
1422
0
      else if ( n_ins == 0 )
1423
0
        return FT_Err_Ok;
1424
1425
0
      if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
1426
0
        return error;
1427
1428
0
      loader->glyph->control_data = loader->exec->glyphIns;
1429
0
      loader->glyph->control_len  = n_ins;
1430
0
    }
1431
1432
0
#endif
1433
1434
0
    tt_prepare_zone( &loader->zone, &loader->gloader->base,
1435
0
                     start_point, start_contour );
1436
1437
    /* Some points are likely touched during execution of  */
1438
    /* instructions on components.  So let's untouch them. */
1439
0
    for ( i = 0; i < loader->zone.n_points; i++ )
1440
0
      loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
1441
1442
0
    loader->zone.n_points += 4;
1443
1444
0
    return TT_Hint_Glyph( loader, 1 );
1445
0
  }
1446
1447
1448
  /*
1449
   * Calculate the phantom points
1450
   *
1451
   * Defining the right side bearing (rsb) as
1452
   *
1453
   *   rsb = aw - (lsb + xmax - xmin)
1454
   *
1455
   * (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
1456
   * and `xmax' the glyph's minimum and maximum x value), the OpenType
1457
   * specification defines the initial position of horizontal phantom points
1458
   * as
1459
   *
1460
   *   pp1 = (round(xmin - lsb), 0)      ,
1461
   *   pp2 = (round(pp1 + aw), 0)        .
1462
   *
1463
   * Note that the rounding to the grid (in the device space) is not
1464
   * documented currently in the specification.
1465
   *
1466
   * However, the specification lacks the precise definition of vertical
1467
   * phantom points.  Greg Hitchcock provided the following explanation.
1468
   *
1469
   * - a `vmtx' table is present
1470
   *
1471
   *   For any glyph, the minimum and maximum y values (`ymin' and `ymax')
1472
   *   are given in the `glyf' table, the top side bearing (tsb) and advance
1473
   *   height (ah) are given in the `vmtx' table.  The bottom side bearing
1474
   *   (bsb) is then calculated as
1475
   *
1476
   *     bsb = ah - (tsb + ymax - ymin)       ,
1477
   *
1478
   *   and the initial position of vertical phantom points is
1479
   *
1480
   *     pp3 = (x, round(ymax + tsb))       ,
1481
   *     pp4 = (x, round(pp3 - ah))         .
1482
   *
1483
   *   See below for value `x'.
1484
   *
1485
   * - no `vmtx' table in the font
1486
   *
1487
   *   If there is an `OS/2' table, we set
1488
   *
1489
   *     DefaultAscender = sTypoAscender       ,
1490
   *     DefaultDescender = sTypoDescender     ,
1491
   *
1492
   *   otherwise we use data from the `hhea' table:
1493
   *
1494
   *     DefaultAscender = Ascender         ,
1495
   *     DefaultDescender = Descender       .
1496
   *
1497
   *   With these two variables we can now set
1498
   *
1499
   *     ah = DefaultAscender - sDefaultDescender    ,
1500
   *     tsb = DefaultAscender - yMax                ,
1501
   *
1502
   *   and proceed as if a `vmtx' table was present.
1503
   *
1504
   * Usually we have
1505
   *
1506
   *   x = aw / 2      ,                                                (1)
1507
   *
1508
   * but there is one compatibility case where it can be set to
1509
   *
1510
   *   x = -DefaultDescender -
1511
   *         ((DefaultAscender - DefaultDescender - aw) / 2)     .      (2)
1512
   *
1513
   * and another one with
1514
   *
1515
   *   x = 0     .                                                      (3)
1516
   *
1517
   * In Windows, the history of those values is quite complicated,
1518
   * depending on the hinting engine (that is, the graphics framework).
1519
   *
1520
   *   framework        from                 to       formula
1521
   *  ----------------------------------------------------------
1522
   *    GDI       Windows 98               current      (1)
1523
   *              (Windows 2000 for NT)
1524
   *    GDI+      Windows XP               Windows 7    (2)
1525
   *    GDI+      Windows 8                current      (3)
1526
   *    DWrite    Windows 7                current      (3)
1527
   *
1528
   * For simplicity, FreeType uses (1) for grayscale subpixel hinting and
1529
   * (3) for everything else.
1530
   *
1531
   */
1532
  static void
1533
  tt_loader_set_pp( TT_Loader  loader )
1534
0
  {
1535
0
    FT_Bool  subpixel_hinting = 0;
1536
0
    FT_Bool  grayscale        = 0;
1537
0
    FT_Bool  use_aw_2         = 0;
1538
1539
0
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
1540
0
    TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
1541
0
#endif
1542
1543
1544
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1545
    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
1546
    {
1547
      subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting
1548
                                      : 0;
1549
      grayscale        = loader->exec ? loader->exec->grayscale
1550
                                      : 0;
1551
    }
1552
#endif
1553
0
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1554
0
    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
1555
0
    {
1556
0
      subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean
1557
0
                                      : 0;
1558
0
      grayscale        = loader->exec ? loader->exec->grayscale_cleartype
1559
0
                                      : 0;
1560
0
    }
1561
0
#endif
1562
1563
0
    use_aw_2 = FT_BOOL( subpixel_hinting && grayscale );
1564
1565
0
    loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
1566
0
    loader->pp1.y = 0;
1567
0
    loader->pp2.x = loader->pp1.x + loader->advance;
1568
0
    loader->pp2.y = 0;
1569
1570
0
    loader->pp3.x = use_aw_2 ? loader->advance / 2 : 0;
1571
0
    loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
1572
0
    loader->pp4.x = use_aw_2 ? loader->advance / 2 : 0;
1573
0
    loader->pp4.y = loader->pp3.y - loader->vadvance;
1574
0
  }
1575
1576
1577
  /* a utility function to retrieve i-th node from given FT_List */
1578
  static FT_ListNode
1579
  ft_list_get_node_at( FT_List  list,
1580
                       FT_UInt  idx )
1581
0
  {
1582
0
    FT_ListNode  cur;
1583
1584
1585
0
    if ( !list )
1586
0
      return NULL;
1587
1588
0
    for ( cur = list->head; cur; cur = cur->next )
1589
0
    {
1590
0
      if ( !idx )
1591
0
        return cur;
1592
1593
0
      idx--;
1594
0
    }
1595
1596
0
    return NULL;
1597
0
  }
1598
1599
1600
  /**************************************************************************
1601
   *
1602
   * @Function:
1603
   *   load_truetype_glyph
1604
   *
1605
   * @Description:
1606
   *   Loads a given truetype glyph.  Handles composites and uses a
1607
   *   TT_Loader object.
1608
   */
1609
  static FT_Error
1610
  load_truetype_glyph( TT_Loader  loader,
1611
                       FT_UInt    glyph_index,
1612
                       FT_UInt    recurse_count,
1613
                       FT_Bool    header_only )
1614
0
  {
1615
0
    FT_Error        error   = FT_Err_Ok;
1616
0
    FT_Fixed        x_scale, y_scale;
1617
0
    FT_ULong        offset;
1618
0
    TT_Face         face    = loader->face;
1619
0
    FT_GlyphLoader  gloader = loader->gloader;
1620
1621
0
    FT_Bool  opened_frame = 0;
1622
1623
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
1624
0
    FT_StreamRec    inc_stream;
1625
0
    FT_Data         glyph_data;
1626
0
    FT_Bool         glyph_data_loaded = 0;
1627
0
#endif
1628
1629
1630
#ifdef FT_DEBUG_LEVEL_TRACE
1631
    if ( recurse_count )
1632
      FT_TRACE5(( "  nesting level: %d\n", recurse_count ));
1633
#endif
1634
1635
    /* some fonts have an incorrect value of `maxComponentDepth' */
1636
0
    if ( recurse_count > face->max_profile.maxComponentDepth )
1637
0
    {
1638
0
      FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n",
1639
0
                  recurse_count ));
1640
0
      face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
1641
0
    }
1642
1643
#ifndef FT_CONFIG_OPTION_INCREMENTAL
1644
    /* check glyph index */
1645
    if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1646
    {
1647
      error = FT_THROW( Invalid_Glyph_Index );
1648
      goto Exit;
1649
    }
1650
#endif
1651
1652
0
    loader->glyph_index = glyph_index;
1653
1654
0
    if ( loader->load_flags & FT_LOAD_NO_SCALE )
1655
0
    {
1656
0
      x_scale = 0x10000L;
1657
0
      y_scale = 0x10000L;
1658
0
    }
1659
0
    else
1660
0
    {
1661
0
      x_scale = loader->size->metrics->x_scale;
1662
0
      y_scale = loader->size->metrics->y_scale;
1663
0
    }
1664
1665
    /* Set `offset' to the start of the glyph relative to the start of */
1666
    /* the `glyf' table, and `byte_len' to the length of the glyph in  */
1667
    /* bytes.                                                          */
1668
1669
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
1670
1671
    /* If we are loading glyph data via the incremental interface, set */
1672
    /* the loader stream to a memory stream reading the data returned  */
1673
    /* by the interface.                                               */
1674
0
    if ( face->root.internal->incremental_interface )
1675
0
    {
1676
0
      error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1677
0
                face->root.internal->incremental_interface->object,
1678
0
                glyph_index, &glyph_data );
1679
0
      if ( error )
1680
0
        goto Exit;
1681
1682
0
      glyph_data_loaded = 1;
1683
0
      offset            = 0;
1684
0
      loader->byte_len  = glyph_data.length;
1685
1686
0
      FT_ZERO( &inc_stream );
1687
0
      FT_Stream_OpenMemory( &inc_stream,
1688
0
                            glyph_data.pointer,
1689
0
                            (FT_ULong)glyph_data.length );
1690
1691
0
      loader->stream = &inc_stream;
1692
0
    }
1693
0
    else
1694
1695
0
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1696
1697
0
      offset = tt_face_get_location( face, glyph_index,
1698
0
                                     (FT_UInt*)&loader->byte_len );
1699
1700
0
    if ( loader->byte_len > 0 )
1701
0
    {
1702
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
1703
      /* for the incremental interface, `glyf_offset' is always zero */
1704
0
      if ( !face->glyf_offset                          &&
1705
0
           !face->root.internal->incremental_interface )
1706
#else
1707
      if ( !face->glyf_offset )
1708
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1709
0
      {
1710
0
        FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
1711
0
        error = FT_THROW( Invalid_Table );
1712
0
        goto Exit;
1713
0
      }
1714
1715
0
      error = face->access_glyph_frame( loader, glyph_index,
1716
0
                                        face->glyf_offset + offset,
1717
0
                                        (FT_UInt)loader->byte_len );
1718
0
      if ( error )
1719
0
        goto Exit;
1720
1721
      /* read glyph header first */
1722
0
      error = face->read_glyph_header( loader );
1723
1724
0
      face->forget_glyph_frame( loader );
1725
1726
0
      if ( error )
1727
0
        goto Exit;
1728
0
    }
1729
1730
    /* a space glyph */
1731
0
    if ( loader->byte_len == 0 || loader->n_contours == 0 )
1732
0
    {
1733
0
      loader->bbox.xMin = 0;
1734
0
      loader->bbox.xMax = 0;
1735
0
      loader->bbox.yMin = 0;
1736
0
      loader->bbox.yMax = 0;
1737
0
    }
1738
1739
    /* the metrics must be computed after loading the glyph header */
1740
    /* since we need the glyph's `yMax' value in case the vertical */
1741
    /* metrics must be emulated                                    */
1742
0
    error = tt_get_metrics( loader, glyph_index );
1743
0
    if ( error )
1744
0
      goto Exit;
1745
1746
0
    if ( header_only )
1747
0
      goto Exit;
1748
1749
0
    if ( loader->byte_len == 0 || loader->n_contours == 0 )
1750
0
    {
1751
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
1752
0
      tt_get_metrics_incremental( loader, glyph_index );
1753
0
#endif
1754
0
      tt_loader_set_pp( loader );
1755
1756
1757
0
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1758
1759
0
      if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1760
0
           FT_IS_VARIATION( FT_FACE( face ) )      )
1761
0
      {
1762
        /* a small outline structure with four elements for */
1763
        /* communication with `TT_Vary_Apply_Glyph_Deltas'  */
1764
0
        FT_Vector   points[4];
1765
0
        char        tags[4]     = { 1, 1, 1, 1 };
1766
0
        short       contours[4] = { 0, 1, 2, 3 };
1767
0
        FT_Outline  outline;
1768
1769
        /* unrounded values */
1770
0
        FT_Vector  unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1771
1772
1773
0
        points[0].x = loader->pp1.x;
1774
0
        points[0].y = loader->pp1.y;
1775
0
        points[1].x = loader->pp2.x;
1776
0
        points[1].y = loader->pp2.y;
1777
1778
0
        points[2].x = loader->pp3.x;
1779
0
        points[2].y = loader->pp3.y;
1780
0
        points[3].x = loader->pp4.x;
1781
0
        points[3].y = loader->pp4.y;
1782
1783
0
        outline.n_points   = 4;
1784
0
        outline.n_contours = 4;
1785
0
        outline.points     = points;
1786
0
        outline.tags       = tags;
1787
0
        outline.contours   = contours;
1788
1789
        /* this must be done before scaling */
1790
0
        error = TT_Vary_Apply_Glyph_Deltas( loader->face,
1791
0
                                            glyph_index,
1792
0
                                            &outline,
1793
0
                                            unrounded,
1794
0
                                            (FT_UInt)outline.n_points );
1795
0
        if ( error )
1796
0
          goto Exit;
1797
1798
0
        loader->pp1.x = points[0].x;
1799
0
        loader->pp1.y = points[0].y;
1800
0
        loader->pp2.x = points[1].x;
1801
0
        loader->pp2.y = points[1].y;
1802
1803
0
        loader->pp3.x = points[2].x;
1804
0
        loader->pp3.y = points[2].y;
1805
0
        loader->pp4.x = points[3].x;
1806
0
        loader->pp4.y = points[3].y;
1807
1808
        /* recalculate linear horizontal and vertical advances */
1809
        /* if we don't have HVAR and VVAR, respectively        */
1810
0
        if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
1811
0
          loader->linear = FT_PIX_ROUND( unrounded[1].x -
1812
0
                                         unrounded[0].x ) / 64;
1813
0
        if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
1814
0
          loader->vadvance = FT_PIX_ROUND( unrounded[3].x -
1815
0
                                           unrounded[2].x ) / 64;
1816
0
      }
1817
1818
0
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1819
1820
      /* scale phantom points, if necessary; */
1821
      /* they get rounded in `TT_Hint_Glyph' */
1822
0
      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1823
0
      {
1824
0
        loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1825
0
        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1826
        /* pp1.y and pp2.y are always zero */
1827
1828
0
        loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1829
0
        loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1830
0
        loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1831
0
        loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1832
0
      }
1833
1834
0
      error = FT_Err_Ok;
1835
0
      goto Exit;
1836
0
    }
1837
1838
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
1839
0
    tt_get_metrics_incremental( loader, glyph_index );
1840
0
#endif
1841
0
    tt_loader_set_pp( loader );
1842
1843
1844
    /***********************************************************************/
1845
    /***********************************************************************/
1846
    /***********************************************************************/
1847
1848
    /* we now open a frame again, right after the glyph header */
1849
    /* (which consists of 10 bytes)                            */
1850
0
    error = face->access_glyph_frame( loader, glyph_index,
1851
0
                                      face->glyf_offset + offset + 10,
1852
0
                                      (FT_UInt)loader->byte_len - 10 );
1853
0
    if ( error )
1854
0
      goto Exit;
1855
1856
0
    opened_frame = 1;
1857
1858
    /* if it is a simple glyph, load it */
1859
1860
0
    if ( loader->n_contours > 0 )
1861
0
    {
1862
0
      error = face->read_simple_glyph( loader );
1863
0
      if ( error )
1864
0
        goto Exit;
1865
1866
      /* all data have been read */
1867
0
      face->forget_glyph_frame( loader );
1868
0
      opened_frame = 0;
1869
1870
0
      error = TT_Process_Simple_Glyph( loader );
1871
0
      if ( error )
1872
0
        goto Exit;
1873
1874
0
      FT_GlyphLoader_Add( gloader );
1875
0
    }
1876
1877
    /***********************************************************************/
1878
    /***********************************************************************/
1879
    /***********************************************************************/
1880
1881
    /* otherwise, load a composite! */
1882
0
    else if ( loader->n_contours < 0 )
1883
0
    {
1884
0
      FT_Memory  memory = face->root.memory;
1885
1886
0
      FT_UInt   start_point;
1887
0
      FT_UInt   start_contour;
1888
0
      FT_ULong  ins_pos;  /* position of composite instructions, if any */
1889
1890
0
      FT_ListNode  node, node2;
1891
1892
1893
      /* normalize the `n_contours' value */
1894
0
      loader->n_contours = -1;
1895
1896
      /*
1897
       * We store the glyph index directly in the `node->data' pointer,
1898
       * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
1899
       * double cast to make this portable.  Note, however, that this needs
1900
       * pointers with a width of at least 32 bits.
1901
       */
1902
1903
      /* clear the nodes filled by sibling chains */
1904
0
      node = ft_list_get_node_at( &loader->composites, recurse_count );
1905
0
      for ( node2 = node; node2; node2 = node2->next )
1906
0
        node2->data = (void*)FT_ULONG_MAX;
1907
1908
      /* check whether we already have a composite glyph with this index */
1909
0
      if ( FT_List_Find( &loader->composites,
1910
0
                         FT_UINT_TO_POINTER( glyph_index ) ) )
1911
0
      {
1912
0
        FT_TRACE1(( "TT_Load_Composite_Glyph:"
1913
0
                    " infinite recursion detected\n" ));
1914
0
        error = FT_THROW( Invalid_Composite );
1915
0
        goto Exit;
1916
0
      }
1917
1918
0
      else if ( node )
1919
0
        node->data = FT_UINT_TO_POINTER( glyph_index );
1920
1921
0
      else
1922
0
      {
1923
0
        if ( FT_NEW( node ) )
1924
0
          goto Exit;
1925
0
        node->data = FT_UINT_TO_POINTER( glyph_index );
1926
0
        FT_List_Add( &loader->composites, node );
1927
0
      }
1928
1929
0
      start_point   = (FT_UInt)gloader->base.outline.n_points;
1930
0
      start_contour = (FT_UInt)gloader->base.outline.n_contours;
1931
1932
      /* for each subglyph, read composite header */
1933
0
      error = face->read_composite_glyph( loader );
1934
0
      if ( error )
1935
0
        goto Exit;
1936
1937
      /* store the offset of instructions */
1938
0
      ins_pos = loader->ins_pos;
1939
1940
      /* all data we need are read */
1941
0
      face->forget_glyph_frame( loader );
1942
0
      opened_frame = 0;
1943
1944
0
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1945
1946
0
      if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1947
0
           FT_IS_VARIATION( FT_FACE( face ) )      )
1948
0
      {
1949
0
        short        i, limit;
1950
0
        FT_SubGlyph  subglyph;
1951
1952
0
        FT_Outline  outline;
1953
0
        FT_Vector*  points    = NULL;
1954
0
        char*       tags      = NULL;
1955
0
        short*      contours  = NULL;
1956
0
        FT_Vector*  unrounded = NULL;
1957
1958
1959
0
        limit = (short)gloader->current.num_subglyphs;
1960
1961
        /* construct an outline structure for              */
1962
        /* communication with `TT_Vary_Apply_Glyph_Deltas' */
1963
0
        outline.n_points   = (short)( gloader->current.num_subglyphs + 4 );
1964
0
        outline.n_contours = outline.n_points;
1965
1966
0
        outline.points   = NULL;
1967
0
        outline.tags     = NULL;
1968
0
        outline.contours = NULL;
1969
1970
0
        if ( FT_NEW_ARRAY( points, outline.n_points )    ||
1971
0
             FT_NEW_ARRAY( tags, outline.n_points )      ||
1972
0
             FT_NEW_ARRAY( contours, outline.n_points )  ||
1973
0
             FT_NEW_ARRAY( unrounded, outline.n_points ) )
1974
0
          goto Exit1;
1975
1976
0
        subglyph = gloader->current.subglyphs;
1977
1978
0
        for ( i = 0; i < limit; i++, subglyph++ )
1979
0
        {
1980
          /* applying deltas for anchor points doesn't make sense, */
1981
          /* but we don't have to specially check this since       */
1982
          /* unused delta values are zero anyways                  */
1983
0
          points[i].x = subglyph->arg1;
1984
0
          points[i].y = subglyph->arg2;
1985
0
          tags[i]     = 1;
1986
0
          contours[i] = i;
1987
0
        }
1988
1989
0
        points[i].x = loader->pp1.x;
1990
0
        points[i].y = loader->pp1.y;
1991
0
        tags[i]     = 1;
1992
0
        contours[i] = i;
1993
1994
0
        i++;
1995
0
        points[i].x = loader->pp2.x;
1996
0
        points[i].y = loader->pp2.y;
1997
0
        tags[i]     = 1;
1998
0
        contours[i] = i;
1999
2000
0
        i++;
2001
0
        points[i].x = loader->pp3.x;
2002
0
        points[i].y = loader->pp3.y;
2003
0
        tags[i]     = 1;
2004
0
        contours[i] = i;
2005
2006
0
        i++;
2007
0
        points[i].x = loader->pp4.x;
2008
0
        points[i].y = loader->pp4.y;
2009
0
        tags[i]     = 1;
2010
0
        contours[i] = i;
2011
2012
0
        outline.points   = points;
2013
0
        outline.tags     = tags;
2014
0
        outline.contours = contours;
2015
2016
        /* this call provides additional offsets */
2017
        /* for each component's translation      */
2018
0
        if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas(
2019
0
                             face,
2020
0
                             glyph_index,
2021
0
                             &outline,
2022
0
                             unrounded,
2023
0
                             (FT_UInt)outline.n_points ) ) )
2024
0
          goto Exit1;
2025
2026
0
        subglyph = gloader->current.subglyphs;
2027
2028
0
        for ( i = 0; i < limit; i++, subglyph++ )
2029
0
        {
2030
0
          if ( subglyph->flags & ARGS_ARE_XY_VALUES )
2031
0
          {
2032
0
            subglyph->arg1 = (FT_Int16)points[i].x;
2033
0
            subglyph->arg2 = (FT_Int16)points[i].y;
2034
0
          }
2035
0
        }
2036
2037
0
        loader->pp1.x = points[i + 0].x;
2038
0
        loader->pp1.y = points[i + 0].y;
2039
0
        loader->pp2.x = points[i + 1].x;
2040
0
        loader->pp2.y = points[i + 1].y;
2041
2042
0
        loader->pp3.x = points[i + 2].x;
2043
0
        loader->pp3.y = points[i + 2].y;
2044
0
        loader->pp4.x = points[i + 3].x;
2045
0
        loader->pp4.y = points[i + 3].y;
2046
2047
        /* recalculate linear horizontal and vertical advances */
2048
        /* if we don't have HVAR and VVAR, respectively        */
2049
0
        if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
2050
0
          loader->linear =
2051
0
            FT_PIX_ROUND( unrounded[outline.n_points - 3].x -
2052
0
                          unrounded[outline.n_points - 4].x ) / 64;
2053
0
        if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
2054
0
          loader->vadvance =
2055
0
            FT_PIX_ROUND( unrounded[outline.n_points - 1].x -
2056
0
                          unrounded[outline.n_points - 2].x ) / 64;
2057
2058
0
      Exit1:
2059
0
        FT_FREE( outline.points );
2060
0
        FT_FREE( outline.tags );
2061
0
        FT_FREE( outline.contours );
2062
0
        FT_FREE( unrounded );
2063
2064
0
        if ( error )
2065
0
          goto Exit;
2066
0
      }
2067
2068
0
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
2069
2070
      /* scale phantom points, if necessary; */
2071
      /* they get rounded in `TT_Hint_Glyph' */
2072
0
      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
2073
0
      {
2074
0
        loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
2075
0
        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
2076
        /* pp1.y and pp2.y are always zero */
2077
2078
0
        loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
2079
0
        loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
2080
0
        loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
2081
0
        loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
2082
0
      }
2083
2084
      /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
2085
      /* `as is' in the glyph slot (the client application will be     */
2086
      /* responsible for interpreting these data)...                   */
2087
0
      if ( loader->load_flags & FT_LOAD_NO_RECURSE )
2088
0
      {
2089
0
        FT_GlyphLoader_Add( gloader );
2090
0
        loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
2091
2092
0
        goto Exit;
2093
0
      }
2094
2095
      /*********************************************************************/
2096
      /*********************************************************************/
2097
      /*********************************************************************/
2098
2099
0
      {
2100
0
        FT_UInt      n, num_base_points;
2101
0
        FT_SubGlyph  subglyph       = NULL;
2102
2103
0
        FT_UInt      num_points     = start_point;
2104
0
        FT_UInt      num_subglyphs  = gloader->current.num_subglyphs;
2105
0
        FT_UInt      num_base_subgs = gloader->base.num_subglyphs;
2106
2107
0
        FT_Stream    old_stream     = loader->stream;
2108
0
        FT_Int       old_byte_len   = loader->byte_len;
2109
2110
2111
0
        FT_GlyphLoader_Add( gloader );
2112
2113
        /* read each subglyph independently */
2114
0
        for ( n = 0; n < num_subglyphs; n++ )
2115
0
        {
2116
0
          FT_Vector  pp[4];
2117
2118
0
          FT_Int  linear_hadvance;
2119
0
          FT_Int  linear_vadvance;
2120
2121
2122
          /* Each time we call `load_truetype_glyph' in this loop, the */
2123
          /* value of `gloader.base.subglyphs' can change due to table */
2124
          /* reallocations.  We thus need to recompute the subglyph    */
2125
          /* pointer on each iteration.                                */
2126
0
          subglyph = gloader->base.subglyphs + num_base_subgs + n;
2127
2128
0
          pp[0] = loader->pp1;
2129
0
          pp[1] = loader->pp2;
2130
0
          pp[2] = loader->pp3;
2131
0
          pp[3] = loader->pp4;
2132
2133
0
          linear_hadvance = loader->linear;
2134
0
          linear_vadvance = loader->vadvance;
2135
2136
0
          num_base_points = (FT_UInt)gloader->base.outline.n_points;
2137
2138
0
          error = load_truetype_glyph( loader,
2139
0
                                       (FT_UInt)subglyph->index,
2140
0
                                       recurse_count + 1,
2141
0
                                       FALSE );
2142
0
          if ( error )
2143
0
            goto Exit;
2144
2145
          /* restore subglyph pointer */
2146
0
          subglyph = gloader->base.subglyphs + num_base_subgs + n;
2147
2148
          /* restore phantom points if necessary */
2149
0
          if ( !( subglyph->flags & USE_MY_METRICS ) )
2150
0
          {
2151
0
            loader->pp1 = pp[0];
2152
0
            loader->pp2 = pp[1];
2153
0
            loader->pp3 = pp[2];
2154
0
            loader->pp4 = pp[3];
2155
2156
0
            loader->linear   = linear_hadvance;
2157
0
            loader->vadvance = linear_vadvance;
2158
0
          }
2159
2160
0
          num_points = (FT_UInt)gloader->base.outline.n_points;
2161
2162
0
          if ( num_points == num_base_points )
2163
0
            continue;
2164
2165
          /* gloader->base.outline consists of three parts:           */
2166
          /*                                                          */
2167
          /* 0 ----> start_point ----> num_base_points ----> n_points */
2168
          /*    (1)               (2)                   (3)           */
2169
          /*                                                          */
2170
          /* (1) points that exist from the beginning                 */
2171
          /* (2) component points that have been loaded so far        */
2172
          /* (3) points of the newly loaded component                 */
2173
0
          error = TT_Process_Composite_Component( loader,
2174
0
                                                  subglyph,
2175
0
                                                  start_point,
2176
0
                                                  num_base_points );
2177
0
          if ( error )
2178
0
            goto Exit;
2179
0
        }
2180
2181
0
        loader->stream   = old_stream;
2182
0
        loader->byte_len = old_byte_len;
2183
2184
        /* process the glyph */
2185
0
        loader->ins_pos = ins_pos;
2186
0
        if ( IS_HINTED( loader->load_flags ) &&
2187
0
#ifdef TT_USE_BYTECODE_INTERPRETER
2188
0
             subglyph                        &&
2189
0
             subglyph->flags & WE_HAVE_INSTR &&
2190
0
#endif
2191
0
             num_points > start_point )
2192
0
        {
2193
0
          error = TT_Process_Composite_Glyph( loader,
2194
0
                                              start_point,
2195
0
                                              start_contour );
2196
0
          if ( error )
2197
0
            goto Exit;
2198
0
        }
2199
0
      }
2200
2201
      /* retain the overlap flag */
2202
0
      if ( gloader->base.num_subglyphs                         &&
2203
0
           gloader->base.subglyphs[0].flags & OVERLAP_COMPOUND )
2204
0
        gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
2205
0
    }
2206
2207
    /***********************************************************************/
2208
    /***********************************************************************/
2209
    /***********************************************************************/
2210
2211
0
  Exit:
2212
2213
0
    if ( opened_frame )
2214
0
      face->forget_glyph_frame( loader );
2215
2216
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
2217
2218
0
    if ( glyph_data_loaded )
2219
0
      face->root.internal->incremental_interface->funcs->free_glyph_data(
2220
0
        face->root.internal->incremental_interface->object,
2221
0
        &glyph_data );
2222
2223
0
#endif
2224
2225
0
    return error;
2226
0
  }
2227
2228
2229
  static FT_Error
2230
  compute_glyph_metrics( TT_Loader  loader,
2231
                         FT_UInt    glyph_index )
2232
0
  {
2233
0
    TT_Face    face   = loader->face;
2234
0
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
2235
0
    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2236
0
    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
2237
0
#endif
2238
2239
0
    FT_BBox       bbox;
2240
0
    FT_Fixed      y_scale;
2241
0
    TT_GlyphSlot  glyph = loader->glyph;
2242
0
    TT_Size       size  = loader->size;
2243
2244
2245
0
    y_scale = 0x10000L;
2246
0
    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
2247
0
      y_scale = size->metrics->y_scale;
2248
2249
0
    if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
2250
0
      FT_Outline_Get_CBox( &glyph->outline, &bbox );
2251
0
    else
2252
0
      bbox = loader->bbox;
2253
2254
    /* get the device-independent horizontal advance; it is scaled later */
2255
    /* by the base layer.                                                */
2256
0
    glyph->linearHoriAdvance = loader->linear;
2257
2258
0
    glyph->metrics.horiBearingX = bbox.xMin;
2259
0
    glyph->metrics.horiBearingY = bbox.yMax;
2260
0
    glyph->metrics.horiAdvance  = SUB_LONG(loader->pp2.x, loader->pp1.x);
2261
2262
    /* Adjust advance width to the value contained in the hdmx table   */
2263
    /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */
2264
    /* mode of the v40 interpreter is active.  See `ttinterp.h' for    */
2265
    /* details on backward compatibility mode.                         */
2266
0
    if (
2267
0
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2268
0
         !( driver->interpreter_version == TT_INTERPRETER_VERSION_40  &&
2269
0
            ( loader->exec && loader->exec->backward_compatibility  ) ) &&
2270
0
#endif
2271
0
         !face->postscript.isFixedPitch                                 &&
2272
0
         IS_HINTED( loader->load_flags )                                &&
2273
0
         !( loader->load_flags & FT_LOAD_COMPUTE_METRICS )              )
2274
0
    {
2275
0
      FT_Byte*  widthp;
2276
2277
2278
0
      widthp = tt_face_get_device_metrics( face,
2279
0
                                           size->metrics->x_ppem,
2280
0
                                           glyph_index );
2281
2282
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2283
2284
      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
2285
      {
2286
        FT_Bool  ignore_x_mode;
2287
2288
2289
        ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) !=
2290
                                 FT_RENDER_MODE_MONO );
2291
2292
        if ( widthp                                                   &&
2293
             ( ( ignore_x_mode && loader->exec->compatible_widths ) ||
2294
                !ignore_x_mode                                      ||
2295
                SPH_OPTION_BITMAP_WIDTHS                            ) )
2296
          glyph->metrics.horiAdvance = *widthp * 64;
2297
      }
2298
      else
2299
2300
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2301
2302
0
      {
2303
0
        if ( widthp )
2304
0
          glyph->metrics.horiAdvance = *widthp * 64;
2305
0
      }
2306
0
    }
2307
2308
    /* set glyph dimensions */
2309
0
    glyph->metrics.width  = SUB_LONG( bbox.xMax, bbox.xMin );
2310
0
    glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin );
2311
2312
    /* Now take care of vertical metrics.  In the case where there is */
2313
    /* no vertical information within the font (relatively common),   */
2314
    /* create some metrics manually                                   */
2315
0
    {
2316
0
      FT_Pos  top;      /* scaled vertical top side bearing  */
2317
0
      FT_Pos  advance;  /* scaled vertical advance height    */
2318
2319
2320
      /* Get the unscaled top bearing and advance height. */
2321
0
      if ( face->vertical_info                   &&
2322
0
           face->vertical.number_Of_VMetrics > 0 )
2323
0
      {
2324
0
        top = (FT_Short)FT_DivFix( SUB_LONG( loader->pp3.y, bbox.yMax ),
2325
0
                                   y_scale );
2326
2327
0
        if ( loader->pp3.y <= loader->pp4.y )
2328
0
          advance = 0;
2329
0
        else
2330
0
          advance = (FT_UShort)FT_DivFix( SUB_LONG( loader->pp3.y,
2331
0
                                                    loader->pp4.y ),
2332
0
                                          y_scale );
2333
0
      }
2334
0
      else
2335
0
      {
2336
0
        FT_Pos  height;
2337
2338
2339
        /* XXX Compute top side bearing and advance height in  */
2340
        /*     Get_VMetrics instead of here.                   */
2341
2342
        /* NOTE: The OS/2 values are the only `portable' ones, */
2343
        /*       which is why we use them, if there is an OS/2 */
2344
        /*       table in the font.  Otherwise, we use the     */
2345
        /*       values defined in the horizontal header.      */
2346
2347
0
        height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax,
2348
0
                                                bbox.yMin ),
2349
0
                                      y_scale );
2350
0
        if ( face->os2.version != 0xFFFFU )
2351
0
          advance = (FT_Pos)( face->os2.sTypoAscender -
2352
0
                              face->os2.sTypoDescender );
2353
0
        else
2354
0
          advance = (FT_Pos)( face->horizontal.Ascender -
2355
0
                              face->horizontal.Descender );
2356
2357
0
        top = ( advance - height ) / 2;
2358
0
      }
2359
2360
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
2361
0
      {
2362
0
        FT_Incremental_InterfaceRec*  incr;
2363
0
        FT_Incremental_MetricsRec     incr_metrics;
2364
0
        FT_Error                      error;
2365
2366
2367
0
        incr = face->root.internal->incremental_interface;
2368
2369
        /* If this is an incrementally loaded font see if there are */
2370
        /* overriding metrics for this glyph.                       */
2371
0
        if ( incr && incr->funcs->get_glyph_metrics )
2372
0
        {
2373
0
          incr_metrics.bearing_x = 0;
2374
0
          incr_metrics.bearing_y = top;
2375
0
          incr_metrics.advance   = advance;
2376
2377
0
          error = incr->funcs->get_glyph_metrics( incr->object,
2378
0
                                                  glyph_index,
2379
0
                                                  TRUE,
2380
0
                                                  &incr_metrics );
2381
0
          if ( error )
2382
0
            return error;
2383
2384
0
          top     = incr_metrics.bearing_y;
2385
0
          advance = incr_metrics.advance;
2386
0
        }
2387
0
      }
2388
2389
      /* GWW: Do vertical metrics get loaded incrementally too? */
2390
2391
0
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
2392
2393
0
      glyph->linearVertAdvance = advance;
2394
2395
      /* scale the metrics */
2396
0
      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
2397
0
      {
2398
0
        top     = FT_MulFix( top,     y_scale );
2399
0
        advance = FT_MulFix( advance, y_scale );
2400
0
      }
2401
2402
      /* XXX: for now, we have no better algorithm for the lsb, but it */
2403
      /*      should work fine.                                        */
2404
      /*                                                               */
2405
0
      glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX,
2406
0
                                              glyph->metrics.horiAdvance / 2 );
2407
0
      glyph->metrics.vertBearingY = top;
2408
0
      glyph->metrics.vertAdvance  = advance;
2409
0
    }
2410
2411
0
    return FT_Err_Ok;
2412
0
  }
2413
2414
2415
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2416
2417
  static FT_Error
2418
  load_sbit_image( TT_Size       size,
2419
                   TT_GlyphSlot  glyph,
2420
                   FT_UInt       glyph_index,
2421
                   FT_Int32      load_flags )
2422
0
  {
2423
0
    TT_Face             face;
2424
0
    SFNT_Service        sfnt;
2425
0
    FT_Stream           stream;
2426
0
    FT_Error            error;
2427
0
    TT_SBit_MetricsRec  sbit_metrics;
2428
2429
2430
0
    face   = (TT_Face)glyph->face;
2431
0
    sfnt   = (SFNT_Service)face->sfnt;
2432
0
    stream = face->root.stream;
2433
2434
0
    error = sfnt->load_sbit_image( face,
2435
0
                                   size->strike_index,
2436
0
                                   glyph_index,
2437
0
                                   (FT_UInt)load_flags,
2438
0
                                   stream,
2439
0
                                   &glyph->bitmap,
2440
0
                                   &sbit_metrics );
2441
0
    if ( !error )
2442
0
    {
2443
0
      glyph->outline.n_points   = 0;
2444
0
      glyph->outline.n_contours = 0;
2445
2446
0
      glyph->metrics.width  = (FT_Pos)sbit_metrics.width  * 64;
2447
0
      glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64;
2448
2449
0
      glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
2450
0
      glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
2451
0
      glyph->metrics.horiAdvance  = (FT_Pos)sbit_metrics.horiAdvance  * 64;
2452
2453
0
      glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
2454
0
      glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
2455
0
      glyph->metrics.vertAdvance  = (FT_Pos)sbit_metrics.vertAdvance  * 64;
2456
2457
0
      glyph->format = FT_GLYPH_FORMAT_BITMAP;
2458
2459
0
      if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2460
0
      {
2461
0
        glyph->bitmap_left = sbit_metrics.vertBearingX;
2462
0
        glyph->bitmap_top  = sbit_metrics.vertBearingY;
2463
0
      }
2464
0
      else
2465
0
      {
2466
0
        glyph->bitmap_left = sbit_metrics.horiBearingX;
2467
0
        glyph->bitmap_top  = sbit_metrics.horiBearingY;
2468
0
      }
2469
0
    }
2470
2471
0
    return error;
2472
0
  }
2473
2474
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2475
2476
2477
  static FT_Error
2478
  tt_loader_init( TT_Loader     loader,
2479
                  TT_Size       size,
2480
                  TT_GlyphSlot  glyph,
2481
                  FT_Int32      load_flags,
2482
                  FT_Bool       glyf_table_only )
2483
0
  {
2484
0
    TT_Face    face;
2485
0
    FT_Stream  stream;
2486
2487
0
#ifdef TT_USE_BYTECODE_INTERPRETER
2488
0
    FT_Error   error;
2489
0
    FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2490
0
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
2491
0
    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2492
0
    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
2493
0
#endif
2494
0
#endif
2495
2496
2497
0
    face   = (TT_Face)glyph->face;
2498
0
    stream = face->root.stream;
2499
2500
0
    FT_ZERO( loader );
2501
2502
0
#ifdef TT_USE_BYTECODE_INTERPRETER
2503
2504
    /* load execution context */
2505
0
    if ( IS_HINTED( load_flags ) && !glyf_table_only )
2506
0
    {
2507
0
      TT_ExecContext  exec;
2508
0
      FT_Bool         grayscale = TRUE;
2509
0
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2510
0
      FT_Bool         subpixel_hinting_lean;
2511
0
      FT_Bool         grayscale_cleartype;
2512
0
#endif
2513
2514
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2515
      FT_Bool  subpixel_hinting = FALSE;
2516
2517
#if 0
2518
      /* not used yet */
2519
      FT_Bool  compatible_widths;
2520
      FT_Bool  symmetrical_smoothing;
2521
      FT_Bool  bgr;
2522
      FT_Bool  vertical_lcd;
2523
      FT_Bool  subpixel_positioned;
2524
      FT_Bool  gray_cleartype;
2525
#endif
2526
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2527
2528
0
      FT_Bool  reexecute = FALSE;
2529
2530
2531
0
      if ( size->bytecode_ready < 0 || size->cvt_ready < 0 )
2532
0
      {
2533
0
        error = tt_size_ready_bytecode( size, pedantic );
2534
0
        if ( error )
2535
0
          return error;
2536
0
      }
2537
0
      else if ( size->bytecode_ready )
2538
0
        return size->bytecode_ready;
2539
0
      else if ( size->cvt_ready )
2540
0
        return size->cvt_ready;
2541
2542
      /* query new execution context */
2543
0
      exec = size->context;
2544
0
      if ( !exec )
2545
0
        return FT_THROW( Could_Not_Find_Context );
2546
2547
0
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2548
0
      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2549
0
      {
2550
0
        subpixel_hinting_lean =
2551
0
          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2552
0
                   FT_RENDER_MODE_MONO               );
2553
0
        grayscale_cleartype =
2554
0
          FT_BOOL( subpixel_hinting_lean         &&
2555
0
                   !( ( load_flags         &
2556
0
                        FT_LOAD_TARGET_LCD )   ||
2557
0
                      ( load_flags           &
2558
0
                        FT_LOAD_TARGET_LCD_V ) ) );
2559
0
        exec->vertical_lcd_lean =
2560
0
          FT_BOOL( subpixel_hinting_lean    &&
2561
0
                   ( load_flags           &
2562
0
                     FT_LOAD_TARGET_LCD_V ) );
2563
0
      }
2564
0
      else
2565
0
      {
2566
0
        subpixel_hinting_lean   = FALSE;
2567
0
        grayscale_cleartype     = FALSE;
2568
0
        exec->vertical_lcd_lean = FALSE;
2569
0
      }
2570
0
#endif
2571
2572
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2573
2574
      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
2575
      {
2576
        subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
2577
                                      FT_RENDER_MODE_MONO               )  &&
2578
                                    SPH_OPTION_SET_SUBPIXEL                );
2579
2580
        if ( subpixel_hinting )
2581
          grayscale = FALSE;
2582
        else if ( SPH_OPTION_SET_GRAYSCALE )
2583
        {
2584
          grayscale        = TRUE;
2585
          subpixel_hinting = FALSE;
2586
        }
2587
        else
2588
          grayscale = FALSE;
2589
2590
        if ( FT_IS_TRICKY( glyph->face ) )
2591
          subpixel_hinting = FALSE;
2592
2593
        exec->ignore_x_mode      = subpixel_hinting || grayscale;
2594
        exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
2595
        if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
2596
          exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
2597
2598
#if 1
2599
        exec->compatible_widths     = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
2600
        exec->symmetrical_smoothing = TRUE;
2601
        exec->bgr                   = FALSE;
2602
        exec->vertical_lcd          = FALSE;
2603
        exec->subpixel_positioned   = TRUE;
2604
        exec->gray_cleartype        = FALSE;
2605
#else /* 0 */
2606
        exec->compatible_widths =
2607
          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2608
                   TT_LOAD_COMPATIBLE_WIDTHS );
2609
        exec->symmetrical_smoothing =
2610
          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2611
                   TT_LOAD_SYMMETRICAL_SMOOTHING );
2612
        exec->bgr =
2613
          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2614
                   TT_LOAD_BGR );
2615
        exec->vertical_lcd =
2616
          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2617
                   TT_LOAD_VERTICAL_LCD );
2618
        exec->subpixel_positioned =
2619
          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2620
                   TT_LOAD_SUBPIXEL_POSITIONED );
2621
        exec->gray_cleartype =
2622
          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2623
                   TT_LOAD_GRAY_CLEARTYPE );
2624
#endif /* 0 */
2625
2626
      }
2627
      else
2628
2629
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2630
2631
0
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2632
0
      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2633
0
        grayscale = FT_BOOL( !subpixel_hinting_lean               &&
2634
0
                             FT_LOAD_TARGET_MODE( load_flags ) !=
2635
0
                               FT_RENDER_MODE_MONO                );
2636
0
      else
2637
0
#endif
2638
0
        grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2639
0
                               FT_RENDER_MODE_MONO             );
2640
2641
0
      error = TT_Load_Context( exec, face, size );
2642
0
      if ( error )
2643
0
        return error;
2644
2645
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2646
2647
      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
2648
      {
2649
        /* a change from mono to subpixel rendering (and vice versa) */
2650
        /* requires a re-execution of the CVT program                */
2651
        if ( subpixel_hinting != exec->subpixel_hinting )
2652
        {
2653
          FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
2654
                      " re-executing `prep' table\n" ));
2655
2656
          exec->subpixel_hinting = subpixel_hinting;
2657
          reexecute              = TRUE;
2658
        }
2659
2660
        /* a change from mono to grayscale rendering (and vice versa) */
2661
        /* requires a re-execution of the CVT program                 */
2662
        if ( grayscale != exec->grayscale )
2663
        {
2664
          FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
2665
                      " re-executing `prep' table\n" ));
2666
2667
          exec->grayscale = grayscale;
2668
          reexecute       = TRUE;
2669
        }
2670
      }
2671
      else
2672
2673
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2674
2675
0
      {
2676
2677
0
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2678
0
        if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2679
0
        {
2680
          /* a change from mono to subpixel rendering (and vice versa) */
2681
          /* requires a re-execution of the CVT program                */
2682
0
          if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
2683
0
          {
2684
0
            FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
2685
0
                        " re-executing `prep' table\n" ));
2686
2687
0
            exec->subpixel_hinting_lean = subpixel_hinting_lean;
2688
0
            reexecute                   = TRUE;
2689
0
          }
2690
2691
          /* a change from colored to grayscale subpixel rendering (and */
2692
          /* vice versa) requires a re-execution of the CVT program     */
2693
0
          if ( grayscale_cleartype != exec->grayscale_cleartype )
2694
0
          {
2695
0
            FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
2696
0
                        " re-executing `prep' table\n" ));
2697
2698
0
            exec->grayscale_cleartype = grayscale_cleartype;
2699
0
            reexecute                 = TRUE;
2700
0
          }
2701
0
        }
2702
0
#endif
2703
2704
        /* a change from mono to grayscale rendering (and vice versa) */
2705
        /* requires a re-execution of the CVT program                 */
2706
0
        if ( grayscale != exec->grayscale )
2707
0
        {
2708
0
          FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
2709
0
                      " re-executing `prep' table\n" ));
2710
2711
0
          exec->grayscale = grayscale;
2712
0
          reexecute       = TRUE;
2713
0
        }
2714
0
      }
2715
2716
0
      if ( reexecute )
2717
0
      {
2718
0
        error = tt_size_run_prep( size, pedantic );
2719
0
        if ( error )
2720
0
          return error;
2721
0
      }
2722
2723
      /* check whether the cvt program has disabled hinting */
2724
0
      if ( exec->GS.instruct_control & 1 )
2725
0
        load_flags |= FT_LOAD_NO_HINTING;
2726
2727
      /* load default graphics state -- if needed */
2728
0
      if ( exec->GS.instruct_control & 2 )
2729
0
        exec->GS = tt_default_graphics_state;
2730
2731
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2732
      /* check whether we have a font hinted for ClearType --           */
2733
      /* note that this flag can also be modified in a glyph's bytecode */
2734
      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
2735
           exec->GS.instruct_control & 4                            )
2736
        exec->ignore_x_mode = 0;
2737
#endif
2738
2739
0
      exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2740
0
      loader->exec = exec;
2741
0
      loader->instructions = exec->glyphIns;
2742
0
    }
2743
2744
0
#endif /* TT_USE_BYTECODE_INTERPRETER */
2745
2746
    /* get face's glyph loader */
2747
0
    if ( !glyf_table_only )
2748
0
    {
2749
0
      FT_GlyphLoader  gloader = glyph->internal->loader;
2750
2751
2752
0
      FT_GlyphLoader_Rewind( gloader );
2753
0
      loader->gloader = gloader;
2754
0
    }
2755
2756
0
    loader->load_flags = (FT_ULong)load_flags;
2757
2758
0
    loader->face   = face;
2759
0
    loader->size   = size;
2760
0
    loader->glyph  = (FT_GlyphSlot)glyph;
2761
0
    loader->stream = stream;
2762
2763
0
    loader->composites.head = NULL;
2764
0
    loader->composites.tail = NULL;
2765
2766
0
    return FT_Err_Ok;
2767
0
  }
2768
2769
2770
  static void
2771
  tt_loader_done( TT_Loader  loader )
2772
0
  {
2773
0
    FT_List_Finalize( &loader->composites,
2774
0
                      NULL,
2775
0
                      loader->face->root.memory,
2776
0
                      NULL );
2777
0
  }
2778
2779
2780
  /**************************************************************************
2781
   *
2782
   * @Function:
2783
   *   TT_Load_Glyph
2784
   *
2785
   * @Description:
2786
   *   A function used to load a single glyph within a given glyph slot,
2787
   *   for a given size.
2788
   *
2789
   * @Input:
2790
   *   glyph ::
2791
   *     A handle to a target slot object where the glyph
2792
   *     will be loaded.
2793
   *
2794
   *   size ::
2795
   *     A handle to the source face size at which the glyph
2796
   *     must be scaled/loaded.
2797
   *
2798
   *   glyph_index ::
2799
   *     The index of the glyph in the font file.
2800
   *
2801
   *   load_flags ::
2802
   *     A flag indicating what to load for this glyph.  The
2803
   *     FT_LOAD_XXX constants can be used to control the
2804
   *     glyph loading process (e.g., whether the outline
2805
   *     should be scaled, whether to load bitmaps or not,
2806
   *     whether to hint the outline, etc).
2807
   *
2808
   * @Return:
2809
   *   FreeType error code.  0 means success.
2810
   */
2811
  FT_LOCAL_DEF( FT_Error )
2812
  TT_Load_Glyph( TT_Size       size,
2813
                 TT_GlyphSlot  glyph,
2814
                 FT_UInt       glyph_index,
2815
                 FT_Int32      load_flags )
2816
0
  {
2817
0
    FT_Error      error;
2818
0
    TT_LoaderRec  loader;
2819
2820
2821
0
    FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
2822
2823
0
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2824
2825
    /* try to load embedded bitmap (if any) */
2826
0
    if ( size->strike_index != 0xFFFFFFFFUL      &&
2827
0
         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
2828
0
         IS_DEFAULT_INSTANCE( glyph->face )      )
2829
0
    {
2830
0
      FT_Fixed  x_scale = size->root.metrics.x_scale;
2831
0
      FT_Fixed  y_scale = size->root.metrics.y_scale;
2832
2833
2834
0
      error = load_sbit_image( size, glyph, glyph_index, load_flags );
2835
0
      if ( FT_ERR_EQ( error, Missing_Bitmap ) )
2836
0
      {
2837
        /* the bitmap strike is incomplete and misses the requested glyph; */
2838
        /* if we have a bitmap-only font, return an empty glyph            */
2839
0
        if ( !FT_IS_SCALABLE( glyph->face ) )
2840
0
        {
2841
0
          TT_Face  face = (TT_Face)glyph->face;
2842
2843
0
          FT_Short  left_bearing = 0;
2844
0
          FT_Short  top_bearing  = 0;
2845
2846
0
          FT_UShort  advance_width  = 0;
2847
0
          FT_UShort  advance_height = 0;
2848
2849
2850
          /* to return an empty glyph, however, we need metrics data   */
2851
          /* from the `hmtx' (or `vmtx') table; the assumption is that */
2852
          /* empty glyphs are missing intentionally, representing      */
2853
          /* whitespace - not having at least horizontal metrics is    */
2854
          /* thus considered an error                                  */
2855
0
          if ( !face->horz_metrics_size )
2856
0
            return error;
2857
2858
          /* we now construct an empty bitmap glyph */
2859
0
          TT_Get_HMetrics( face, glyph_index,
2860
0
                           &left_bearing,
2861
0
                           &advance_width );
2862
0
          TT_Get_VMetrics( face, glyph_index,
2863
0
                           0,
2864
0
                           &top_bearing,
2865
0
                           &advance_height );
2866
2867
0
          glyph->outline.n_points   = 0;
2868
0
          glyph->outline.n_contours = 0;
2869
2870
0
          glyph->metrics.width  = 0;
2871
0
          glyph->metrics.height = 0;
2872
2873
0
          glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale );
2874
0
          glyph->metrics.horiBearingY = 0;
2875
0
          glyph->metrics.horiAdvance  = FT_MulFix( advance_width, x_scale );
2876
2877
0
          glyph->metrics.vertBearingX = 0;
2878
0
          glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale );
2879
0
          glyph->metrics.vertAdvance  = FT_MulFix( advance_height, y_scale );
2880
2881
0
          glyph->format            = FT_GLYPH_FORMAT_BITMAP;
2882
0
          glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
2883
2884
0
          glyph->bitmap_left = 0;
2885
0
          glyph->bitmap_top  = 0;
2886
2887
0
          return FT_Err_Ok;
2888
0
        }
2889
0
      }
2890
0
      else if ( error )
2891
0
      {
2892
        /* return error if font is not scalable */
2893
0
        if ( !FT_IS_SCALABLE( glyph->face ) )
2894
0
          return error;
2895
0
      }
2896
0
      else
2897
0
      {
2898
0
        if ( FT_IS_SCALABLE( glyph->face ) )
2899
0
        {
2900
          /* for the bbox we need the header only */
2901
0
          (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
2902
0
          (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
2903
0
          tt_loader_done( &loader );
2904
0
          glyph->linearHoriAdvance = loader.linear;
2905
0
          glyph->linearVertAdvance = loader.vadvance;
2906
2907
          /* sanity checks: if `xxxAdvance' in the sbit metric */
2908
          /* structure isn't set, use `linearXXXAdvance'      */
2909
0
          if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
2910
0
            glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance,
2911
0
                                                    x_scale );
2912
0
          if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
2913
0
            glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance,
2914
0
                                                    y_scale );
2915
0
        }
2916
2917
0
        return FT_Err_Ok;
2918
0
      }
2919
0
    }
2920
2921
0
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2922
2923
    /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
2924
0
    if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
2925
0
    {
2926
0
      error = FT_THROW( Invalid_Size_Handle );
2927
0
      goto Exit;
2928
0
    }
2929
2930
0
    if ( load_flags & FT_LOAD_SBITS_ONLY )
2931
0
    {
2932
0
      error = FT_THROW( Invalid_Argument );
2933
0
      goto Exit;
2934
0
    }
2935
2936
0
    error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
2937
0
    if ( error )
2938
0
      goto Exit;
2939
2940
0
    glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
2941
0
    glyph->num_subglyphs = 0;
2942
0
    glyph->outline.flags = 0;
2943
2944
    /* main loading loop */
2945
0
    error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
2946
0
    if ( !error )
2947
0
    {
2948
0
      if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
2949
0
      {
2950
0
        glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
2951
0
        glyph->subglyphs     = loader.gloader->base.subglyphs;
2952
0
      }
2953
0
      else
2954
0
      {
2955
0
        glyph->outline        = loader.gloader->base.outline;
2956
0
        glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
2957
2958
        /* Translate array so that (0,0) is the glyph's origin.  Note  */
2959
        /* that this behaviour is independent on the value of bit 1 of */
2960
        /* the `flags' field in the `head' table -- at least major     */
2961
        /* applications like Acroread indicate that.                   */
2962
0
        if ( loader.pp1.x )
2963
0
          FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
2964
0
      }
2965
2966
0
#ifdef TT_USE_BYTECODE_INTERPRETER
2967
2968
0
      if ( IS_HINTED( load_flags ) )
2969
0
      {
2970
0
        if ( loader.exec->GS.scan_control )
2971
0
        {
2972
          /* convert scan conversion mode to FT_OUTLINE_XXX flags */
2973
0
          switch ( loader.exec->GS.scan_type )
2974
0
          {
2975
0
          case 0: /* simple drop-outs including stubs */
2976
0
            glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
2977
0
            break;
2978
0
          case 1: /* simple drop-outs excluding stubs */
2979
            /* nothing; it's the default rendering mode */
2980
0
            break;
2981
0
          case 4: /* smart drop-outs including stubs */
2982
0
            glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
2983
0
                                    FT_OUTLINE_INCLUDE_STUBS;
2984
0
            break;
2985
0
          case 5: /* smart drop-outs excluding stubs  */
2986
0
            glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
2987
0
            break;
2988
2989
0
          default: /* no drop-out control */
2990
0
            glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2991
0
            break;
2992
0
          }
2993
0
        }
2994
0
        else
2995
0
          glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2996
0
      }
2997
2998
0
#endif /* TT_USE_BYTECODE_INTERPRETER */
2999
3000
0
      error = compute_glyph_metrics( &loader, glyph_index );
3001
0
    }
3002
3003
    /* Set the `high precision' bit flag.                           */
3004
    /* This is _critical_ to get correct output for monochrome      */
3005
    /* TrueType glyphs at all sizes using the bytecode interpreter. */
3006
    /*                                                              */
3007
0
    if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
3008
0
         size->metrics->y_ppem < 24         )
3009
0
      glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
3010
3011
0
    FT_TRACE1(( "  subglyphs = %u, contours = %hd, points = %hd,"
3012
0
                " flags = 0x%.3x\n",
3013
0
                loader.gloader->base.num_subglyphs,
3014
0
                glyph->outline.n_contours,
3015
0
                glyph->outline.n_points,
3016
0
                glyph->outline.flags ));
3017
3018
0
    tt_loader_done( &loader );
3019
3020
0
  Exit:
3021
#ifdef FT_DEBUG_LEVEL_TRACE
3022
    if ( error )
3023
      FT_TRACE1(( "  failed (error code 0x%x)\n",
3024
                  error ));
3025
#endif
3026
3027
0
    return error;
3028
0
  }
3029
3030
3031
/* END */