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

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/truetype/ttgload.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  ttgload.c                                                              */
 
4
/*                                                                         */
 
5
/*    TrueType Glyph Loader (body).                                        */
 
6
/*                                                                         */
 
7
/*  Copyright 1996-2001, 2002, 2003, 2004 by                               */
 
8
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 
9
/*                                                                         */
 
10
/*  This file is part of the FreeType project, and may only be used,       */
 
11
/*  modified, and distributed under the terms of the FreeType project      */
 
12
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
 
13
/*  this file you indicate that you have read the license and              */
 
14
/*  understand and accept it fully.                                        */
 
15
/*                                                                         */
 
16
/***************************************************************************/
 
17
 
 
18
 
 
19
#include <ft2build.h>
 
20
#include FT_INTERNAL_DEBUG_H
 
21
#include FT_INTERNAL_CALC_H
 
22
#include FT_INTERNAL_STREAM_H
 
23
#include FT_INTERNAL_SFNT_H
 
24
#include FT_TRUETYPE_TAGS_H
 
25
#include FT_OUTLINE_H
 
26
 
 
27
#include "ttgload.h"
 
28
 
 
29
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
30
#include "ttgxvar.h"
 
31
#endif
 
32
 
 
33
#include "tterrors.h"
 
34
 
 
35
 
 
36
  /*************************************************************************/
 
37
  /*                                                                       */
 
38
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 
39
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 
40
  /* messages during execution.                                            */
 
41
  /*                                                                       */
 
42
#undef  FT_COMPONENT
 
43
#define FT_COMPONENT  trace_ttgload
 
44
 
 
45
 
 
46
  /*************************************************************************/
 
47
  /*                                                                       */
 
48
  /* Composite font flags.                                                 */
 
49
  /*                                                                       */
 
50
#define ARGS_ARE_WORDS             0x0001
 
51
#define ARGS_ARE_XY_VALUES         0x0002
 
52
#define ROUND_XY_TO_GRID           0x0004
 
53
#define WE_HAVE_A_SCALE            0x0008
 
54
/* reserved                        0x0010 */
 
55
#define MORE_COMPONENTS            0x0020
 
56
#define WE_HAVE_AN_XY_SCALE        0x0040
 
57
#define WE_HAVE_A_2X2              0x0080
 
58
#define WE_HAVE_INSTR              0x0100
 
59
#define USE_MY_METRICS             0x0200
 
60
#define OVERLAP_COMPOUND           0x0400
 
61
#define SCALED_COMPONENT_OFFSET    0x0800
 
62
#define UNSCALED_COMPONENT_OFFSET  0x1000
 
63
 
 
64
 
 
65
/* Maximum recursion depth we allow for composite glyphs.
 
66
 * The TrueType spec doesn't say anything about recursion,
 
67
 * so it isn't clear that recursion is allowed at all. But
 
68
 * we'll be generous.
 
69
 */
 
70
#define TT_MAX_COMPOSITE_RECURSE 5
 
71
 
 
72
 
 
73
 
 
74
  /*************************************************************************/
 
75
  /*                                                                       */
 
76
  /* <Function>                                                            */
 
77
  /*    TT_Get_Metrics                                                     */
 
78
  /*                                                                       */
 
79
  /* <Description>                                                         */
 
80
  /*    Returns the horizontal or vertical metrics in font units for a     */
 
81
  /*    given glyph.  The metrics are the left side bearing (resp. top     */
 
82
  /*    side bearing) and advance width (resp. advance height).            */
 
83
  /*                                                                       */
 
84
  /* <Input>                                                               */
 
85
  /*    header  :: A pointer to either the horizontal or vertical metrics  */
 
86
  /*               structure.                                              */
 
87
  /*                                                                       */
 
88
  /*    idx     :: The glyph index.                                        */
 
89
  /*                                                                       */
 
90
  /* <Output>                                                              */
 
91
  /*    bearing :: The bearing, either left side or top side.              */
 
92
  /*                                                                       */
 
93
  /*    advance :: The advance width resp. advance height.                 */
 
94
  /*                                                                       */
 
95
  /* <Note>                                                                */
 
96
  /*    This function will much probably move to another component in the  */
 
97
  /*    near future, but I haven't decided which yet.                      */
 
98
  /*                                                                       */
 
99
  FT_LOCAL_DEF( void )
 
100
  TT_Get_Metrics( TT_HoriHeader*  header,
 
101
                  FT_UInt         idx,
 
102
                  FT_Short*       bearing,
 
103
                  FT_UShort*      advance )
 
104
  {
 
105
    TT_LongMetrics  longs_m;
 
106
    FT_UShort       k = header->number_Of_HMetrics;
 
107
 
 
108
 
 
109
    if ( k == 0 )
 
110
    {
 
111
      *bearing = *advance = 0;
 
112
      return;
 
113
    }
 
114
 
 
115
    if ( idx < (FT_UInt)k )
 
116
    {
 
117
      longs_m  = (TT_LongMetrics )header->long_metrics + idx;
 
118
      *bearing = longs_m->bearing;
 
119
      *advance = longs_m->advance;
 
120
    }
 
121
    else
 
122
    {
 
123
      *bearing = ((TT_ShortMetrics*)header->short_metrics)[idx - k];
 
124
      *advance = ((TT_LongMetrics )header->long_metrics)[k - 1].advance;
 
125
    }
 
126
  }
 
127
 
 
128
 
 
129
  /*************************************************************************/
 
130
  /*                                                                       */
 
131
  /* Returns the horizontal metrics in font units for a given glyph.  If   */
 
132
  /* `check' is true, take care of monospaced fonts by returning the       */
 
133
  /* advance width maximum.                                                */
 
134
  /*                                                                       */
 
135
  static void
 
136
  Get_HMetrics( TT_Face     face,
 
137
                FT_UInt     idx,
 
138
                FT_Bool     check,
 
139
                FT_Short*   lsb,
 
140
                FT_UShort*  aw )
 
141
  {
 
142
    TT_Get_Metrics( &face->horizontal, idx, lsb, aw );
 
143
 
 
144
    if ( check && face->postscript.isFixedPitch )
 
145
      *aw = face->horizontal.advance_Width_Max;
 
146
  }
 
147
 
 
148
 
 
149
  /*************************************************************************/
 
150
  /*                                                                       */
 
151
  /* Returns the advance width table for a given pixel size if it is found */
 
152
  /* in the font's `hdmx' table (if any).                                  */
 
153
  /*                                                                       */
 
154
  static FT_Byte*
 
155
  Get_Advance_Widths( TT_Face    face,
 
156
                      FT_UShort  ppem )
 
157
  {
 
158
    FT_UShort  n;
 
159
 
 
160
 
 
161
    for ( n = 0; n < face->hdmx.num_records; n++ )
 
162
      if ( face->hdmx.records[n].ppem == ppem )
 
163
        return face->hdmx.records[n].widths;
 
164
 
 
165
    return NULL;
 
166
  }
 
167
 
 
168
 
 
169
  /*************************************************************************/
 
170
  /*                                                                       */
 
171
  /* Returns the vertical metrics in font units for a given glyph.         */
 
172
  /* Greg Hitchcock from Microsoft told us that if there were no `vmtx'    */
 
173
  /* table, typoAscender/Descender from the `OS/2' table would be used     */
 
174
  /* instead, and if there were no `OS/2' table, use ascender/descender    */
 
175
  /* from the `hhea' table.  But that is not what Microsoft's rasterizer   */
 
176
  /* apparently does: It uses the ppem value as the advance height, and    */
 
177
  /* sets the top side bearing to be zero.                                 */
 
178
  /*                                                                       */
 
179
  /* The monospace `check' is probably not meaningful here, but we leave   */
 
180
  /* it in for a consistent interface.                                     */
 
181
  /*                                                                       */
 
182
  static void
 
183
  Get_VMetrics( TT_Face     face,
 
184
                FT_UInt     idx,
 
185
                FT_Bool     check,
 
186
                FT_Short*   tsb,
 
187
                FT_UShort*  ah )
 
188
  {
 
189
    FT_UNUSED( check );
 
190
 
 
191
    if ( face->vertical_info )
 
192
      TT_Get_Metrics( (TT_HoriHeader *)&face->vertical, idx, tsb, ah );
 
193
 
 
194
#if 1             /* Emperically determined, at variance with what MS said */
 
195
 
 
196
    else
 
197
    {
 
198
      *tsb = 0;
 
199
      *ah  = face->root.units_per_EM;
 
200
    }
 
201
 
 
202
#else      /* This is what MS said to do.  It isn't what they do, however. */
 
203
 
 
204
    else if ( face->os2.version != 0xFFFFU )
 
205
    {
 
206
      *tsb = face->os2.sTypoAscender;
 
207
      *ah  = face->os2.sTypoAscender - face->os2.sTypoDescender;
 
208
    }
 
209
    else
 
210
    {
 
211
      *tsb = face->horizontal.Ascender;
 
212
      *ah  = face->horizontal.Ascender - face->horizontal.Descender;
 
213
    }
 
214
 
 
215
#endif
 
216
 
 
217
  }
 
218
 
 
219
 
 
220
#define cur_to_org( n, zone ) \
 
221
          FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) )
 
222
 
 
223
#define org_to_cur( n, zone ) \
 
224
          FT_ARRAY_COPY( (zone)->cur, (zone)->org, (n) )
 
225
 
 
226
 
 
227
  /*************************************************************************/
 
228
  /*                                                                       */
 
229
  /* Translates an array of coordinates.                                   */
 
230
  /*                                                                       */
 
231
  static void
 
232
  translate_array( FT_UInt     n,
 
233
                   FT_Vector*  coords,
 
234
                   FT_Pos      delta_x,
 
235
                   FT_Pos      delta_y )
 
236
  {
 
237
    FT_UInt  k;
 
238
 
 
239
 
 
240
    if ( delta_x )
 
241
      for ( k = 0; k < n; k++ )
 
242
        coords[k].x += delta_x;
 
243
 
 
244
    if ( delta_y )
 
245
      for ( k = 0; k < n; k++ )
 
246
        coords[k].y += delta_y;
 
247
  }
 
248
 
 
249
 
 
250
  static void
 
