~ubuntu-branches/ubuntu/wily/hedgewars/wily

« back to all changes in this revision

Viewing changes to misc/libfreetype/src/truetype/ttgload.c

  • Committer: Package Import Robot
  • Author(s): Dmitry E. Oboukhov
  • Date: 2011-09-23 10:16:55 UTC
  • mfrom: (1.2.11 upstream)
  • Revision ID: package-import@ubuntu.com-20110923101655-3977th2gc5n0a3pv
Tags: 0.9.16-1
* New upstream version.
 + Downloadable content! Simply click to install any content.
   New voices, hats, maps, themes, translations, music, scripts...
   Hedgewars is now more customisable than ever before! As time goes
   by we will be soliciting community content to feature on this page,
   so remember to check it from time to time. If you decide you want
   to go back to standard Hedgewars, just remove the Data directory
   from your Hedgewars config directory.
 + 3-D rendering! Diorama-like rendering of the game in a variety
   of 3D modes. Let us know which ones work best for you, we didn't
   really have the equipment to test them all.
 + Resizable game window.
 + New utilities! The Time Box will remove one of your hedgehogs
   from the game for a while, protecting from attack until it returns,
   somewhere else on the map. Land spray will allow you to build bridges,
   seal up holes, or just make life unpleasant for your enemies.
 + New single player: Bamboo Thicket, That Sinking Feeling, Newton and
   the Tree and multi-player: The Specialists, Space Invaders,
   Racer - scripts! And a ton more script hooks for scripters
 + New twists on old weapons. Drill strike, seduction and fire have
   been adjusted. Defective mines have been added, rope can attach to
   hogs/crates/barrels again, grenades now have variable bounce (use
   precise key + 1-5). Portal gun is now more usable in flight and
   all game actions are a lot faster.
 + New theme - Golf, dozens of new community hats and a new
   localised Default voice, Ukranian.

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