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