251
  tt_prepare_zone( TT_GlyphZone  zone,
 
252
                   FT_GlyphLoad  load,
 
253
                   FT_UInt       start_point,
 
254
                   FT_UInt       start_contour )
 
255
  {
 
256
    zone->n_points   = (FT_UShort)( load->outline.n_points - start_point );
 
257
    zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour );
 
258
    zone->org        = load->extra_points + start_point;
 
259
    zone->cur        = load->outline.points + start_point;
 
260
    zone->tags       = (FT_Byte*)load->outline.tags + start_point;
 
261
    zone->contours   = (FT_UShort*)load->outline.contours + start_contour;
 
262
  }
 
263
 
 
264
 
 
265
#undef  IS_HINTED
 
266
#define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
 
267
 
 
268
 
 
269
  /*************************************************************************/
 
270
  /*                                                                       */
 
271
  /* The following functions are used by default with TrueType fonts.      */
 
272
  /* However, they can be replaced by alternatives if we need to support   */
 
273
  /* TrueType-compressed formats (like MicroType) in the future.           */
 
274
  /*                                                                       */
 
275
  /*************************************************************************/
 
276
 
 
277
  FT_CALLBACK_DEF( FT_Error )
 
278
  TT_Access_Glyph_Frame( TT_Loader  loader,
 
279
                         FT_UInt    glyph_index,
 
280
                         FT_ULong   offset,
 
281
                         FT_UInt    byte_count )
 
282
  {
 
283
    FT_Error   error;
 
284
    FT_Stream  stream = loader->stream;
 
285
 
 
286
    /* for non-debug mode */
 
287
    FT_UNUSED( glyph_index );
 
288
 
 
289
 
 
290
    FT_TRACE5(( "Glyph %ld\n", glyph_index ));
 
291
 
 
292
    /* the following line sets the `error' variable through macros! */
 
293
    if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
 
294
      return error;
 
295
 
 
296
    return TT_Err_Ok;
 
297
  }
 
298
 
 
299
 
 
300
  FT_CALLBACK_DEF( void )
 
301
  TT_Forget_Glyph_Frame( TT_Loader  loader )
 
302
  {
 
303
    FT_Stream  stream = loader->stream;
 
304
 
 
305
 
 
306
    FT_FRAME_EXIT();
 
307
  }
 
308
 
 
309
 
 
310
  FT_CALLBACK_DEF( FT_Error )
 
311
  TT_Load_Glyph_Header( TT_Loader  loader )
 
312
  {
 
313
    FT_Stream  stream   = loader->stream;
 
314
    FT_Int     byte_len = loader->byte_len - 10;
 
315
 
 
316
 
 
317
    if ( byte_len < 0 )
 
318
      return TT_Err_Invalid_Outline;
 
319
 
 
320
    loader->n_contours = FT_GET_SHORT();
 
321
 
 
322
    loader->bbox.xMin = FT_GET_SHORT();
 
323
    loader->bbox.yMin = FT_GET_SHORT();
 
324
    loader->bbox.xMax = FT_GET_SHORT();
 
325
    loader->bbox.yMax = FT_GET_SHORT();
 
326
 
 
327
    FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
 
328
    FT_TRACE5(( "  xMin: %4d  xMax: %4d\n", loader->bbox.xMin,
 
329
                                            loader->bbox.xMax ));
 
330
    FT_TRACE5(( "  yMin: %4d  yMax: %4d\n", loader->bbox.yMin,
 
331
                                            loader->bbox.yMax ));
 
332
    loader->byte_len = byte_len;
 
333
 
 
334
    return TT_Err_Ok;
 
335
  }
 
336
 
 
337
 
 
338
  FT_CALLBACK_DEF( FT_Error )
 
339
  TT_Load_Simple_Glyph( TT_Loader  load )
 
340
  {
 
341
    FT_Error        error;
 
342
    FT_Stream       stream     = load->stream;
 
343
    FT_GlyphLoader  gloader    = load->gloader;
 
344
    FT_Int          n_contours = load->n_contours;
 
345
    FT_Outline*     outline;
 
346
    TT_Face         face       = (TT_Face)load->face;
 
347
    TT_GlyphSlot    slot       = (TT_GlyphSlot)load->glyph;
 
348
    FT_UShort       n_ins;
 
349
    FT_Int          n, n_points;
 
350
    FT_Int          byte_len   = load->byte_len;
 
351
 
 
352
    FT_Byte         *flag, *flag_limit;
 
353
    FT_Byte         c, count;
 
354
    FT_Vector       *vec, *vec_limit;
 
355
    FT_Pos          x;
 
356
    FT_Short        *cont, *cont_limit;
 
357
 
 
358
 
 
359
    /* reading the contours' endpoints & number of points */
 
360
    cont       = gloader->current.outline.contours;
 
361
    cont_limit = cont + n_contours;
 
362
 
 
363
    /* check space for contours array + instructions count */
 
364
    byte_len -= 2 * ( n_contours + 1 );
 
365
    if ( byte_len < 0 )
 
366
      goto Invalid_Outline;
 
367
 
 
368
    for ( ; cont < cont_limit; cont++ )
 
369
      cont[0] = FT_GET_USHORT();
 
370
 
 
371
    n_points = 0;
 
372
    if ( n_contours > 0 )
 
373
      n_points = cont[-1] + 1;
 
374
 
 
375
    error = FT_GlyphLoader_CheckPoints( gloader, n_points + 4, 0 );
 
376
    if ( error )
 
377
      goto Fail;
 
378
 
 
379
    /* we'd better check the contours table right now */
 
380
    outline = &gloader->current.outline;
 
381
 
 
382
    for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
 
383
      if ( cont[-1] >= cont[0] )
 
384
        goto Invalid_Outline;
 
385
 
 
386
    /* reading the bytecode instructions */
 
387
    slot->control_len  = 0;
 
388
    slot->control_data = 0;
 
389
 
 
390
    n_ins = FT_GET_USHORT();
 
391
 
 
392
    FT_TRACE5(( "  Instructions size: %u\n", n_ins ));
 
393
 
 
394
    if ( n_ins > face->max_profile.maxSizeOfInstructions )
 
395
    {
 
396
      FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions!\n" ));
 
397
      error = TT_Err_Too_Many_Hints;
 
398
      goto Fail;
 
399
    }
 
400
 
 
401
    byte_len -= (FT_Int)n_ins;
 
402
    if ( byte_len < 0 )
 
403
    {
 
404
      FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
 
405
      error = TT_Err_Too_Many_Hints;
 
406
      goto Fail;
 
407
    }
 
408
 
 
409
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
410
 
 
411
    if ( ( load->load_flags                        &
 
412
         ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
 
413
           load->instructions )
 
414
    {
 
415
      slot->control_len  = n_ins;
 
416
      slot->control_data = load->instructions;
 
417
 
 
418
      FT_MEM_COPY( load->instructions, stream->cursor, (FT_Long)n_ins );
 
419
    }
 
420
 
 
421
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
 
422
 
 
423
    stream->cursor += (FT_Int)n_ins;
 
424
 
 
425
    /* reading the point tags */
 
426
    flag       = (FT_Byte*)outline->tags;
 
427
    flag_limit = flag + n_points;
 
428
 
 
429
    while ( flag < flag_limit )
 
430
    {
 
431
      if ( --byte_len < 0 )
 
432
        goto Invalid_Outline;
 
433
 
 
434
      *flag++ = c = FT_GET_BYTE();
 
435
      if ( c & 8 )
 
436
      {
 
437
        if ( --byte_len < 0 )
 
438
          goto Invalid_Outline;
 
439
 
 
440
        count = FT_GET_BYTE();
 
441
        if ( flag + (FT_Int)count > flag_limit )
 
442
          goto Invalid_Outline;
 
443
 
 
444
        for ( ; count > 0; count-- )
 
445
          *flag++ = c;
 
446
      }
 
447
    }
 
448
 
 
449
    /* check that there is enough room to load the coordinates */
 
450
    for ( flag = (FT_Byte*)outline->tags; flag < flag_limit; flag++ )
 
451
    {
 
452
      if ( *flag & 2 )
 
453
        byte_len -= 1;
 
454
      else if ( ( *flag & 16 ) == 0 )
 
455
        byte_len -= 2;
 
456
 
 
457
      if ( *flag & 4 )
 
458
        byte_len -= 1;
 
459
      else if ( ( *flag & 32 ) == 0 )
 
460
        byte_len -= 2;
 
461
    }
 
462
 
 
463
    if ( byte_len < 0 )
 
464
      goto Invalid_Outline;
 
465
 
 
466
    /* reading the X coordinates */
 
467
 
 
468
    vec       = outline->points;
 
469
    vec_limit = vec + n_points;
 
470
    flag      = (FT_Byte*)outline->tags;
 
471
    x         = 0;
 
472
 
 
473
    for ( ; vec < vec_limit; vec++, flag++ )
 
474
    {
 
475
      FT_Pos  y = 0;
 
476
 
 
477
 
 
478
      if ( *flag & 2 )
 
479
      {
 
480
        y = (FT_Pos)FT_GET_BYTE();
 
481
        if ( ( *flag & 16 ) == 0 )
 
482
          y = -y;
 
483
      }
 
484
      else if ( ( *flag & 16 ) == 0 )
 
485
        y = (FT_Pos)FT_GET_SHORT();
 
486
 
 
487
      x     += y;
 
488
      vec->x = x;
 
489
    }
 
490
 
 
491
    /* reading the Y coordinates */
 
492
 
 
493
    vec       = gloader->current.outline.points;
 
494
    vec_limit = vec + n_points;
 
495
    flag      = (FT_Byte*)outline->tags;
 
496
    x         = 0;
 
497
 
 
498
    for ( ; vec < vec_limit; vec++, flag++ )
 
499
    {
 
500
      FT_Pos  y = 0;
 
501
 
 
502
 
 
503
      if ( *flag & 4 )
 
504
      {
 
505
        y = (FT_Pos)FT_GET_BYTE();
 
506
        if ( ( *flag & 32 ) == 0 )
 
507
          y = -y;
 
508
      }
 
509
      else if ( ( *flag & 32 ) == 0 )
 
510
        y = (FT_Pos)FT_GET_SHORT();
 
511
 
 
512
      x     += y;
 
513
      vec->y = x;
 
514
    }
 
515
 
 
516
    /* clear the touch tags */
 
517
    for ( n = 0; n < n_points; n++ )
 
518
      outline->tags[n] &= FT_CURVE_TAG_ON;
 
519
 
 
520
    outline->n_points   = (FT_UShort)n_points;
 
521
    outline->n_contours = (FT_Short) n_contours;
 
522
 
 
523
    load->byte_len = byte_len;
 
524
 
 
525
  Fail:
 
526
    return error;
 
527
 
 
528
  Invalid_Outline:
 
529
    error = TT_Err_Invalid_Outline;
 
530
    goto Fail;
 
531
  }
 
532
 
 
533
 
 
534
  FT_CALLBACK_DEF( FT_Error )
 
535
  TT_Load_Composite_Glyph( TT_Loader  loader )
 
536
  {
 
537
    FT_Error        error;
 
538
    FT_Stream       stream  = loader->stream;
 
539
    FT_GlyphLoader  gloader = loader->gloader;
 
540
    FT_SubGlyph     subglyph;
 
541
    FT_UInt         num_subglyphs;
 
542
    FT_Int          byte_len = loader->byte_len;
 
543
 
 
544
 
 
545
    num_subglyphs = 0;
 
546
 
 
547
    do
 
548
    {
 
549
      FT_Fixed  xx, xy, yy, yx;
 
550
 
 
551
 
 
552
      /* check that we can load a new subglyph */
 
553
      error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
 
554
      if ( error )
 
555
        goto Fail;
 
556
 
 
557
      /* check space */
 
558
      byte_len -= 4;
 
559
      if ( byte_len < 0 )
 
560
        goto Invalid_Composite;
 
561
 
 
562
      subglyph = gloader->current.subglyphs + num_subglyphs;
 
563
 
 
564
      subglyph->arg1 = subglyph->arg2 = 0;
 
565
 
 
566
      subglyph->flags = FT_GET_USHORT();
 
567
      subglyph->index = FT_GET_USHORT();
 
568
 
 
569
      /* check space */
 
570
      byte_len -= 2;
 
571
      if ( subglyph->flags & ARGS_ARE_WORDS )
 
572
        byte_len -= 2;
 
573
      if ( subglyph->flags & WE_HAVE_A_SCALE )
 
574
        byte_len -= 2;
 
575
      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
 
576
        byte_len -= 4;
 
577
      else if ( subglyph->flags & WE_HAVE_A_2X2 )
 
578
        byte_len -= 8;
 
579
 
 
580
      if ( byte_len < 0 )
 
581
        goto Invalid_Composite;
 
582
 
 
583
      /* read arguments */
 
584
      if ( subglyph->flags & ARGS_ARE_WORDS )
 
585
      {
 
586
        subglyph->arg1 = FT_GET_SHORT();
 
587
        subglyph->arg2 = FT_GET_SHORT();
 
588
      }
 
589
      else
 
590
      {
 
591
        subglyph->arg1 = FT_GET_CHAR();
 
592
        subglyph->arg2 = FT_GET_CHAR();
 
593
      }
 
594
 
 
595
      /* read transform */
 
596
      xx = yy = 0x10000L;
 
597
      xy = yx = 0;
 
598
 
 
599
      if ( subglyph->flags & WE_HAVE_A_SCALE )
 
600
      {
 
601
        xx = (FT_Fixed)FT_GET_SHORT() << 2;
 
602
        yy = xx;
 
603
      }
 
604
      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
 
605
      {
 
606
        xx = (FT_Fixed)FT_GET_SHORT() << 2;
 
607
        yy = (FT_Fixed)FT_GET_SHORT() << 2;
 
608
      }
 
609
      else if ( subglyph->flags & WE_HAVE_A_2X2 )
 
610
      {
 
611
        xx = (FT_Fixed)FT_GET_SHORT() << 2;
 
612
        yx = (FT_Fixed)FT_GET_SHORT() << 2;
 
613
        xy = (FT_Fixed)FT_GET_SHORT() << 2;
 
614
        yy = (FT_Fixed)FT_GET_SHORT() << 2;
 
615
      }
 
616
 
 
617
      subglyph->transform.xx = xx;
 
618
      subglyph->transform.xy = xy;
 
619
      subglyph->transform.yx = yx;
 
620
      subglyph->transform.yy = yy;
 
621
 
 
622
      num_subglyphs++;
 
623
 
 
624
    } while ( subglyph->flags & MORE_COMPONENTS );
 
625
 
 
626
    gloader->current.num_subglyphs = num_subglyphs;
 
627
 
 
628
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
629
    {
 
630
      /* we must undo the FT_FRAME_ENTER in order to point to the */
 
631
      /* composite instructions, if we find some.               */
 
632
      /* we will process them later...                          */
 
633
      /*                                                        */
 
634
      loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
 
635
                                    stream->cursor - stream->limit );
 
636
    }
 
637
#endif
 
638
 
 
639
    loader->byte_len = byte_len;
 
640
 
 
641
  Fail:
 
642
    return error;
 
643
 
 
644
  Invalid_Composite:
 
645
    error = TT_Err_Invalid_Composite;
 
646
    goto Fail;
 
647
  }
 
