ttgload.c revision f7f82d773b7eac9e5b570a3b64bd0325b0beb62c
1/***************************************************************************/
2/*                                                                         */
3/*  ttgload.c                                                              */
4/*                                                                         */
5/*    TrueType Glyph Loader (body).                                        */
6/*                                                                         */
7/*  Copyright 1996-2001 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#include "tterrors.h"
30
31
32  /*************************************************************************/
33  /*                                                                       */
34  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
35  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
36  /* messages during execution.                                            */
37  /*                                                                       */
38#undef  FT_COMPONENT
39#define FT_COMPONENT  trace_ttgload
40
41
42  /*************************************************************************/
43  /*                                                                       */
44  /* Composite font flags.                                                 */
45  /*                                                                       */
46#define ARGS_ARE_WORDS       0x001
47#define ARGS_ARE_XY_VALUES   0x002
48#define ROUND_XY_TO_GRID     0x004
49#define WE_HAVE_A_SCALE      0x008
50/* reserved                  0x010 */
51#define MORE_COMPONENTS      0x020
52#define WE_HAVE_AN_XY_SCALE  0x040
53#define WE_HAVE_A_2X2        0x080
54#define WE_HAVE_INSTR        0x100
55#define USE_MY_METRICS       0x200
56
57
58
59  /*************************************************************************/
60  /*                                                                       */
61  /* <Function>                                                            */
62  /*    TT_Get_Metrics                                                     */
63  /*                                                                       */
64  /* <Description>                                                         */
65  /*    Returns the horizontal or vertical metrics in font units for a     */
66  /*    given glyph.  The metrics are the left side bearing (resp. top     */
67  /*    side bearing) and advance width (resp. advance height).            */
68  /*                                                                       */
69  /* <Input>                                                               */
70  /*    header  :: A pointer to either the horizontal or vertical metrics  */
71  /*               structure.                                              */
72  /*                                                                       */
73  /*    index   :: The glyph index.                                        */
74  /*                                                                       */
75  /* <Output>                                                              */
76  /*    bearing :: The bearing, either left side or top side.              */
77  /*                                                                       */
78  /*    advance :: The advance width resp. advance height.                 */
79  /*                                                                       */
80  /* <Note>                                                                */
81  /*    This function will much probably move to another component in the  */
82  /*    near future, but I haven't decided which yet.                      */
83  /*                                                                       */
84  FT_LOCAL_DEF void
85  TT_Get_Metrics( TT_HoriHeader*  header,
86                  FT_UInt         index,
87                  FT_Short*       bearing,
88                  FT_UShort*      advance )
89  {
90    TT_LongMetrics*  longs_m;
91    FT_UShort        k = header->number_Of_HMetrics;
92
93
94    if ( index < (FT_UInt)k )
95    {
96      longs_m  = (TT_LongMetrics*)header->long_metrics + index;
97      *bearing = longs_m->bearing;
98      *advance = longs_m->advance;
99    }
100    else
101    {
102      *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
103      *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
104    }
105  }
106
107
108  /*************************************************************************/
109  /*                                                                       */
110  /* Returns the horizontal metrics in font units for a given glyph.  If   */
111  /* `check' is true, take care of monospaced fonts by returning the       */
112  /* advance width maximum.                                                */
113  /*                                                                       */
114  static void
115  Get_HMetrics( TT_Face     face,
116                FT_UInt     index,
117                FT_Bool     check,
118                FT_Short*   lsb,
119                FT_UShort*  aw )
120  {
121    TT_Get_Metrics( &face->horizontal, index, lsb, aw );
122
123    if ( check && face->postscript.isFixedPitch )
124      *aw = face->horizontal.advance_Width_Max;
125  }
126
127
128  /*************************************************************************/
129  /*                                                                       */
130  /*    Returns the advance width table for a given pixel size if it is    */
131  /*    found in the font's `hdmx' table (if any).                         */
132  /*                                                                       */
133  static FT_Byte*
134  Get_Advance_Widths( TT_Face    face,
135                      FT_UShort  ppem )
136  {
137    FT_UShort  n;
138
139    for ( n = 0; n < face->hdmx.num_records; n++ )
140      if ( face->hdmx.records[n].ppem == ppem )
141        return face->hdmx.records[n].widths;
142
143    return NULL;
144  }
145
146
147#define cur_to_org( n, zone ) \
148          MEM_Copy( (zone)->org, (zone)->cur, (n) * sizeof ( FT_Vector ) )
149
150#define org_to_cur( n, zone ) \
151          MEM_Copy( (zone)->cur, (zone)->org, (n) * sizeof ( FT_Vector ) )
152
153
154  /*************************************************************************/
155  /*                                                                       */
156  /*    Translates an array of coordinates.                                */
157  /*                                                                       */
158  static void
159  translate_array( FT_UInt     n,
160                   FT_Vector*  coords,
161                   FT_Pos      delta_x,
162                   FT_Pos      delta_y )
163  {
164    FT_UInt  k;
165
166
167    if ( delta_x )
168      for ( k = 0; k < n; k++ )
169        coords[k].x += delta_x;
170
171    if ( delta_y )
172      for ( k = 0; k < n; k++ )
173        coords[k].y += delta_y;
174  }
175
176
177  static void
178  tt_prepare_zone( TT_GlyphZone*  zone,
179                   FT_GlyphLoad*  load,
180                   FT_UInt        start_point,
181                   FT_UInt        start_contour )
182  {
183    zone->n_points   = (FT_UShort)( load->outline.n_points - start_point );
184    zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour );
185    zone->org        = load->extra_points + start_point;
186    zone->cur        = load->outline.points + start_point;
187    zone->tags       = (FT_Byte*)load->outline.tags + start_point;
188    zone->contours   = (FT_UShort*)load->outline.contours + start_contour;
189  }
190
191
192#undef  IS_HINTED
193#define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
194
195
196  /*************************************************************************/
197  /*                                                                       */
198  /*  The following functions are used by default with TrueType fonts.     */
199  /*  However, they can be replaced by alternatives if we need to support  */
200  /*  TrueType-compressed formats (like MicroType) in the future.          */
201  /*                                                                       */
202  /*************************************************************************/
203
204  FT_CALLBACK_DEF( FT_Error )
205  TT_Access_Glyph_Frame( TT_Loader*  loader,
206                         FT_UInt     glyph_index,
207                         FT_ULong    offset,
208                         FT_UInt     byte_count )
209  {
210    FT_Error   error;
211    FT_Stream  stream = loader->stream;
212
213    /* for non-debug mode */
214    FT_UNUSED( glyph_index );
215
216
217    FT_TRACE5(( "Glyph %ld\n", glyph_index ));
218
219    /* the following line sets the `error' variable through macros! */
220    if ( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) )
221      return error;
222
223    return TT_Err_Ok;
224  }
225
226
227  FT_CALLBACK_DEF( void )
228  TT_Forget_Glyph_Frame( TT_Loader*  loader )
229  {
230    FT_Stream  stream = loader->stream;
231
232
233    FORGET_Frame();
234  }
235
236
237  FT_CALLBACK_DEF( FT_Error )
238  TT_Load_Glyph_Header( TT_Loader*  loader )
239  {
240    FT_Stream   stream   = loader->stream;
241    FT_Int      byte_len = loader->byte_len - 10;
242
243    if ( byte_len < 0 )
244      return TT_Err_Invalid_Outline;
245
246    loader->n_contours = GET_Short();
247
248    loader->bbox.xMin = GET_Short();
249    loader->bbox.yMin = GET_Short();
250    loader->bbox.xMax = GET_Short();
251    loader->bbox.yMax = GET_Short();
252
253    FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
254    FT_TRACE5(( "  xMin: %4d  xMax: %4d\n", loader->bbox.xMin,
255                                            loader->bbox.xMax ));
256    FT_TRACE5(( "  yMin: %4d  yMax: %4d\n", loader->bbox.yMin,
257                                            loader->bbox.yMax ));
258    loader->byte_len = byte_len;
259
260    return TT_Err_Ok;
261  }
262
263
264  FT_CALLBACK_DEF( FT_Error )
265  TT_Load_Simple_Glyph( TT_Loader*  load )
266  {
267    FT_Error         error;
268    FT_Stream        stream     = load->stream;
269    FT_GlyphLoader*  gloader    = load->gloader;
270    FT_Int           n_contours = load->n_contours;
271    FT_Outline*      outline;
272    TT_Face          face    = (TT_Face)load->face;
273    TT_GlyphSlot     slot    = (TT_GlyphSlot)load->glyph;
274    FT_UShort        n_ins;
275    FT_Int           n, n_points;
276    FT_Int           byte_len = load->byte_len;
277
278
279    /* reading the contours endpoints & number of points */
280    {
281      short*  cur   = gloader->current.outline.contours;
282      short*  limit = cur + n_contours;
283
284      /* check room for contours array + instructions count */
285      byte_len -= 2*(n_contours+1);
286      if ( byte_len < 0 )
287        goto Invalid_Outline;
288
289      for ( ; cur < limit; cur++ )
290        cur[0] = GET_UShort();
291
292      n_points = 0;
293      if ( n_contours > 0 )
294        n_points = cur[-1] + 1;
295
296      error = FT_GlyphLoader_Check_Points( gloader, n_points + 2, 0 );
297      if ( error )
298        goto Fail;
299
300      /* we'd better check the contours table right now */
301      outline = &gloader->current.outline;
302
303      for ( cur = outline->contours + 1; cur < limit; cur++ )
304        if ( cur[-1] >= cur[0] )
305          goto Invalid_Outline;
306    }
307
308    /* reading the bytecode instructions */
309    slot->control_len  = 0;
310    slot->control_data = 0;
311
312    n_ins = GET_UShort();
313
314    FT_TRACE5(( "  Instructions size: %d\n", n_ins ));
315
316    if ( n_ins > face->max_profile.maxSizeOfInstructions )
317    {
318      FT_TRACE0(( "ERROR: Too many instructions!\n" ));
319      error = TT_Err_Too_Many_Hints;
320      goto Fail;
321    }
322
323    byte_len -= n_ins;
324    if ( byte_len < 0 )
325    {
326      FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
327      error = TT_Err_Too_Many_Hints;
328      goto Fail;
329    }
330
331#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
332
333    if ( ( load->load_flags                        &
334         ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
335           load->instructions )
336    {
337      slot->control_len  = n_ins;
338      slot->control_data = load->instructions;
339
340      MEM_Copy( load->instructions, stream->cursor, n_ins );
341    }
342
343#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
344
345    stream->cursor += n_ins;
346
347    /* reading the point tags */
348    {
349      FT_Byte*  flag  = (FT_Byte*)outline->tags;
350      FT_Byte*  limit = flag + n_points;
351      FT_Byte   c, count;
352
353
354      while ( flag < limit )
355      {
356        if ( --byte_len < 0 )
357          goto Invalid_Outline;
358
359        *flag++ = c = GET_Byte();
360        if ( c & 8 )
361        {
362          if ( --byte_len < 0 )
363            goto Invalid_Outline;
364
365          count = GET_Byte();
366          if ( flag + count > limit )
367            goto Invalid_Outline;
368
369          for ( ; count > 0; count-- )
370            *flag++ = c;
371        }
372      }
373
374      /* check that there is enough room to load the coordinates */
375      for ( flag = (FT_Byte*)outline->tags; flag < limit; flag++ )
376      {
377        if ( *flag & 2 )
378          byte_len -= 1;
379        else if ( (*flag & 16) == 0 )
380          byte_len -= 2;
381
382        if ( *flag & 4 )
383          byte_len -= 1;
384        else if ( (*flag & 32) == 0 )
385          byte_len -= 2;
386      }
387
388      if ( byte_len < 0 )
389        goto Invalid_Outline;
390    }
391
392
393    /* reading the X coordinates */
394
395    {
396      FT_Vector*  vec   = outline->points;
397      FT_Vector*  limit = vec + n_points;
398      FT_Byte*    flag  = (FT_Byte*)outline->tags;
399      FT_Pos      x     = 0;
400
401
402      for ( ; vec < limit; vec++, flag++ )
403      {
404        FT_Pos  y = 0;
405
406
407        if ( *flag & 2 )
408        {
409          y = GET_Byte();
410          if ( ( *flag & 16 ) == 0 )
411            y = -y;
412        }
413        else if ( ( *flag & 16 ) == 0 )
414          y = GET_Short();
415
416        x     += y;
417        vec->x = x;
418      }
419    }
420
421    /* reading the Y coordinates */
422
423    {
424      FT_Vector*  vec   = gloader->current.outline.points;
425      FT_Vector*  limit = vec + n_points;
426      FT_Byte*    flag  = (FT_Byte*)outline->tags;
427      FT_Pos      x     = 0;
428
429
430      for ( ; vec < limit; vec++, flag++ )
431      {
432        FT_Pos  y = 0;
433
434
435        if ( *flag & 4 )
436        {
437          y = GET_Byte();
438          if ( ( *flag & 32 ) == 0 )
439            y = -y;
440        }
441        else if ( ( *flag & 32 ) == 0 )
442          y = GET_Short();
443
444        x     += y;
445        vec->y = x;
446      }
447    }
448
449    /* clear the touch tags */
450    for ( n = 0; n < n_points; n++ )
451      outline->tags[n] &= FT_Curve_Tag_On;
452
453    outline->n_points   = (FT_UShort)n_points;
454    outline->n_contours = (FT_Short) n_contours;
455
456    load->byte_len = byte_len;
457
458  Fail:
459    return error;
460
461  Invalid_Outline:
462    error = TT_Err_Invalid_Outline;
463    goto Fail;
464  }
465
466
467  FT_CALLBACK_DEF( FT_Error )
468  TT_Load_Composite_Glyph( TT_Loader*  loader )
469  {
470    FT_Error         error;
471    FT_Stream        stream  = loader->stream;
472    FT_GlyphLoader*  gloader = loader->gloader;
473    FT_SubGlyph*     subglyph;
474    FT_UInt          num_subglyphs;
475    FT_Int           byte_len = loader->byte_len;
476
477
478    num_subglyphs = 0;
479
480    do
481    {
482      FT_Fixed  xx, xy, yy, yx;
483
484
485      /* check that we can load a new subglyph */
486      error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs + 1 );
487      if ( error )
488        goto Fail;
489
490      /* check room */
491      byte_len -= 4;
492      if ( byte_len < 0 )
493        goto Invalid_Composite;
494
495      subglyph = gloader->current.subglyphs + num_subglyphs;
496
497      subglyph->arg1 = subglyph->arg2 = 0;
498
499      subglyph->flags = GET_UShort();
500      subglyph->index = GET_UShort();
501
502      /* check room */
503      byte_len -= 2;
504      if ( subglyph->flags & ARGS_ARE_WORDS )
505        byte_len -= 2;
506      if ( subglyph->flags & WE_HAVE_A_SCALE )
507        byte_len -= 2;
508      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
509        byte_len -= 4;
510      else if ( subglyph->flags & WE_HAVE_A_2X2 )
511        byte_len -= 8;
512
513      if ( byte_len < 0 )
514        goto Invalid_Composite;
515
516      /* read arguments */
517      if ( subglyph->flags & ARGS_ARE_WORDS )
518      {
519        subglyph->arg1 = GET_Short();
520        subglyph->arg2 = GET_Short();
521      }
522      else
523      {
524        subglyph->arg1 = GET_Char();
525        subglyph->arg2 = GET_Char();
526      }
527
528      /* read transform */
529      xx = yy = 0x10000L;
530      xy = yx = 0;
531
532      if ( subglyph->flags & WE_HAVE_A_SCALE )
533      {
534        xx = (FT_Fixed)GET_Short() << 2;
535        yy = xx;
536      }
537      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
538      {
539        xx = (FT_Fixed)GET_Short() << 2;
540        yy = (FT_Fixed)GET_Short() << 2;
541      }
542      else if ( subglyph->flags & WE_HAVE_A_2X2 )
543      {
544        xx = (FT_Fixed)GET_Short() << 2;
545        xy = (FT_Fixed)GET_Short() << 2;
546        yx = (FT_Fixed)GET_Short() << 2;
547        yy = (FT_Fixed)GET_Short() << 2;
548      }
549
550      subglyph->transform.xx = xx;
551      subglyph->transform.xy = xy;
552      subglyph->transform.yx = yx;
553      subglyph->transform.yy = yy;
554
555      num_subglyphs++;
556
557    } while ( subglyph->flags & MORE_COMPONENTS );
558
559    gloader->current.num_subglyphs = num_subglyphs;
560
561#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
562    {
563      /* we must undo the ACCESS_Frame in order to point to the */
564      /* composite instructions, if we find some.               */
565      /* we will process them later...                          */
566      /*                                                        */
567      loader->ins_pos = (FT_ULong)( FILE_Pos() +
568                                    stream->cursor - stream->limit );
569    }
570#endif
571
572    loader->byte_len = byte_len;
573
574  Fail:
575    return error;
576
577  Invalid_Composite:
578    error = TT_Err_Invalid_Composite;
579    goto Fail;
580  }
581
582
583  FT_LOCAL_DEF void
584  TT_Init_Glyph_Loading( TT_Face  face )
585  {
586    face->access_glyph_frame   = TT_Access_Glyph_Frame;
587    face->read_glyph_header    = TT_Load_Glyph_Header;
588    face->read_simple_glyph    = TT_Load_Simple_Glyph;
589    face->read_composite_glyph = TT_Load_Composite_Glyph;
590    face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
591  }
592
593
594  /*************************************************************************/
595  /*                                                                       */
596  /* <Function>                                                            */
597  /*    TT_Process_Simple_Glyph                                            */
598  /*                                                                       */
599  /* <Description>                                                         */
600  /*    Once a simple glyph has been loaded, it needs to be processed.     */
601  /*    Usually, this means scaling and hinting through bytecode           */
602  /*    interpretation.                                                    */
603  /*                                                                       */
604  static FT_Error
605  TT_Process_Simple_Glyph( TT_Loader*  load,
606                           FT_Bool     debug )
607  {
608    FT_GlyphLoader*  gloader  = load->gloader;
609    FT_Outline*      outline  = &gloader->current.outline;
610    FT_UInt          n_points = outline->n_points;
611    FT_UInt          n_ins;
612    TT_GlyphZone*    zone     = &load->zone;
613    FT_Error         error    = TT_Err_Ok;
614
615    FT_UNUSED( debug );  /* used by truetype interpreter only */
616
617
618    n_ins = load->glyph->control_len;
619
620    /* add shadow points */
621
622    /* Now add the two shadow points at n and n + 1.    */
623    /* We need the left side bearing and advance width. */
624
625    {
626      FT_Vector*  pp1;
627      FT_Vector*  pp2;
628
629
630      /* pp1 = xMin - lsb */
631      pp1    = outline->points + n_points;
632      pp1->x = load->bbox.xMin - load->left_bearing;
633      pp1->y = 0;
634
635      /* pp2 = pp1 + aw */
636      pp2    = pp1 + 1;
637      pp2->x = pp1->x + load->advance;
638      pp2->y = 0;
639
640      outline->tags[n_points    ] = 0;
641      outline->tags[n_points + 1] = 0;
642    }
643
644    /* Note that we return two more points that are not */
645    /* part of the glyph outline.                       */
646
647    n_points += 2;
648
649    /* set up zone for hinting */
650    tt_prepare_zone( zone, &gloader->current, 0, 0 );
651
652    /* eventually scale the glyph */
653    if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
654    {
655      FT_Vector*  vec     = zone->cur;
656      FT_Vector*  limit   = vec + n_points;
657      FT_Fixed    x_scale = load->size->metrics.x_scale;
658      FT_Fixed    y_scale = load->size->metrics.y_scale;
659
660
661      /* first scale the glyph points */
662      for ( ; vec < limit; vec++ )
663      {
664        vec->x = FT_MulFix( vec->x, x_scale );
665        vec->y = FT_MulFix( vec->y, y_scale );
666      }
667    }
668
669    cur_to_org( n_points, zone );
670
671    /* eventually hint the glyph */
672    if ( IS_HINTED( load->load_flags ) )
673    {
674      FT_Pos  x = zone->org[n_points-2].x;
675
676
677      x = ( ( x + 32 ) & -64 ) - x;
678      translate_array( n_points, zone->org, x, 0 );
679
680      org_to_cur( n_points, zone );
681
682      zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
683
684#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
685
686      /* now consider hinting */
687      if ( n_ins > 0 )
688      {
689        error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
690                                  load->exec->glyphIns, n_ins );
691        if ( error )
692          goto Exit;
693
694        load->exec->is_composite     = FALSE;
695        load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
696                                                  FT_LOAD_PEDANTIC );
697        load->exec->pts              = *zone;
698        load->exec->pts.n_points    += 2;
699
700        error = TT_Run_Context( load->exec, debug );
701        if ( error && load->exec->pedantic_hinting )
702          goto Exit;
703
704        error = TT_Err_Ok;  /* ignore bytecode errors in non-pedantic mode */
705      }
706
707#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
708
709    }
710
711    /* save glyph phantom points */
712    if ( !load->preserve_pps )
713    {
714      load->pp1 = zone->cur[n_points - 2];
715      load->pp2 = zone->cur[n_points - 1];
716    }
717
718#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
719  Exit:
720#endif
721    return error;
722  }
723
724
725  /*************************************************************************/
726  /*                                                                       */
727  /* <Function>                                                            */
728  /*    load_truetype_glyph                                                */
729  /*                                                                       */
730  /* <Description>                                                         */
731  /*    Loads a given truetype glyph.  Handles composites and uses a       */
732  /*    TT_Loader object.                                                  */
733  /*                                                                       */
734  static FT_Error
735  load_truetype_glyph( TT_Loader*  loader,
736                       FT_UInt     glyph_index )
737  {
738
739#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
740    FT_Stream        stream = loader->stream;
741#endif
742
743    FT_Error         error;
744    TT_Face          face   = (TT_Face)loader->face;
745    FT_ULong         offset;
746    FT_Int           contours_count;
747    FT_UInt          index, num_points, count;
748    FT_Fixed         x_scale, y_scale;
749    FT_GlyphLoader*  gloader = loader->gloader;
750    FT_Bool          opened_frame = 0;
751
752
753    /* check glyph index */
754    index = glyph_index;
755    if ( index >= (FT_UInt)face->root.num_glyphs )
756    {
757      error = TT_Err_Invalid_Glyph_Index;
758      goto Exit;
759    }
760
761    loader->glyph_index = glyph_index;
762    num_points   = 0;
763
764    x_scale = 0x10000L;
765    y_scale = 0x10000L;
766    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
767    {
768      x_scale = loader->size->metrics.x_scale;
769      y_scale = loader->size->metrics.y_scale;
770    }
771
772    /* get horizontal metrics */
773    {
774      FT_Short   left_bearing;
775      FT_UShort  advance_width;
776
777
778      Get_HMetrics( face, index,
779                    (FT_Bool)!(loader->load_flags &
780                                FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
781                    &left_bearing,
782                    &advance_width );
783
784      loader->left_bearing = left_bearing;
785      loader->advance      = advance_width;
786
787      if ( !loader->linear_def )
788      {
789        loader->linear_def = 1;
790        loader->linear     = advance_width;
791      }
792    }
793
794    offset = face->glyph_locations[index];
795    count  = 0;
796
797    if ( index < (FT_UInt)face->num_locations - 1 )
798       count = face->glyph_locations[index + 1] - offset;
799
800    if ( count == 0 )
801    {
802      /* as described by Frederic Loyer, these are spaces, and */
803      /* not the unknown glyph.                                */
804      loader->bbox.xMin = 0;
805      loader->bbox.xMax = 0;
806      loader->bbox.yMin = 0;
807      loader->bbox.yMax = 0;
808
809      loader->pp1.x = 0;
810      loader->pp2.x = loader->advance;
811
812      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
813        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
814
815#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
816
817      if ( loader->exec )
818        loader->exec->glyphSize = 0;
819
820#endif
821
822      error = TT_Err_Ok;
823      goto Exit;
824    }
825
826    loader->byte_len = (FT_Int) count;
827
828#if 0
829    /* temporary hack */
830    if ( count < 10 )
831    {
832      /* This glyph is corrupted -- it does not have a complete header */
833      error = TT_Err_Invalid_Outline;
834      goto Fail;
835    }
836#endif
837
838    offset = loader->glyf_offset + offset;
839
840    /* access glyph frame */
841    error = face->access_glyph_frame( loader, glyph_index, offset, count );
842    if ( error )
843      goto Exit;
844
845    opened_frame = 1;
846
847    /* read first glyph header */
848    error = face->read_glyph_header( loader );
849    if ( error )
850      goto Fail;
851
852    contours_count = loader->n_contours;
853
854    count -= 10;
855
856    loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
857    loader->pp1.y = 0;
858    loader->pp2.x = loader->pp1.x + loader->advance;
859    loader->pp2.y = 0;
860
861    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
862    {
863      loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
864      loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
865    }
866
867    /***********************************************************************/
868    /***********************************************************************/
869    /***********************************************************************/
870
871    /* if it is a simple glyph, load it */
872
873    if ( contours_count >= 0 )
874    {
875      /* check that we can add the contours to the glyph */
876      error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count );
877      if ( error )
878        goto Fail;
879
880      error = face->read_simple_glyph( loader );
881      if ( error )
882        goto Fail;
883
884#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
885
886      {
887        TT_Size size = (TT_Size)loader->size;
888
889
890        error = TT_Process_Simple_Glyph( loader,
891                                         (FT_Bool)( size && size->debug ) );
892      }
893
894#else
895
896      error = TT_Process_Simple_Glyph( loader, 0 );
897
898#endif
899
900      if ( error )
901        goto Fail;
902
903      FT_GlyphLoader_Add( gloader );
904
905      /* Note: We could have put the simple loader source there */
906      /*       but the code is fat enough already :-)           */
907    }
908
909    /***********************************************************************/
910    /***********************************************************************/
911    /***********************************************************************/
912
913    /* otherwise, load a composite! */
914    else
915    {
916      TT_GlyphSlot  glyph = (TT_GlyphSlot)loader->glyph;
917      FT_UInt       start_point, start_contour;
918      FT_ULong      ins_pos;  /* position of composite instructions, if any */
919
920
921      /* for each subglyph, read composite header */
922      start_point   = gloader->base.outline.n_points;
923      start_contour = gloader->base.outline.n_contours;
924
925      error = face->read_composite_glyph( loader );
926      if ( error )
927        goto Fail;
928
929      ins_pos = loader->ins_pos;
930      face->forget_glyph_frame( loader );
931      opened_frame = 0;
932
933      /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
934      /* `as is' in the glyph slot (the client application will be     */
935      /* responsible for interpreting this data)...                    */
936      /*                                                               */
937      if ( loader->load_flags & FT_LOAD_NO_RECURSE )
938      {
939        /* set up remaining glyph fields */
940        FT_GlyphLoader_Add( gloader );
941
942        glyph->num_subglyphs  = gloader->base.num_subglyphs;
943        glyph->format         = ft_glyph_format_composite;
944        glyph->subglyphs      = gloader->base.subglyphs;
945
946        goto Exit;
947      }
948
949      /*********************************************************************/
950      /*********************************************************************/
951      /*********************************************************************/
952
953      /* Now, read each subglyph independently. */
954      {
955        FT_Int        n, num_base_points, num_new_points;
956        FT_SubGlyph*  subglyph = 0;
957
958        FT_UInt num_subglyphs  = gloader->current.num_subglyphs;
959        FT_UInt num_base_subgs = gloader->base.num_subglyphs;
960
961
962        FT_GlyphLoader_Add( gloader );
963
964        for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
965        {
966          FT_Vector  pp1, pp2;
967          FT_Pos     x, y;
968
969
970          /* Each time we call load_truetype_glyph in this loop, the   */
971          /* value of `gloader.base.subglyphs' can change due to table */
972          /* reallocations.  We thus need to recompute the subglyph    */
973          /* pointer on each iteration.                                */
974          subglyph = gloader->base.subglyphs + num_base_subgs + n;
975
976          pp1 = loader->pp1;
977          pp2 = loader->pp2;
978
979          num_base_points = gloader->base.outline.n_points;
980
981          error = load_truetype_glyph( loader, subglyph->index );
982          if ( error )
983            goto Fail;
984
985          /* restore subglyph pointer */
986          subglyph = gloader->base.subglyphs + num_base_subgs + n;
987
988          if ( subglyph->flags & USE_MY_METRICS )
989          {
990            pp1 = loader->pp1;
991            pp2 = loader->pp2;
992          }
993          else
994          {
995            loader->pp1 = pp1;
996            loader->pp2 = pp2;
997          }
998
999          num_points = gloader->base.outline.n_points;
1000
1001          num_new_points = num_points - num_base_points;
1002
1003          /* now perform the transform required for this subglyph */
1004
1005          if ( subglyph->flags & ( WE_HAVE_A_SCALE     |
1006                                   WE_HAVE_AN_XY_SCALE |
1007                                   WE_HAVE_A_2X2       ) )
1008          {
1009            FT_Vector*  cur   = gloader->base.outline.points +
1010                                  num_base_points;
1011            FT_Vector*  org   = gloader->base.extra_points +
1012                                  num_base_points;
1013            FT_Vector*  limit = cur + num_new_points;
1014
1015
1016            for ( ; cur < limit; cur++, org++ )
1017            {
1018              FT_Vector_Transform( cur, &subglyph->transform );
1019              FT_Vector_Transform( org, &subglyph->transform );
1020            }
1021          }
1022
1023          /* apply offset */
1024
1025          if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
1026          {
1027            FT_UInt     k = subglyph->arg1;
1028            FT_UInt     l = subglyph->arg2;
1029            FT_Vector*  p1;
1030            FT_Vector*  p2;
1031
1032
1033            if ( start_point + k >= (FT_UInt)num_base_points ||
1034                               l >= (FT_UInt)num_new_points  )
1035            {
1036              error = TT_Err_Invalid_Composite;
1037              goto Fail;
1038            }
1039
1040            l += num_base_points;
1041
1042            p1 = gloader->base.outline.points + start_point + k;
1043            p2 = gloader->base.outline.points + start_point + l;
1044
1045            x = p1->x - p2->x;
1046            y = p1->y - p2->y;
1047          }
1048          else
1049          {
1050            x = subglyph->arg1;
1051            y = subglyph->arg2;
1052
1053            if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1054            {
1055              x = FT_MulFix( x, x_scale );
1056              y = FT_MulFix( y, y_scale );
1057
1058              if ( subglyph->flags & ROUND_XY_TO_GRID )
1059              {
1060                x = ( x + 32 ) & -64;
1061                y = ( y + 32 ) & -64;
1062              }
1063            }
1064          }
1065
1066          if ( x | y )
1067          {
1068            translate_array( num_new_points,
1069                             gloader->base.outline.points + num_base_points,
1070                             x, y );
1071
1072            translate_array( num_new_points,
1073                             gloader->base.extra_points + num_base_points,
1074                             x, y );
1075          }
1076        }
1077
1078        /*******************************************************************/
1079        /*******************************************************************/
1080        /*******************************************************************/
1081
1082        /* we have finished loading all sub-glyphs; now, look for */
1083        /* instructions for this composite!                       */
1084
1085#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1086
1087        if ( num_subglyphs > 0               &&
1088             loader->exec                    &&
1089             ins_pos         > 0             &&
1090             subglyph->flags & WE_HAVE_INSTR )
1091        {
1092          FT_UShort       n_ins;
1093          TT_ExecContext  exec = loader->exec;
1094          TT_GlyphZone*   pts;
1095          FT_Vector*      pp1;
1096
1097
1098          /* read size of instructions */
1099          if ( FILE_Seek( ins_pos ) ||
1100               READ_UShort( n_ins ) )
1101            goto Fail;
1102          FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
1103
1104          /* in some fonts? */
1105          if ( n_ins == 0xFFFF )
1106            n_ins = 0;
1107
1108          /* check it */
1109          if ( n_ins > face->max_profile.maxSizeOfInstructions )
1110          {
1111            FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
1112                        n_ins, subglyph->index ));
1113            error = TT_Err_Too_Many_Hints;
1114            goto Fail;
1115          }
1116
1117          /* read the instructions */
1118          if ( FILE_Read( exec->glyphIns, n_ins ) )
1119            goto Fail;
1120
1121          glyph->control_data = exec->glyphIns;
1122          glyph->control_len  = n_ins;
1123
1124          error = TT_Set_CodeRange( exec,
1125                                    tt_coderange_glyph,
1126                                    exec->glyphIns,
1127                                    n_ins );
1128          if ( error )
1129            goto Fail;
1130
1131          /* prepare the execution context */
1132          tt_prepare_zone( &exec->pts, &gloader->base,
1133                           start_point, start_contour );
1134          pts = &exec->pts;
1135
1136          pts->n_points   = (short)(num_points + 2);
1137          pts->n_contours = gloader->base.outline.n_contours;
1138
1139          /* add phantom points */
1140          pp1    = pts->cur + num_points;
1141          pp1[0] = loader->pp1;
1142          pp1[1] = loader->pp2;
1143
1144          pts->tags[num_points    ] = 0;
1145          pts->tags[num_points + 1] = 0;
1146
1147          /* if hinting, round the phantom points */
1148          if ( IS_HINTED( loader->load_flags ) )
1149          {
1150            pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 );
1151            pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 );
1152          }
1153
1154          {
1155            FT_UInt  k;
1156
1157
1158            for ( k = 0; k < num_points; k++ )
1159              pts->tags[k] &= FT_Curve_Tag_On;
1160          }
1161
1162          cur_to_org( num_points + 2, pts );
1163
1164          /* now consider hinting */
1165          if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
1166          {
1167            exec->is_composite     = TRUE;
1168            exec->pedantic_hinting =
1169              (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC );
1170
1171            error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
1172            if ( error && exec->pedantic_hinting )
1173              goto Fail;
1174          }
1175
1176          /* save glyph origin and advance points */
1177          loader->pp1 = pp1[0];
1178          loader->pp2 = pp1[1];
1179        }
1180
1181#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1182
1183      }
1184      /* end of composite loading */
1185    }
1186
1187    /***********************************************************************/
1188    /***********************************************************************/
1189    /***********************************************************************/
1190
1191  Fail:
1192    if ( opened_frame )
1193      face->forget_glyph_frame( loader );
1194
1195  Exit:
1196    return error;
1197  }
1198
1199
1200  static void
1201  compute_glyph_metrics( TT_Loader*  loader,
1202                         FT_UInt     glyph_index )
1203  {
1204    FT_BBox       bbox;
1205    TT_Face       face = (TT_Face)loader->face;
1206    FT_Fixed      y_scale;
1207    TT_GlyphSlot  glyph = loader->glyph;
1208    TT_Size       size = (TT_Size)loader->size;
1209
1210
1211    y_scale = 0x10000L;
1212    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1213      y_scale = size->root.metrics.y_scale;
1214
1215    if ( glyph->format != ft_glyph_format_composite )
1216    {
1217      glyph->outline.flags &= ~ft_outline_single_pass;
1218
1219      /* copy outline to our glyph slot */
1220      FT_GlyphLoader_Copy_Points( glyph->internal->loader, loader->gloader );
1221      glyph->outline = glyph->internal->loader->base.outline;
1222
1223      /* translate array so that (0,0) is the glyph's origin */
1224      FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
1225
1226      FT_Outline_Get_CBox( &glyph->outline, &bbox );
1227
1228      if ( IS_HINTED( loader->load_flags ) )
1229      {
1230        /* grid-fit the bounding box */
1231        bbox.xMin &= -64;
1232        bbox.yMin &= -64;
1233        bbox.xMax  = ( bbox.xMax + 63 ) & -64;
1234        bbox.yMax  = ( bbox.yMax + 63 ) & -64;
1235      }
1236    }
1237    else
1238      bbox = loader->bbox;
1239
1240    /* get the device-independent horizontal advance.  It is scaled later */
1241    /* by the base layer.                                                 */
1242    {
1243      FT_Pos  advance = loader->linear;
1244
1245
1246      /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1247      /* correctly support DynaLab fonts, which have an incorrect       */
1248      /* `advance_Width_Max' field!  It is used, to my knowledge,       */
1249      /* exclusively in the X-TrueType font server.                     */
1250      /*                                                                */
1251      if ( face->postscript.isFixedPitch                                    &&
1252           ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
1253        advance = face->horizontal.advance_Width_Max;
1254
1255      /* we need to return the advance in font units in linearHoriAdvance, */
1256      /* it will be scaled later by the base layer.                        */
1257      glyph->linearHoriAdvance = advance;
1258    }
1259
1260    glyph->metrics.horiBearingX = bbox.xMin;
1261    glyph->metrics.horiBearingY = bbox.yMax;
1262    glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
1263
1264    /* don't forget to hint the advance when we need to */
1265    if ( IS_HINTED( loader->load_flags ) )
1266      glyph->metrics.horiAdvance = ( glyph->metrics.horiAdvance + 32 ) & -64;
1267
1268    /* Now take care of vertical metrics.  In the case where there is    */
1269    /* no vertical information within the font (relatively common), make */
1270    /* up some metrics by `hand'...                                      */
1271
1272    {
1273      FT_Short   top_bearing;    /* vertical top side bearing (EM units) */
1274      FT_UShort  advance_height; /* vertical advance height   (EM units) */
1275
1276      FT_Pos  left;     /* scaled vertical left side bearing         */
1277      FT_Pos  top;      /* scaled vertical top side bearing          */
1278      FT_Pos  advance;  /* scaled vertical advance height            */
1279
1280
1281      /* Get the unscaled `tsb' and `ah' */
1282      if ( face->vertical_info                   &&
1283           face->vertical.number_Of_VMetrics > 0 )
1284      {
1285        /* Don't assume that both the vertical header and vertical */
1286        /* metrics are present in the same font :-)                */
1287
1288        TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
1289                        glyph_index,
1290                        &top_bearing,
1291                        &advance_height );
1292      }
1293      else
1294      {
1295        /* Make up the distances from the horizontal header.   */
1296
1297        /* NOTE: The OS/2 values are the only `portable' ones, */
1298        /*       which is why we use them, if there is an OS/2 */
1299        /*       table in the font.  Otherwise, we use the     */
1300        /*       values defined in the horizontal header.      */
1301        /*                                                     */
1302        /* NOTE2: The sTypoDescender is negative, which is why */
1303        /*        we compute the baseline-to-baseline distance */
1304        /*        here with:                                   */
1305        /*             ascender - descender + linegap          */
1306        /*                                                     */
1307        if ( face->os2.version != 0xFFFF )
1308        {
1309          top_bearing    = (FT_Short)( face->os2.sTypoLineGap / 2 );
1310          advance_height = (FT_UShort)( face->os2.sTypoAscender -
1311                                        face->os2.sTypoDescender +
1312                                        face->os2.sTypoLineGap );
1313        }
1314        else
1315        {
1316          top_bearing    = (FT_Short)( face->horizontal.Line_Gap / 2 );
1317          advance_height = (FT_UShort)( face->horizontal.Ascender  +
1318                                        face->horizontal.Descender +
1319                                        face->horizontal.Line_Gap );
1320        }
1321      }
1322
1323      /* We must adjust the top_bearing value from the bounding box given */
1324      /* in the glyph header to te bounding box calculated with           */
1325      /* FT_Get_Outline_CBox().                                           */
1326
1327      /* scale the metrics */
1328      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1329      {
1330        top     = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
1331                    - bbox.yMax;
1332        advance = FT_MulFix( advance_height, y_scale );
1333      }
1334      else
1335      {
1336        top     = top_bearing + loader->bbox.yMax - bbox.yMax;
1337        advance = advance_height;
1338      }
1339
1340      /* set the advance height in design units.  It is scaled later by */
1341      /* the base layer.                                                */
1342      glyph->linearVertAdvance = advance_height;
1343
1344      /* XXX: for now, we have no better algorithm for the lsb, but it */
1345      /*      should work fine.                                        */
1346      /*                                                               */
1347      left = ( bbox.xMin - bbox.xMax ) / 2;
1348
1349      /* grid-fit them if necessary */
1350      if ( IS_HINTED( loader->load_flags ) )
1351      {
1352        left   &= -64;
1353        top     = ( top + 63     ) & -64;
1354        advance = ( advance + 32 ) & -64;
1355      }
1356
1357      glyph->metrics.vertBearingX = left;
1358      glyph->metrics.vertBearingY = top;
1359      glyph->metrics.vertAdvance  = advance;
1360    }
1361
1362    /* adjust advance width to the value contained in the hdmx table */
1363    if ( !face->postscript.isFixedPitch && size &&
1364         IS_HINTED( loader->load_flags )        )
1365    {
1366      FT_Byte* widths = Get_Advance_Widths( face,
1367                                            size->root.metrics.x_ppem );
1368
1369
1370      if ( widths )
1371        glyph->metrics.horiAdvance = widths[glyph_index] << 6;
1372    }
1373
1374    /* set glyph dimensions */
1375    glyph->metrics.width  = bbox.xMax - bbox.xMin;
1376    glyph->metrics.height = bbox.yMax - bbox.yMin;
1377  }
1378
1379
1380  /*************************************************************************/
1381  /*                                                                       */
1382  /* <Function>                                                            */
1383  /*    TT_Load_Glyph                                                      */
1384  /*                                                                       */
1385  /* <Description>                                                         */
1386  /*    A function used to load a single glyph within a given glyph slot,  */
1387  /*    for a given size.                                                  */
1388  /*                                                                       */
1389  /* <Input>                                                               */
1390  /*    glyph       :: A handle to a target slot object where the glyph    */
1391  /*                   will be loaded.                                     */
1392  /*                                                                       */
1393  /*    size        :: A handle to the source face size at which the glyph */
1394  /*                   must be scaled/loaded.                              */
1395  /*                                                                       */
1396  /*    glyph_index :: The index of the glyph in the font file.            */
1397  /*                                                                       */
1398  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
1399  /*                   FT_LOAD_XXX constants can be used to control the    */
1400  /*                   glyph loading process (e.g., whether the outline    */
1401  /*                   should be scaled, whether to load bitmaps or not,   */
1402  /*                   whether to hint the outline, etc).                  */
1403  /*                                                                       */
1404  /* <Return>                                                              */
1405  /*    FreeType error code.  0 means success.                             */
1406  /*                                                                       */
1407  FT_LOCAL_DEF FT_Error
1408  TT_Load_Glyph( TT_Size       size,
1409                 TT_GlyphSlot  glyph,
1410                 FT_UShort     glyph_index,
1411                 FT_UInt       load_flags )
1412  {
1413    SFNT_Interface*  sfnt;
1414    TT_Face          face;
1415    FT_Stream        stream;
1416    FT_Error         error;
1417    TT_Loader        loader;
1418
1419
1420    face   = (TT_Face)glyph->face;
1421    sfnt   = (SFNT_Interface*)face->sfnt;
1422    stream = face->root.stream;
1423    error  = 0;
1424
1425    if ( !size || ( load_flags & FT_LOAD_NO_SCALE )   ||
1426                  ( load_flags & FT_LOAD_NO_RECURSE ) )
1427    {
1428      size        = NULL;
1429      load_flags |= FT_LOAD_NO_SCALE   |
1430                    FT_LOAD_NO_HINTING |
1431                    FT_LOAD_NO_BITMAP;
1432    }
1433
1434    glyph->num_subglyphs = 0;
1435
1436#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1437
1438    /* try to load embedded bitmap if any              */
1439    /*                                                 */
1440    /* XXX: The convention should be emphasized in     */
1441    /*      the documents because it can be confusing. */
1442    if ( size                                    &&
1443         size->strike_index != 0xFFFF            &&
1444         sfnt->load_sbits                        &&
1445         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
1446
1447    {
1448      TT_SBit_Metrics  metrics;
1449
1450
1451      error = sfnt->load_sbit_image( face,
1452                                     size->strike_index,
1453                                     glyph_index,
1454                                     load_flags,
1455                                     stream,
1456                                     &glyph->bitmap,
1457                                     &metrics );
1458      if ( !error )
1459      {
1460        glyph->outline.n_points   = 0;
1461        glyph->outline.n_contours = 0;
1462
1463        glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
1464        glyph->metrics.height = (FT_Pos)metrics.height << 6;
1465
1466        glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1467        glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1468        glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
1469
1470        glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1471        glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1472        glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
1473
1474        glyph->format = ft_glyph_format_bitmap;
1475        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1476        {
1477          glyph->bitmap_left = metrics.vertBearingX;
1478          glyph->bitmap_top  = metrics.vertBearingY;
1479        }
1480        else
1481        {
1482          glyph->bitmap_left = metrics.horiBearingX;
1483          glyph->bitmap_top  = metrics.horiBearingY;
1484        }
1485        return error;
1486      }
1487    }
1488
1489#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1490
1491    /* return immediately if we only want the embedded bitmaps */
1492    if ( load_flags & FT_LOAD_SBITS_ONLY )
1493      return FT_Err_Invalid_Argument;
1494
1495    /* seek to the beginning of the glyph table.  For Type 42 fonts      */
1496    /* the table might be accessed from a Postscript stream or something */
1497    /* else...                                                           */
1498
1499    error = face->goto_table( face, TTAG_glyf, stream, 0 );
1500    if ( error )
1501    {
1502      FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
1503      goto Exit;
1504    }
1505
1506    MEM_Set( &loader, 0, sizeof ( loader ) );
1507
1508    /* update the glyph zone bounds */
1509    {
1510      FT_GlyphLoader*  gloader = FT_FACE_DRIVER(face)->glyph_loader;
1511
1512
1513      loader.gloader = gloader;
1514
1515      FT_GlyphLoader_Rewind( gloader );
1516
1517      tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
1518      tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
1519    }
1520
1521#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1522
1523    if ( size )
1524    {
1525      /* query new execution context */
1526      loader.exec = size->debug ? size->context : TT_New_Context( face );
1527      if ( !loader.exec )
1528        return TT_Err_Could_Not_Find_Context;
1529
1530      TT_Load_Context( loader.exec, face, size );
1531      loader.instructions = loader.exec->glyphIns;
1532
1533      /* load default graphics state - if needed */
1534      if ( size->GS.instruct_control & 2 )
1535        loader.exec->GS = tt_default_graphics_state;
1536    }
1537
1538#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1539
1540    /* clear all outline flags, except the `owner' one */
1541    glyph->outline.flags = 0;
1542
1543    if ( size && size->root.metrics.y_ppem < 24 )
1544      glyph->outline.flags |= ft_outline_high_precision;
1545
1546    /* let's initialize the rest of our loader now */
1547
1548    loader.load_flags    = load_flags;
1549
1550    loader.face   = (FT_Face)face;
1551    loader.size   = (FT_Size)size;
1552    loader.glyph  = (FT_GlyphSlot)glyph;
1553    loader.stream = stream;
1554
1555    loader.glyf_offset  = FILE_Pos();
1556
1557#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1558
1559    /* if the cvt program has disabled hinting, the argument */
1560    /* is ignored.                                           */
1561    if ( size && ( size->GS.instruct_control & 1 ) )
1562      loader.load_flags |= FT_LOAD_NO_HINTING;
1563
1564#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1565
1566    /* Main loading loop */
1567    glyph->format        = ft_glyph_format_outline;
1568    glyph->num_subglyphs = 0;
1569    error = load_truetype_glyph( &loader, glyph_index );
1570    if ( !error )
1571      compute_glyph_metrics( &loader, glyph_index );
1572
1573#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1574
1575    if ( !size || !size->debug )
1576      TT_Done_Context( loader.exec );
1577
1578#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1579
1580  Exit:
1581    return error;
1582  }
1583
1584
1585/* END */
1586