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