648
 
 
649
 
 
650
  FT_LOCAL_DEF( void )
 
651
  TT_Init_Glyph_Loading( TT_Face  face )
 
652
  {
 
653
    face->access_glyph_frame   = TT_Access_Glyph_Frame;
 
654
    face->read_glyph_header    = TT_Load_Glyph_Header;
 
655
    face->read_simple_glyph    = TT_Load_Simple_Glyph;
 
656
    face->read_composite_glyph = TT_Load_Composite_Glyph;
 
657
    face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
 
658
  }
 
659
 
 
660
 
 
661
  /*************************************************************************/
 
662
  /*                                                                       */
 
663
  /* <Function>                                                            */
 
664
  /*    TT_Process_Simple_Glyph                                            */
 
665
  /*                                                                       */
 
666
  /* <Description>                                                         */
 
667
  /*    Once a simple glyph has been loaded, it needs to be processed.     */
 
668
  /*    Usually, this means scaling and hinting through bytecode           */
 
669
  /*    interpretation.                                                    */
 
670
  /*                                                                       */
 
671
  static FT_Error
 
672
  TT_Process_Simple_Glyph( TT_Loader  load,
 
673
                           FT_Bool    debug )
 
674
  {
 
675
    FT_GlyphLoader  gloader  = load->gloader;
 
676
    FT_Outline*     outline  = &gloader->current.outline;
 
677
    FT_UInt         n_points = outline->n_points;
 
678
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
679
    FT_UInt         n_ins;
 
680
#endif
 
681
    TT_GlyphZone    zone     = &load->zone;
 
682
    FT_Error        error    = TT_Err_Ok;
 
683
 
 
684
    FT_UNUSED( debug );  /* used by truetype interpreter only */
 
685
 
 
686
 
 
687
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
688
    n_ins = load->glyph->control_len;
 
689
#endif
 
690
 
 
691
    /* add shadow points */
 
692
 
 
693
    /* Add two horizontal shadow points at n and n+1.   */
 
694
    /* We need the left side bearing and advance width. */
 
695
    /* Add two vertical shadow points at n+2 and n+3.   */
 
696
    /* We need the top side bearing and advance height. */
 
697
 
 
698
    {
 
699
      FT_Vector*  pp1;
 
700
      FT_Vector*  pp2;
 
701
      FT_Vector*  pp3;
 
702
      FT_Vector*  pp4;
 
703
 
 
704
 
 
705
      /* pp1 = xMin - lsb */
 
706
      pp1    = outline->points + n_points;
 
707
      pp1->x = load->bbox.xMin - load->left_bearing;
 
708
      pp1->y = 0;
 
709
 
 
710
      /* pp2 = pp1 + aw */
 
711
      pp2    = pp1 + 1;
 
712
      pp2->x = pp1->x + load->advance;
 
713
      pp2->y = 0;
 
714
 
 
715
      /* pp3 = top side bearing */
 
716
      pp3    = pp1 + 2;
 
717
      pp3->x = 0;
 
718
      pp3->y = load->top_bearing + load->bbox.yMax;
 
719
 
 
720
      /* pp4 = pp3 - ah */
 
721
      pp4    = pp1 + 3;
 
722
      pp4->x = 0;
 
723
      pp4->y = pp3->y - load->vadvance;
 
724
 
 
725
      outline->tags[n_points    ] = 0;
 
726
      outline->tags[n_points + 1] = 0;
 
727
      outline->tags[n_points + 2] = 0;
 
728
      outline->tags[n_points + 3] = 0;
 
729
    }
 
730
 
 
731
    /* Note that we return four more points that are not */
 
732
    /* part of the glyph outline.                        */
 
733
 
 
734
    n_points += 4;
 
735
 
 
736
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
737
 
 
738
    if ( ((TT_Face)load->face)->doblend )
 
739
    {
 
740
      /* Deltas apply to the unscaled data. */
 
741
      FT_Vector*    deltas;
 
742
      FT_Memory     memory       = load->face->memory;
 
743
      FT_StreamRec  saved_stream = *(load->stream);
 
744
      FT_UInt       i;
 
745
 
 
746
 
 
747
      /* TT_Vary_Get_Glyph_Deltas uses a frame, thus we have to save */
 
748
      /* (and restore) the current one                               */
 
749
      load->stream->cursor = 0;
 
750
      load->stream->limit  = 0;
 
751
 
 
752
      error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(load->face),
 
753
                                        load->glyph_index,
 
754
                                        &deltas,
 
755
                                        n_points );
 
756
 
 
757
      *(load->stream) = saved_stream;
 
758
 
 
759
      if ( error )
 
760
        goto Exit;
 
761
 
 
762
      for ( i = 0; i < n_points; ++i )
 
763
      {
 
764
        outline->points[i].x += deltas[i].x;
 
765
        outline->points[i].y += deltas[i].y;
 
766
      }
 
767
 
 
768
      FT_FREE( deltas );
 
769
    }
 
770
 
 
771
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
772
 
 
773
    /* set up zone for hinting */
 
774
    tt_prepare_zone( zone, &gloader->current, 0, 0 );
 
775
 
 
776
    /* eventually scale the glyph */
 
777
    if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
 
778
    {
 
779
      FT_Vector*  vec     = zone->cur;
 
780
      FT_Vector*  limit   = vec + n_points;
 
781
      FT_Fixed    x_scale = ((TT_Size)load->size)->metrics.x_scale;
 
782
      FT_Fixed    y_scale = ((TT_Size)load->size)->metrics.y_scale;
 
783
 
 
784
      /* first scale the glyph points */
 
785
      for ( ; vec < limit; vec++ )
 
786
      {
 
787
        vec->x = FT_MulFix( vec->x, x_scale );
 
788
        vec->y = FT_MulFix( vec->y, y_scale );
 
789
      }
 
790
    }
 
791
 
 
792
    cur_to_org( n_points, zone );
 
793
 
 
794
    /* eventually hint the glyph */
 
795
    if ( IS_HINTED( load->load_flags ) )
 
796
    {
 
797
      FT_Pos  x = zone->org[n_points-4].x;
 
798
      FT_Pos  y = zone->org[n_points-2].y;
 
799
 
 
800
 
 
801
      x = FT_PIX_ROUND( x ) - x;
 
802
      y = FT_PIX_ROUND( y ) - y;
 
803
      translate_array( n_points, zone->org, x, y );
 
804
 
 
805
      org_to_cur( n_points, zone );
 
806
 
 
807
      zone->cur[n_points - 3].x = FT_PIX_ROUND( zone->cur[n_points - 3].x );
 
808
      zone->cur[n_points - 1].y = FT_PIX_ROUND( zone->cur[n_points - 1].y );
 
809
 
 
810
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
811
 
 
812
      /* now consider hinting */
 
813
      if ( n_ins > 0 )
 
814
      {
 
815
        error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
 
816
                                  load->exec->glyphIns, n_ins );
 
817
        if ( error )
 
818
          goto Exit;
 
819
 
 
820
        load->exec->is_composite     = FALSE;
 
821
        load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
 
822
                                                  FT_LOAD_PEDANTIC );
 
823
        load->exec->pts              = *zone;
 
824
        load->exec->pts.n_points    += 4;
 
825
 
 
826
        error = TT_Run_Context( load->exec, debug );
 
827
        if ( error && load->exec->pedantic_hinting )
 
828
          goto Exit;
 
829
 
 
830
        error = TT_Err_Ok;  /* ignore bytecode errors in non-pedantic mode */
 
831
      }
 
832
 
 
833
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
 
834
 
 
835
    }
 
836
 
 
837
    /* save glyph phantom points */
 
838
    if ( !load->preserve_pps )
 
839
    {
 
840
      load->pp1 = zone->cur[n_points - 4];
 
841
      load->pp2 = zone->cur[n_points - 3];
 
842
      load->pp3 = zone->cur[n_points - 2];
 
843
      load->pp4 = zone->cur[n_points - 1];
 
844
    }
 
845
 
 
846
#if defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) || \
 
847
    defined( TT_CONFIG_OPTION_GX_VAR_SUPPORT )
 
848
  Exit:
 
849
#endif
 
850
 
 
851
    return error;
 
852
  }
 
853
 
 
854
 
 
855
  /*************************************************************************/
 
856
  /*                                                                       */
 
857
  /* <Function>                                                            */
 
858
  /*    load_truetype_glyph                                                */
 
859
  /*                                                                       */
 
860
  /* <Description>                                                         */
 
861
  /*    Loads a given truetype glyph.  Handles composites and uses a       */
 
862
  /*    TT_Loader object.                                                  */
 
863
  /*                                                                       */
 
864
  static FT_Error
 
865
  load_truetype_glyph( TT_Loader  loader,
 
866
                       FT_UInt    glyph_index,
 
867
                       FT_UInt    recurse_count )
 
868
  {
 
869
 
 
870
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
871
    FT_Stream       stream = loader->stream;
 
872
#endif
 
873
 
 
874
    FT_Error        error;
 
875
    TT_Face         face = (TT_Face)loader->face;
 
876
    FT_ULong        offset;
 
877
    FT_Int          contours_count;
 
878
    FT_UInt         num_points, count;
 
879
    FT_Fixed        x_scale, y_scale;
 
880
    FT_GlyphLoader  gloader = loader->gloader;
 
881
    FT_Bool         opened_frame = 0;
 
882
 
 
883
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
884
    FT_StreamRec    inc_stream;
 
885
    FT_Data         glyph_data;
 
886
    FT_Bool         glyph_data_loaded = 0;
 
887
#endif
 
888
 
 
889
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
890
    FT_Vector      *deltas;
 
891
#endif
 
892
 
 
893
 
 
894
    if ( recurse_count >= TT_MAX_COMPOSITE_RECURSE )
 
895
    {
 
896
      error = TT_Err_Invalid_Composite;
 
897
      goto Exit;
 
898
    }
 
899
 
 
900
    /* check glyph index */
 
901
    if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
 
902
    {
 
903
      error = TT_Err_Invalid_Glyph_Index;
 
904
      goto Exit;
 
905
    }
 
906
 
 
907
    loader->glyph_index = glyph_index;
 
908
    num_points          = 0;
 
909
 
 
910
    x_scale = 0x10000L;
 
911
    y_scale = 0x10000L;
 
912
    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
 
913
    {
 
914
      x_scale = ((TT_Size)loader->size)->metrics.x_scale;
 
915
      y_scale = ((TT_Size)loader->size)->metrics.y_scale;
 
916
    }
 
917
 
 
918
    /* get metrics, horizontal and vertical */
 
919
    {
 
920
      FT_Short   left_bearing = 0, top_bearing = 0;
 
921
      FT_UShort  advance_width = 0, advance_height = 0;
 
922
 
 
923
 
 
924
      Get_HMetrics( face, glyph_index,
 
925
                    (FT_Bool)!( loader->load_flags &
 
926
                                FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
 
927
                    &left_bearing,
 
928
                    &advance_width );
 
929
      Get_VMetrics( face, glyph_index,
 
930
                    (FT_Bool)!( loader->load_flags &
 
931
                                FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
 
932
                    &top_bearing,
 
933
                    &advance_height );
 
934
 
 
935
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
936
 
 
937
      /* If this is an incrementally loaded font see if there are */
 
938
      /* overriding metrics for this glyph.                       */
 
939
      if ( face->root.internal->incremental_interface &&
 
940
           face->root.internal->incremental_interface->funcs->get_glyph_metrics )
 
941
      {
 
942
        FT_Incremental_MetricsRec  metrics;
 
943
 
 
944
 
 
945
        metrics.bearing_x = left_bearing;
 
946
        metrics.bearing_y = 0;
 
947
        metrics.advance = advance_width;
 
948
        error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
 
949
                  face->root.internal->incremental_interface->object,
 
950
                  glyph_index, FALSE, &metrics );
 
951
        if ( error )
 
952
          goto Exit;
 
953
        left_bearing  = (FT_Short)metrics.bearing_x;
 
954
        advance_width = (FT_UShort)metrics.advance;
 
955
      }
 
956
 
 
957
# if 0
 
958
      /* GWW: Do I do the same for vertical metrics ??? */
 
959
      if ( face->root.internal->incremental_interface &&
 
960
           face->root.internal->incremental_interface->funcs->get_glyph_metrics )
 
961
      {
 
962
        FT_Incremental_MetricsRec  metrics;
 
963
 
 
964
 
 
965
        metrics.bearing_x = 0;
 
966
        metrics.bearing_y = top_bearing;
 
967
        metrics.advance = advance_height;
 
968
        error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
 
969
                  face->root.internal->incremental_interface->object,
 
970
                  glyph_index, TRUE, &metrics );
 
971
        if ( error )
 
972
          goto Exit;
 
973
        top_bearing  = (FT_Short)metrics.bearing_y;
 
974
        advance_height = (FT_UShort)metrics.advance;
 
975
      }
 
976
# endif
 
977
 
 
978
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
979
 
 
980
      loader->left_bearing = left_bearing;
 
981
      loader->advance      = advance_width;
 
982
      loader->top_bearing  = top_bearing;
 
983
      loader->vadvance     = advance_height;
 
984
 
 
985
      if ( !loader->linear_def )
 
986
      {
 
987
        loader->linear_def = 1;
 
988
        loader->linear     = advance_width;
 
989
      }
 
990
    }
 
991
 
 
992
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
993
 
 
994
    /* Set `offset' to the start of the glyph program relative to the  */
 
995
    /* start of the 'glyf' table, and `count' to the length of the     */
 
996
    /* glyph program in bytes.                                         */
 
997
    /*                                                                 */
 
998
    /* If we are loading glyph data via the incremental interface, set */
 
999
    /* the loader stream to a memory stream reading the data returned  */
 
1000
    /* by the interface.                                               */
 
1001
 
 
1002
    if ( face->root.internal->incremental_interface )
 
1003
    {
 
1004
      error = face->root.internal->incremental_interface->funcs->get_glyph_data(
 
1005
                face->root.internal->incremental_interface->object,
 
1006
                glyph_index, &glyph_data );
 
1007
      if ( error )
 
1008
        goto Exit;
 
1009
 
 
1010
      glyph_data_loaded = 1;
 
1011
      offset            = 0;
 
1012
      count             = glyph_data.length;
 
1013
 
 
1014
      FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
 
1015
      FT_Stream_OpenMemory( &inc_stream,
 
1016
                            glyph_data.pointer, glyph_data.length );
 
1017
 
 
1018
      loader->stream = &inc_stream;
 
1019
    }
 
1020
    else
 
1021
 
 
1022
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
1023
 
 
1024
    {
 
1025
      offset = face->glyph_locations[glyph_index];
 
1026
      count  = 0;
 
1027
 
 
1028
      if ( glyph_index < (FT_UInt)face->num_locations - 1 )
 
1029
        count = (FT_UInt)( face->glyph_locations[glyph_index + 1] - offset );
 
1030
    }
 
1031
 
 
1032
    if ( count == 0 )
 
1033
    {
 
1034
      /* as described by Frederic Loyer, these are spaces, and */
 
1035
      /* not the unknown glyph.                                */
 
1036
      loader->bbox.xMin = 0;
 
1037
      loader->bbox.xMax = 0;
 
1038
      loader->bbox.yMin = 0;
 
1039
      loader->bbox.yMax = 0;
 
1040
 
 
1041
      loader->pp1.x = 0;
 
1042
      loader->pp2.x = loader->advance;
 
1043
      loader->pp3.y = 0;
 
1044
      loader->pp4.y = loader->pp3.y-loader->vadvance;
 
1045
 
 
1046
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
1047
      if ( ((TT_Face)(loader->face))->doblend )
 
1048
      {
 
1049
        /* this must be done before scaling */
 
1050
        FT_Memory  memory = loader->face->memory;
 
1051
 
 
1052
 
 
1053
        if ( (error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
 
1054
                                                glyph_index,
 
1055
                                                &deltas,
 
1056
                                                4 ) ) )
 
1057
          goto Exit;
 
1058
 
 
1059
        loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
 
1060
        loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
 
1061
        loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
 
1062
        loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
 
1063
 
 
1064
        FT_FREE( deltas );
 
1065
      }
 
1066
#endif
 
1067
 
 
1068
      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
 
1069
      {
 
1070
        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
 
1071
        loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
 
1072
      }
 
1073
 
 
1074
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
1075
 
 
1076
      if ( loader->exec )
 
1077
        loader->exec->glyphSize = 0;
 
1078
 
 
1079
#endif
 
1080
 
 
1081
      error = TT_Err_Ok;
 
1082
      goto Exit;
 
1083
    }
 
1084
 
 
1085
    loader->byte_len = (FT_Int)count;
 
1086
 
 
1087
    offset = loader->glyf_offset + offset;
 
1088
 
 
1089
    /* access glyph frame */
 
1090
    error = face->access_glyph_frame( loader, glyph_index, offset, count );
 
1091
    if ( error )
 
1092
      goto Exit;
 
1093
 
 
1094
    opened_frame = 1;
 
1095
 
 
1096
    /* read first glyph header */
 
1097
    error = face->read_glyph_header( loader );
 
1098
    if ( error )
 
1099
      goto Fail;
 
1100
 
 
1101
    contours_count = loader->n_contours;
 
1102
 
 
1103
    count -= 10;
 
1104
 
 
1105
    loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
 
1106
    loader->pp1.y = 0;
 
1107
    loader->pp2.x = loader->pp1.x + loader->advance;
 
1108
    loader->pp2.y = 0;
 
1109
 
 
1110
    loader->pp3.x = 0;
 
1111
    loader->pp3.y = loader->top_bearing + loader->bbox.yMax;
 
1112
    loader->pp4.x = 0;
 
1113
    loader->pp4.y = loader->pp3.y - loader->vadvance;
 
1114
 
 
1115
    /***********************************************************************/
 
1116
    /***********************************************************************/
 
1117
    /***********************************************************************/
 
1118
 
 
1119
    /* if it is a simple glyph, load it */
 
1120
 
 
1121
    if ( contours_count >= 0 )
 
1122
    {
 
1123
      /* check that we can add the contours to the glyph */
 
1124
      error = FT_GlyphLoader_CheckPoints( gloader, 0, contours_count );
 
1125
      if ( error )
 
1126
        goto Fail;
 
1127
 
 
1128
      error = face->read_simple_glyph( loader );
 
1129
      if ( error )
 
1130
        goto Fail;
 
1131
 
 
1132
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
1133
 
 
1134
      {
 
1135
        TT_Size  size = (TT_Size)loader->size;
 
1136
 
 
1137
 
 
1138
        error = TT_Process_Simple_Glyph( loader,
 
1139
                                         (FT_Bool)( size && size->debug ) );
 
1140
      }
 
1141
 
 
1142
#else
 
1143
 
 
1144
      error = TT_Process_Simple_Glyph( loader, 0 );
 
1145
 
 
1146
#endif
 
1147
 
 
1148
      if ( error )
 
1149
        goto Fail;
 
1150
 
 
1151
      FT_GlyphLoader_Add( gloader );
 
1152
 
 
1153
      /* Note: We could have put the simple loader source there */
 
1154
      /*       but the code is fat enough already :-)           */
 
1155
    }
 
1156
 
 
1157
    /***********************************************************************/
 
1158
    /***********************************************************************/
 
1159
    /***********************************************************************/
 
1160
 
 
1161
    /* otherwise, load a composite! */
 
1162
    else if ( contours_count == -1 )
 
1163
    {
 
1164
      TT_GlyphSlot  glyph = (TT_GlyphSlot)loader->glyph;
 
1165
      FT_UInt       start_point;
 
1166
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
1167
      FT_UInt       start_contour;
 
1168
      FT_ULong      ins_pos;  /* position of composite instructions, if any */
 
1169
#endif
 
1170
 
 
1171
 
 
1172
      /* for each subglyph, read composite header */
 
1173
      start_point   = gloader->base.outline.n_points;
 
1174
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
1175
      start_contour = gloader->base.outline.n_contours;
 
1176
#endif
 
1177
 
 
1178
      error = face->read_composite_glyph( loader );
 
1179
      if ( error )
 
1180
        goto Fail;
 
1181
 
 
1182
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
1183
      ins_pos = loader->ins_pos;
 
1184
#endif
 
1185
      face->forget_glyph_frame( loader );
 
1186
      opened_frame = 0;
 
1187
 
 
1188
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
1189
 
 
1190
      if ( face->doblend )
 
1191
      {
 
1192
        FT_Int       i, limit;
 
1193
        FT_SubGlyph  subglyph;
 
1194
        FT_Memory    memory = face->root.memory;
 
1195
 
 
1196
 
 
1197
        /* this provides additional offsets */
 
1198
        /* for each component's translation */
 
1199
 
 
1200
        if ( (error = TT_Vary_Get_Glyph_Deltas(
 
1201
                        face,
 
1202
                        glyph_index,
 
1203
                        &deltas,
 
1204
                        gloader->current.num_subglyphs + 4 ) ) )
 
1205
          goto Exit;
 
1206
 
 
1207
        /* Note: No subglyph reallocation here, our pointers are stable. */
 
1208
        subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
 
1209
        limit    = gloader->current.num_subglyphs;
 
1210
 
 
1211
        for ( i = 0; i < limit; ++i, ++subglyph )
 
1212
        {
 
1213
          if ( subglyph->flags & ARGS_ARE_XY_VALUES )
 
1214
          {
 
1215
            subglyph->arg1 += deltas[i].x;
 
1216
            subglyph->arg2 += deltas[i].y;
 
1217
          }
 
1218
        }
 
1219
 
 
1220
        loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
 
1221
        loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
 
1222
        loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
 
1223
        loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
 
1224
 
 
1225
        FT_FREE( deltas );
 
1226
      }
 
1227
 
 
1228
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
1229
 
 
1230
      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
 
1231
      {
 
1232
        loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
 
1233
        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
 
1234
        loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
 
1235
        loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
 
1236
      }
 
1237
 
 
1238
      /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
 
1239
      /* `as is' in the glyph slot (the client application will be     */
 
1240
      /* responsible for interpreting these data)...                   */
 
1241
      /*                                                               */
 
1242
      if ( loader->load_flags & FT_LOAD_NO_RECURSE )
 
1243
      {
 
1244
        /* set up remaining glyph fields */
 
1245
        FT_GlyphLoader_Add( gloader );
 
1246
 
 
1247
        glyph->num_subglyphs = gloader->base.num_subglyphs;
 
1248
        glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
 
1249
        glyph->subglyphs     = gloader->base.subglyphs;
 
1250
 
 
1251
        goto Exit;
 
1252
      }
 
1253
 
 
1254
      /*********************************************************************/
 
1255
      /*********************************************************************/
 
1256
      /*********************************************************************/
 
1257
 
 
1258
      /* Now, read each subglyph independently. */
 
1259
      {
 
1260
        FT_Int       n, num_base_points, num_new_points;
 
1261
        FT_SubGlyph  subglyph       = 0;
 
1262
 
 
1263
        FT_UInt      num_subglyphs  = gloader->current.num_subglyphs;
 
1264
        FT_UInt      num_base_subgs = gloader->base.num_subglyphs;
 
1265
 
 
1266
 
 
1267
        FT_GlyphLoader_Add( gloader );
 
1268
 
 
1269
        for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
 
1270
        {
 
1271
          FT_Vector  pp1, pp2, pp3, pp4;
 
1272
          FT_Pos     x, y;
 
1273
 
 
1274
 
 
1275
          /* Each time we call load_truetype_glyph in this loop, the   */
 
1276
          /* value of `gloader.base.subglyphs' can change due to table */
 
1277
          /* reallocations.  We thus need to recompute the subglyph    */
 
1278
          /* pointer on each iteration.                                */
 
1279
          subglyph = gloader->base.subglyphs + num_base_subgs + n;
 
1280
 
 
1281
          pp1 = loader->pp1;
 
1282
          pp2 = loader->pp2;
 
1283
          pp3 = loader->pp3;
 
1284
          pp4 = loader->pp4;
 
1285
 
 
1286
          num_base_points = gloader->base.outline.n_points;
 
1287
 
 
1288
          error = load_truetype_glyph( loader, subglyph->index,
 
1289
                                       recurse_count + 1 );
 
1290
          if ( error )
 
1291
            goto Fail;
 
1292
 
 
1293
          /* restore subglyph pointer */
 
1294
          subglyph = gloader->base.subglyphs + num_base_subgs + n;
 
1295
 
 
1296
          if ( subglyph->flags & USE_MY_METRICS )
 
1297
          {
 
1298
            pp1 = loader->pp1;
 
1299
            pp2 = loader->pp2;
 
1300
            pp3 = loader->pp3;
 
1301
            pp4 = loader->pp4;
 
1302
          }
 
1303
          else
 
1304
          {
 
1305
            loader->pp1 = pp1;
 
1306
            loader->pp2 = pp2;
 
1307
            loader->pp3 = pp3;
 
1308
            loader->pp4 = pp4;
 
1309
          }
 
1310
 
 
1311
          num_points = gloader->base.outline.n_points;
 
1312
 
 
1313
          num_new_points = num_points - num_base_points;
 
1314
 
 
1315
          /* now perform the transform required for this subglyph */
 
1316
 
 
1317
          if ( subglyph->flags & ( WE_HAVE_A_SCALE     |
 
1318
                                   WE_HAVE_AN_XY_SCALE |
 
1319
                                   WE_HAVE_A_2X2       ) )
 
1320
          {
 
1321
            FT_Vector*  cur   = gloader->base.outline.points +
 
1322
                                  num_base_points;
 
1323
            FT_Vector*  org   = gloader->base.extra_points +
 
1324
                                  num_base_points;
 
1325
            FT_Vector*  limit = cur + num_new_points;
 
1326
 
 
1327
 
 
1328
            for ( ; cur < limit; cur++, org++ )
 
1329
            {
 
1330
              FT_Vector_Transform( cur, &subglyph->transform );
 
1331
              FT_Vector_Transform( org, &subglyph->transform );
 
1332
            }
 
1333
          }
 
1334
 
 
1335
          /* apply offset */
 
1336
 
 
1337
          if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
 
1338
          {
 
1339
            FT_UInt     k = subglyph->arg1;
 
1340
            FT_UInt     l = subglyph->arg2;
 
1341
            FT_Vector*  p1;
 
1342
            FT_Vector*  p2;
 
1343
 
 
1344
 
 
1345
            if ( start_point + k >= (FT_UInt)num_base_points ||
 
1346
                               l >= (FT_UInt)num_new_points  )
 
1347
            {
 
1348
              error = TT_Err_Invalid_Composite;
 
1349
              goto Fail;
 
1350
            }
 
1351
 
 
1352
            l += num_base_points;
 
1353
 
 
1354
            p1 = gloader->base.outline.points + start_point + k;
 
1355
            p2 = gloader->base.outline.points + start_point + l;
 
1356
 
 
1357
            x = p1->x - p2->x;
 
1358
            y = p1->y - p2->y;
 
1359
          }
 
1360
          else
 
1361
          {
 
1362
            x = subglyph->arg1;
 
1363
            y = subglyph->arg2;
 
1364
 
 
1365
  /* Use a default value dependent on                                     */
 
1366
  /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old TT */
 
1367
  /* fonts which don't set the xxx_COMPONENT_OFFSET bit.                  */
 
1368
 
 
1369
#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
 
1370
            if ( !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) &&
 
1371
#else
 
1372
            if (  ( subglyph->flags & SCALED_COMPONENT_OFFSET ) &&
 
1373
#endif
 
1374
                  ( subglyph->flags & ( WE_HAVE_A_SCALE     |
 
1375
                                        WE_HAVE_AN_XY_SCALE |
 
1376
                                        WE_HAVE_A_2X2       )) )
 
1377
            {
 
1378
#if 0
 
1379
 
 
1380
  /*************************************************************************/
 
1381
  /*                                                                       */
 
1382
  /* This algorithm is what Apple documents.  But it doesn't work.         */
 
1383
  /*                                                                       */
 
1384
              int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
 
1385
                                                  : -subglyph->transform.xx;
 
1386
              int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
 
1387
                                                  : -subglyph->transform.yx;
 
1388
              int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
 
1389
                                                  : -subglyph->transform.xy;
 
1390
              int  d = subglyph->transform.yy > 0 ? subglyph->transform.yy
 
1391
                                                  : -subglyph->transform.yy;
 
1392
              int  m = a > b ? a : b;
 
1393
              int  n = c > d ? c : d;
 
1394
 
 
1395
 
 
1396
              if ( a - b <= 33 && a - b >= -33 )
 
1397
                m *= 2;
 
1398
              if ( c - d <= 33 && c - d >= -33 )
 
1399
                n *= 2;
 
1400
              x = FT_MulFix( x, m );
 
1401
              y = FT_MulFix( y, n );
 
1402
 
 
1403
#else /* 0 */
 
1404
 
 
1405
  /*************************************************************************/
 
1406
  /*                                                                       */
 
1407
  /* This algorithm is a guess and works much better than the above.       */
 
1408
  /*                                                                       */
 
1409
              FT_Fixed  mac_xscale = FT_SqrtFixed(
 
1410
                                       FT_MulFix( subglyph->transform.xx,
 
1411
                                                  subglyph->transform.xx ) +
 
1412
                                       FT_MulFix( subglyph->transform.xy,
 
1413
                                                  subglyph->transform.xy) );
 
1414
              FT_Fixed  mac_yscale = FT_SqrtFixed(
 
1415
                                       FT_MulFix( subglyph->transform.yy,
 
1416
                                                  subglyph->transform.yy ) +
 
1417
                                       FT_MulFix( subglyph->transform.yx,
 
1418
                                                  subglyph->transform.yx ) );
 
1419
 
 
1420
 
 
1421
              x = FT_MulFix( x, mac_xscale );
 
1422
              y = FT_MulFix( y, mac_yscale );
 
1423
#endif /* 0 */
 
1424
 
 
1425
            }
 
1426
 
 
1427
            if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
 
1428
            {
 
1429
              x = FT_MulFix( x, x_scale );
 
1430
              y = FT_MulFix( y, y_scale );
 
1431
 
 
1432
              if ( subglyph->flags & ROUND_XY_TO_GRID )
 
1433
              {
 
1434
                x = FT_PIX_ROUND( x );
 
1435
                y = FT_PIX_ROUND( y );
 
1436
              }
 
1437
            }
 
1438
          }
 
1439
 
 
1440
          if ( x || y )
 
1441
          {
 
1442
            translate_array( num_new_points,
 
1443
                             gloader->base.outline.points + num_base_points,
 
1444
                             x, y );
 
1445
 
 
1446
            translate_array( num_new_points,
 
1447
                             gloader->base.extra_points + num_base_points,
 
1448
                             x, y );
 
1449
          }
 
1450
        }
 
1451
 
 
1452
        /*******************************************************************/
 
1453
        /*******************************************************************/
 
1454
        /*******************************************************************/
 
1455
 
 
1456
        /* we have finished loading all sub-glyphs; now, look for */
 
1457
        /* instructions for this composite!                       */
 
1458
 
 
1459
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
1460
 
 
1461
        if ( num_subglyphs > 0               &&
 
1462
             loader->exec                    &&
 
1463
             ins_pos > 0                     &&
 
1464
             subglyph->flags & WE_HAVE_INSTR )
 
1465
        {
 
1466
          FT_UShort       n_ins;
 
1467
          TT_ExecContext  exec = loader->exec;
 
1468
          TT_GlyphZone    pts;
 
1469
          FT_Vector*      pp1;
 
1470
 
 
1471
 
 
1472
          /* read size of instructions */
 
1473
          if ( FT_STREAM_SEEK( ins_pos ) ||
 
1474
               FT_READ_USHORT( n_ins ) )
 
1475
            goto Fail;
 
1476
          FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
 
1477
 
 
1478
          /* in some fonts? */
 
1479
          if ( n_ins == 0xFFFFU )
 
1480
            n_ins = 0;
 
1481
 
 
1482
          /* check it */
 
1483
          if ( n_ins > face->max_profile.maxSizeOfInstructions )
 
1484
          {
 
1485
            FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
 
1486
                        n_ins, subglyph->index ));
 
1487
            error = TT_Err_Too_Many_Hints;
 
1488
            goto Fail;
 
1489
          }
 
1490
 
 
1491
          /* read the instructions */
 
1492
          if ( FT_STREAM_READ( exec->glyphIns, n_ins ) )
 
1493
            goto Fail;
 
1494
 
 
1495
          glyph->control_data = exec->glyphIns;
 
1496
          glyph->control_len  = n_ins;
 
1497
 
 
1498
          error = TT_Set_CodeRange( exec,
 
1499
                                    tt_coderange_glyph,
 
1500
                                    exec->glyphIns,
 
1501
                                    n_ins );
 
1502
          if ( error )
 
1503
            goto Fail;
 
1504
 
 
1505
          error = FT_GlyphLoader_CheckPoints( gloader, num_points + 4, 0 );
 
1506
          if ( error )
 
1507
            goto Fail;
 
1508
 
 
1509
          /* prepare the execution context */
 
1510
          tt_prepare_zone( &exec->pts, &gloader->base,
 
1511
                           start_point, start_contour );
 
1512
          pts = &exec->pts;
 
1513
 
 
1514
          pts->n_points   = (short)( num_points + 4 );
 
1515
          pts->n_contours = gloader->base.outline.n_contours;
 
1516
 
 
1517
          /* add phantom points */
 
1518
          pp1    = pts->cur + num_points;
 
1519
          pp1[0] = loader->pp1;
 
1520
          pp1[1] = loader->pp2;
 
1521
          pp1[2] = loader->pp3;
 
1522
          pp1[3] = loader->pp4;
 
1523
 
 
1524
          pts->tags[num_points    ] = 0;
 
1525
          pts->tags[num_points + 1] = 0;
 
1526
          pts->tags[num_points + 2] = 0;
 
1527
          pts->tags[num_points + 3] = 0;
 
1528
 
 
1529
          /* if hinting, round the phantom points */
 
1530
          if ( IS_HINTED( loader->load_flags ) )
 
1531
          {
 
1532
            pp1[0].x = FT_PIX_ROUND( loader->pp1.x );
 
1533
            pp1[1].x = FT_PIX_ROUND( loader->pp2.x );
 
1534
            pp1[2].y = FT_PIX_ROUND( loader->pp3.y );
 
1535
            pp1[3].y = FT_PIX_ROUND( loader->pp4.y );
 
1536
          }
 
1537
 
 
1538
          {
 
1539
            FT_UInt  k;
 
1540
 
 
1541
 
 
1542
            for ( k = 0; k < num_points; k++ )
 
1543
              pts->tags[k] &= FT_CURVE_TAG_ON;
 
1544
          }
 
1545
 
 
1546
          cur_to_org( num_points + 4, pts );
 
1547
 
 
1548
          /* now consider hinting */
 
1549
          if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
 
1550
          {
 
1551
            exec->is_composite     = TRUE;
 
1552
            exec->pedantic_hinting =
 
1553
              (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC );
 
1554
            error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
 
1555
            if ( error && exec->pedantic_hinting )
 
1556
              goto Fail;
 
1557
          }
 
1558
 
 
1559
          /* save glyph origin and advance points */
 
1560
          loader->pp1 = pp1[0];
 
1561
          loader->pp2 = pp1[1];
 
1562
          loader->pp3 = pp1[2];
 
1563
          loader->pp4 = pp1[3];
 
1564
        }
 
1565
 
 
1566
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
 
1567
 
 
1568
      }
 
1569
      /* end of composite loading */
 
1570
    }
 
1571
    else
 
1572
    {
 
1573
      /* invalid composite count ( negative but not -1 ) */
 
1574
      error = TT_Err_Invalid_Outline;
 
1575
      goto Fail;
 
1576
    }
 
1577
 
 
1578
    /***********************************************************************/
 
1579
    /***********************************************************************/
 
1580
    /***********************************************************************/
 
1581
 
 
1582
  Fail:
 
1583
    if ( opened_frame )
 
1584
      face->forget_glyph_frame( loader );
 
1585
 
 
1586
  Exit:
 
1587
 
 
1588
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
1589
    if ( glyph_data_loaded )
 
1590
      face->root.internal->incremental_interface->funcs->free_glyph_data(
 
1591
        face->root.internal->incremental_interface->object,
 
1592
        &glyph_data );
 
1593
#endif
 
1594
 
 
1595
    return error;
 
1596
  }
 
1597
 
 
1598
 
 
1599
  static FT_Error
 
1600
  compute_glyph_metrics( TT_Loader   loader,
 
1601
                         FT_UInt     glyph_index )
 
1602
  {
 
1603
    FT_BBox       bbox;
 
1604
    TT_Face       face = (TT_Face)loader->face;
 
1605
    FT_Fixed      y_scale;
 
1606
    TT_GlyphSlot  glyph = loader->glyph;
 
1607
    TT_Size       size = (TT_Size)loader->size;
 
1608
 
 
1609
 
 
1610
    y_scale = 0x10000L;
 
1611
    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
 
1612
      y_scale = size->root.metrics.y_scale;
 
1613
 
 
1614
    if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
 
1615
    {
 
1616
      glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
 
1617
 
 
1618
      /* copy outline to our glyph slot */
 
1619
      FT_GlyphLoader_CopyPoints( glyph->internal->loader, loader->gloader );
 
1620
      glyph->outline = glyph->internal->loader->base.outline;
 
1621
 
 
1622
      /* translate array so that (0,0) is the glyph's origin */
 
1623
      FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
 
1624
 
 
1625
      FT_Outline_Get_CBox( &glyph->outline, &bbox );
 
1626
 
 
1627
      if ( IS_HINTED( loader->load_flags ) )
 
1628
      {
 
1629
        /* grid-fit the bounding box */
 
1630
        bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
 
1631
        bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
 
1632
        bbox.xMax = FT_PIX_CEIL( bbox.xMax );
 
1633
        bbox.yMax = FT_PIX_CEIL( bbox.yMax );
 
1634
      }
 
1635
    }
 
1636
    else
 
1637
      bbox = loader->bbox;
 
1638
 
 
1639
    /* get the device-independent horizontal advance.  It is scaled later */
 
1640
    /* by the base layer.                                                 */
 
1641
    {
 
1642
      FT_Pos  advance = loader->linear;
 
1643
 
 
1644
 
 
1645
      /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
 
1646
      /* correctly support DynaLab fonts, which have an incorrect       */
 
1647
      /* `advance_Width_Max' field!  It is used, to my knowledge,       */
 
1648
      /* exclusively in the X-TrueType font server.                     */
 
1649
      /*                                                                */
 
1650
      if ( face->postscript.isFixedPitch                                     &&
 
1651
           ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
 
1652
        advance = face->horizontal.advance_Width_Max;
 
1653
 
 
1654
      /* we need to return the advance in font units in linearHoriAdvance, */
 
1655
      /* it will be scaled later by the base layer.                        */
 
1656
      glyph->linearHoriAdvance = advance;
 
1657
    }
 
1658
 
 
1659
    glyph->metrics.horiBearingX = bbox.xMin;
 
1660
    glyph->metrics.horiBearingY = bbox.yMax;
 
1661
    glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
 
1662
 
 
1663
    /* don't forget to hint the advance when we need to */
 
1664
    if ( IS_HINTED( loader->load_flags ) )
 
1665
      glyph->metrics.horiAdvance = FT_PIX_ROUND( glyph->metrics.horiAdvance );
 
1666
 
 
1667
    /* Now take care of vertical metrics.  In the case where there is    */
 
1668
    /* no vertical information within the font (relatively common), make */
 
1669
    /* up some metrics by `hand'...                                      */
 
1670
 
 
1671
    {
 
1672
      FT_Short   top_bearing;    /* vertical top side bearing (EM units) */
 
1673
      FT_UShort  advance_height; /* vertical advance height   (EM units) */
 
1674
 
 
1675
      FT_Pos     left;     /* scaled vertical left side bearing */
 
1676
      FT_Pos     top;      /* scaled vertical top side bearing  */
 
1677
      FT_Pos     advance;  /* scaled vertical advance height    */
 
1678
 
 
1679
 
 
1680
      /* Get the unscaled top bearing and advance height. */
 
1681
      if ( face->vertical_info &&
 
1682
           face->vertical.number_Of_VMetrics > 0 )
 
1683
      {
 
1684
        advance_height = (FT_UShort)( loader->pp4.y - loader->pp3.y );
 
1685
        top_bearing    = (FT_Short)( loader->pp3.y - bbox.yMax );
 
1686
      }
 
1687
      else
 
1688
      {
 
1689
        /* Make up the distances from the horizontal header.   */
 
1690
 
 
1691
        /* NOTE: The OS/2 values are the only `portable' ones, */
 
1692
        /*       which is why we use them, if there is an OS/2 */
 
1693
        /*       table in the font.  Otherwise, we use the     */
 
1694
        /*       values defined in the horizontal header.      */
 
1695
        /*                                                     */
 
1696
        /* NOTE2: The sTypoDescender is negative, which is why */
 
1697
        /*        we compute the baseline-to-baseline distance */
 
1698
        /*        here with:                                   */
 
1699
        /*             ascender - descender + linegap          */
 
1700
        /*                                                     */
 
1701
        /* NOTE3: This is different from what MS's rasterizer  */
 
1702
        /*        appears to do when getting default values    */
 
1703
        /*        for the vertical phantom points.  We leave   */
 
1704
        /*        the old code untouched, but relying on       */
 
1705
        /*        phantom points alone might be reasonable     */
 
1706
        /*        (i.e., removing the `if' above).             */
 
1707
        if ( face->os2.version != 0xFFFFU )
 
1708
        {
 
1709
          top_bearing    = (FT_Short)( face->os2.sTypoLineGap / 2 );
 
1710
          advance_height = (FT_UShort)( face->os2.sTypoAscender -
 
1711
                                        face->os2.sTypoDescender +
 
1712
                                        face->os2.sTypoLineGap );
 
1713
        }
 
1714
        else
 
1715
        {
 
1716
          top_bearing    = (FT_Short)( face->horizontal.Line_Gap / 2 );
 
1717
          advance_height = (FT_UShort)( face->horizontal.Ascender  +
 
1718
                                        face->horizontal.Descender +
 
1719
                                        face->horizontal.Line_Gap );
 
1720
        }
 
1721
      }
 
1722
 
 
1723
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
1724
 
 
1725
      /* If this is an incrementally loaded font see if there are */
 
1726
      /* overriding metrics for this glyph.                       */
 
1727
      if ( face->root.internal->incremental_interface &&
 
1728
           face->root.internal->incremental_interface->funcs->get_glyph_metrics )
 
1729
      {
 
1730
        FT_Incremental_MetricsRec  metrics;
 
1731
        FT_Error                   error = 0;
 
1732
 
 
1733
 
 
1734
        metrics.bearing_x = 0;
 
1735
        metrics.bearing_y = top_bearing;
 
1736
        metrics.advance = advance_height;
 
1737
        error =
 
1738
          face->root.internal->incremental_interface->funcs->get_glyph_metrics(
 
1739
            face->root.internal->incremental_interface->object,
 
1740
            glyph_index, TRUE, &metrics );
 
1741
 
 
1742
        if ( error )
 
1743
          return error;
 
1744
 
 
1745
        top_bearing    = (FT_Short)metrics.bearing_y;
 
1746
        advance_height = (FT_UShort)metrics.advance;
 
1747
      }
 
1748
 
 
1749
      /* GWW: Do vertical metrics get loaded incrementally too? */
 
1750
 
 
1751
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
1752
 
 
1753
      /* We must adjust the top_bearing value from the bounding box given */
 
1754
      /* in the glyph header to the bounding box calculated with          */
 
1755
      /* FT_Get_Outline_CBox().                                           */
 
1756
 
 
1757
      /* scale the metrics */
 
1758
      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
 
1759
      {
 
1760
        top     = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
 
1761
                    - bbox.yMax;
 
1762
        advance = FT_MulFix( advance_height, y_scale );
 
1763
      }
 
1764
      else
 
1765
      {
 
1766
        top     = top_bearing + loader->bbox.yMax - bbox.yMax;
 
1767
        advance = advance_height;
 
1768
      }
 
1769
 
 
1770
      /* set the advance height in design units.  It is scaled later by */
 
1771
      /* the base layer.                                                */
 
1772
      glyph->linearVertAdvance = advance_height;
 
1773
 
 
1774
      /* XXX: for now, we have no better algorithm for the lsb, but it */
 
1775
      /*      should work fine.                                        */
 
1776
      /*                                                               */
 
1777
      left = ( bbox.xMin - bbox.xMax ) / 2;
 
1778
 
 
1779
      /* grid-fit them if necessary */
 
1780
      if ( IS_HINTED( loader->load_flags ) )
 
1781
      {
 
1782
        left    = FT_PIX_FLOOR( left );
 
1783
        top     = FT_PIX_CEIL( top );
 
1784
        advance = FT_PIX_ROUND( advance );
 
1785
      }
 
1786
 
 
1787
      glyph->metrics.vertBearingX = left;
 
1788
      glyph->metrics.vertBearingY = top;
 
1789
      glyph->metrics.vertAdvance  = advance;
 
1790
    }
 
1791
 
 
1792
    /* adjust advance width to the value contained in the hdmx table */
 
1793
    if ( !face->postscript.isFixedPitch && size &&
 
1794
         IS_HINTED( loader->load_flags )        )
 
1795
    {
 
1796
      FT_Byte*  widths = Get_Advance_Widths( face,
 
1797
                                             size->root.metrics.x_ppem );
 
1798
 
 
1799
 
 
1800
      if ( widths )
 
1801
        glyph->metrics.horiAdvance = widths[glyph_index] << 6;
 
1802
    }
 
1803
 
 
1804
    /* set glyph dimensions */
 
1805
    glyph->metrics.width  = bbox.xMax - bbox.xMin;
 
1806
    glyph->metrics.height = bbox.yMax - bbox.yMin;
 
1807
 
 
1808
    return 0;
 
1809
  }
 
1810
 
 
1811
 
 
1812
  /*************************************************************************/
 
1813
  /*                                                                       */
 
1814
  /* <Function>                                                            */
 
1815
  /*    TT_Load_Glyph                                                      */
 
1816
  /*                                                                       */
 
1817
  /* <Description>                                                         */
 
1818
  /*    A function used to load a single glyph within a given glyph slot,  */
 
1819
  /*    for a given size.                                                  */
 
1820
  /*                                                                       */
 
1821
  /* <Input>                                                               */
 
1822
  /*    glyph       :: A handle to a target slot object where the glyph    */
 
1823
  /*                   will be loaded.                                     */
 
1824
  /*                                                                       */
 
1825
  /*    size        :: A handle to the source face size at which the glyph */
 
1826
  /*                   must be scaled/loaded.                              */
 
1827
  /*                                                                       */
 
1828
  /*    glyph_index :: The index of the glyph in the font file.            */
 
1829
  /*                                                                       */
 
1830
  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
 
1831
  /*                   FT_LOAD_XXX constants can be used to control the    */
 
1832
  /*                   glyph loading process (e.g., whether the outline    */
 
1833
  /*                   should be scaled, whether to load bitmaps or not,   */
 
1834
  /*                   whether to hint the outline, etc).                  */
 
1835
  /*                                                                       */
 
1836
  /* <Return>                                                              */
 
1837
  /*    FreeType error code.  0 means success.                             */
 
1838
  /*                                                                       */
 
1839
  FT_LOCAL_DEF( FT_Error )
 
1840
  TT_Load_Glyph( TT_Size       size,
 
1841
                 TT_GlyphSlot  glyph,
 
1842
                 FT_UInt       glyph_index,
 
1843
                 FT_Int32      load_flags )
 
1844
  {
 
1845
    SFNT_Service  sfnt;
 
1846
    TT_Face       face;
 
1847
    FT_Stream     stream;
 
1848
    FT_Error      error;
 
1849
    TT_LoaderRec  loader;
 
1850
 
 
1851
 
 
1852
    face   = (TT_Face)glyph->face;
 
1853
    sfnt   = (SFNT_Service)face->sfnt;
 
1854
    stream = face->root.stream;
 
1855
    error  = 0;
 
1856
 
 
1857
    if ( !size || ( load_flags & FT_LOAD_NO_SCALE )   ||
 
1858
                  ( load_flags & FT_LOAD_NO_RECURSE ) )
 
1859
    {
 
1860
      size        = NULL;
 
1861
      load_flags |= FT_LOAD_NO_SCALE   |
 
1862
                    FT_LOAD_NO_HINTING |
 
1863
                    FT_LOAD_NO_BITMAP;
 
1864
    }
 
1865
 
 
1866
    glyph->num_subglyphs = 0;
 
1867
 
 
1868
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
1869
 
 
1870
    /* try to load embedded bitmap if any              */
 
1871
    /*                                                 */
 
1872
    /* XXX: The convention should be emphasized in     */
 
1873
    /*      the documents because it can be confusing. */
 
1874
    if ( size                                    &&
 
1875
         size->strike_index != 0xFFFFU           &&
 
1876
         sfnt->load_sbits                        &&
 
1877
         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
 
1878
 
 
1879
    {
 
1880
      TT_SBit_MetricsRec  metrics;
 
1881
 
 
1882
 
 
1883
      error = sfnt->load_sbit_image( face,
 
1884
                                     (FT_ULong)size->strike_index,
 
1885
                                     glyph_index,
 
1886
                                     (FT_Int)load_flags,
 
1887
                                     stream,
 
1888
                                     &glyph->bitmap,
 
1889
                                     &metrics );
 
1890
      if ( !error )
 
1891
      {
 
1892
        glyph->outline.n_points   = 0;
 
1893
        glyph->outline.n_contours = 0;
 
1894
 
 
1895
        glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
 
1896
        glyph->metrics.height = (FT_Pos)metrics.height << 6;
 
1897
 
 
1898
        glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
 
1899
        glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
 
1900
        glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
 
1901
 
 
1902
        glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
 
1903
        glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
 
1904
        glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
 
1905
 
 
1906
        glyph->format = FT_GLYPH_FORMAT_BITMAP;
 
1907
        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
 
1908
        {
 
1909
          glyph->bitmap_left = metrics.vertBearingX;
 
1910
          glyph->bitmap_top  = metrics.vertBearingY;
 
1911
        }
 
1912
        else
 
1913
        {
 
1914
          glyph->bitmap_left = metrics.horiBearingX;
 
1915
          glyph->bitmap_top  = metrics.horiBearingY;
 
1916
        }
 
1917
        return error;
 
1918
      }
 
1919
    }
 
1920
 
 
1921
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
1922
 
 
1923
    /* return immediately if we only want the embedded bitmaps */
 
1924
    if ( load_flags & FT_LOAD_SBITS_ONLY )
 
1925
      return TT_Err_Invalid_Argument;
 
1926
 
 
1927
    /* seek to the beginning of the glyph table.  For Type 42 fonts      */
 
1928
    /* the table might be accessed from a Postscript stream or something */
 
1929
    /* else...                                                           */
 
1930
 
 
1931
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
1932
 
 
1933
    /* Don't look for the glyph table if this is an incremental font. */
 
1934
    if ( !face->root.internal->incremental_interface )
 
1935
 
 
1936
#endif
 
1937
 
 
1938
    {
 
1939
      error = face->goto_table( face, TTAG_glyf, stream, 0 );
 
1940
      if ( error )
 
1941
      {
 
1942
        FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
 
1943
        goto Exit;
 
1944
      }
 
1945
    }
 
1946
 
 
1947
    FT_MEM_ZERO( &loader, sizeof ( loader ) );
 
1948
 
 
1949
    /* update the glyph zone bounds */
 
1950
    {
 
1951
      FT_GlyphLoader  gloader = FT_FACE_DRIVER(face)->glyph_loader;
 
1952
 
 
1953
 
 
1954
      loader.gloader = gloader;
 
1955
 
 
1956
      FT_GlyphLoader_Rewind( gloader );
 
1957
 
 
1958
      tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
 
1959
      tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
 
1960
    }
 
1961
 
 
1962
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
1963
 
 
1964
    if ( size )
 
1965
    {
 
1966
      /* query new execution context */
 
1967
      loader.exec = size->debug ? size->context : TT_New_Context( face );
 
1968
      if ( !loader.exec )
 
1969
        return TT_Err_Could_Not_Find_Context;
 
1970
 
 
1971
      TT_Load_Context( loader.exec, face, size );
 
1972
      loader.instructions = loader.exec->glyphIns;
 
1973
 
 
1974
      /* load default graphics state - if needed */
 
1975
      if ( size->GS.instruct_control & 2 )
 
1976
        loader.exec->GS = tt_default_graphics_state;
 
1977
    }
 
1978
 
 
1979
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
 
1980
 
 
1981
    /* clear all outline flags, except the `owner' one */
 
1982
    glyph->outline.flags = 0;
 
1983
 
 
1984
    /* let's initialize the rest of our loader now */
 
1985
 
 
1986
    loader.load_flags    = load_flags;
 
1987
 
 
1988
    loader.face   = (FT_Face)face;
 
1989
    loader.size   = (FT_Size)size;
 
1990
    loader.glyph  = (FT_GlyphSlot)glyph;
 
1991
    loader.stream = stream;
 
1992
 
 
1993
#ifdef FT_CONFIG_OPTION_INCREMENTAL
 
1994
 
 
1995
    if ( face->root.internal->incremental_interface )
 
1996
      loader.glyf_offset = 0;
 
1997
    else
 
1998
 
 
1999
#endif
 
2000
 
 
2001
      loader.glyf_offset = FT_STREAM_POS();
 
2002
 
 
2003
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
2004
 
 
2005
    /* if the cvt program has disabled hinting, the argument */
 
2006
    /* is ignored.                                           */
 
2007
    if ( size && ( size->GS.instruct_control & 1 ) )
 
2008
      loader.load_flags |= FT_LOAD_NO_HINTING;
 
2009
 
 
2010
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
 
2011
 
 
2012
    /* Main loading loop */
 
2013
    glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
 
2014
    glyph->num_subglyphs = 0;
 
2015
 
 
2016
    error = load_truetype_glyph( &loader, glyph_index, 0 );
 
2017
    if ( !error )
 
2018
      compute_glyph_metrics( &loader, glyph_index );
 
2019
 
 
2020
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
2021
 
 
2022
    if ( !size || !size->debug )
 
2023
      TT_Done_Context( loader.exec );
 
2024
 
 
2025
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
 
2026
 
 
2027
    /* Set the `high precision' bit flag.                           */
 
2028
    /* This is _critical_ to get correct output for monochrome      */
 
2029
    /* TrueType glyphs at all sizes using the bytecode interpreter. */
 
2030
    /*                                                              */
 
2031
    if ( size && size->root.metrics.y_ppem < 24 )
 
2032
      glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
 
2033
 
 
2034
  Exit:
 
2035
    return error;
 
2036
  }
 
2037
 
 
2038
 
 
2039
/* END */