Imported Upstream version 2.13.2
[platform/upstream/freetype2.git] / src / truetype / ttgload.c
1 /****************************************************************************
2  *
3  * ttgload.c
4  *
5  *   TrueType Glyph Loader (body).
6  *
7  * Copyright (C) 1996-2023 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 <freetype/internal/ftdebug.h>
21 #include FT_CONFIG_CONFIG_H
22 #include <freetype/internal/ftcalc.h>
23 #include <freetype/internal/ftstream.h>
24 #include <freetype/internal/sfnt.h>
25 #include <freetype/tttags.h>
26 #include <freetype/ftoutln.h>
27 #include <freetype/ftdriver.h>
28 #include <freetype/ftlist.h>
29
30 #include "ttgload.h"
31 #include "ttpload.h"
32
33 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
34 #include "ttgxvar.h"
35 #endif
36
37 #include "tterrors.h"
38
39
40   /**************************************************************************
41    *
42    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
43    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
44    * messages during execution.
45    */
46 #undef  FT_COMPONENT
47 #define FT_COMPONENT  ttgload
48
49
50   /**************************************************************************
51    *
52    * Simple glyph flags.
53    */
54 #define ON_CURVE_POINT  0x01  /* same value as FT_CURVE_TAG_ON            */
55 #define X_SHORT_VECTOR  0x02
56 #define Y_SHORT_VECTOR  0x04
57 #define REPEAT_FLAG     0x08
58 #define X_POSITIVE      0x10  /* two meanings depending on X_SHORT_VECTOR */
59 #define SAME_X          0x10
60 #define Y_POSITIVE      0x20  /* two meanings depending on Y_SHORT_VECTOR */
61 #define SAME_Y          0x20
62 #define OVERLAP_SIMPLE  0x40  /* retained as FT_OUTLINE_OVERLAP           */
63
64
65   /**************************************************************************
66    *
67    * Composite glyph flags.
68    */
69 #define ARGS_ARE_WORDS             0x0001
70 #define ARGS_ARE_XY_VALUES         0x0002
71 #define ROUND_XY_TO_GRID           0x0004
72 #define WE_HAVE_A_SCALE            0x0008
73 /* reserved                        0x0010 */
74 #define MORE_COMPONENTS            0x0020
75 #define WE_HAVE_AN_XY_SCALE        0x0040
76 #define WE_HAVE_A_2X2              0x0080
77 #define WE_HAVE_INSTR              0x0100
78 #define USE_MY_METRICS             0x0200
79 #define OVERLAP_COMPOUND           0x0400  /* retained as FT_OUTLINE_OVERLAP */
80 #define SCALED_COMPONENT_OFFSET    0x0800
81 #define UNSCALED_COMPONENT_OFFSET  0x1000
82
83
84 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
85 #define IS_DEFAULT_INSTANCE( _face )             \
86           ( !( FT_IS_NAMED_INSTANCE( _face ) ||  \
87                FT_IS_VARIATION( _face )      ) )
88 #else
89 #define IS_DEFAULT_INSTANCE( _face )  1
90 #endif
91
92
93   /**************************************************************************
94    *
95    * Return the horizontal metrics in font units for a given glyph.
96    */
97   FT_LOCAL_DEF( void )
98   TT_Get_HMetrics( TT_Face     face,
99                    FT_UInt     idx,
100                    FT_Short*   lsb,
101                    FT_UShort*  aw )
102   {
103     ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
104
105     FT_TRACE5(( "  advance width (font units): %d\n", *aw ));
106     FT_TRACE5(( "  left side bearing (font units): %d\n", *lsb ));
107   }
108
109
110   /**************************************************************************
111    *
112    * Return the vertical metrics in font units for a given glyph.
113    * See function `tt_loader_set_pp' below for explanations.
114    */
115   FT_LOCAL_DEF( void )
116   TT_Get_VMetrics( TT_Face     face,
117                    FT_UInt     idx,
118                    FT_Pos      yMax,
119                    FT_Short*   tsb,
120                    FT_UShort*  ah )
121   {
122     if ( face->vertical_info )
123       ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
124
125     else if ( face->os2.version != 0xFFFFU )
126     {
127       *tsb = (FT_Short)( face->os2.sTypoAscender - yMax );
128       *ah  = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
129                                 face->os2.sTypoDescender );
130     }
131
132     else
133     {
134       *tsb = (FT_Short)( face->horizontal.Ascender - yMax );
135       *ah  = (FT_UShort)FT_ABS( face->horizontal.Ascender -
136                                 face->horizontal.Descender );
137     }
138
139 #ifdef FT_DEBUG_LEVEL_TRACE
140     if ( !face->vertical_info )
141       FT_TRACE5(( "  [vertical metrics missing, computing values]\n" ));
142 #endif
143
144     FT_TRACE5(( "  advance height (font units): %d\n", *ah ));
145     FT_TRACE5(( "  top side bearing (font units): %d\n", *tsb ));
146   }
147
148
149   static FT_Error
150   tt_get_metrics( TT_Loader  loader,
151                   FT_UInt    glyph_index )
152   {
153     TT_Face    face   = loader->face;
154
155     FT_Error   error;
156     FT_Stream  stream = loader->stream;
157
158     FT_Short   left_bearing = 0, top_bearing = 0;
159     FT_UShort  advance_width = 0, advance_height = 0;
160
161     /* we must preserve the stream position          */
162     /* (which gets altered by the metrics functions) */
163     FT_ULong  pos = FT_STREAM_POS();
164
165
166     TT_Get_HMetrics( face, glyph_index,
167                      &left_bearing,
168                      &advance_width );
169     TT_Get_VMetrics( face, glyph_index,
170                      loader->bbox.yMax,
171                      &top_bearing,
172                      &advance_height );
173
174     if ( FT_STREAM_SEEK( pos ) )
175       return error;
176
177     loader->left_bearing = left_bearing;
178     loader->advance      = advance_width;
179     loader->top_bearing  = top_bearing;
180     loader->vadvance     = advance_height;
181
182 #ifdef FT_CONFIG_OPTION_INCREMENTAL
183     /* With the incremental interface, these values are set by  */
184     /* a call to `tt_get_metrics_incremental'.                  */
185     if ( face->root.internal->incremental_interface == NULL )
186 #endif
187     {
188       if ( !loader->linear_def )
189       {
190         loader->linear_def = 1;
191         loader->linear     = advance_width;
192       }
193     }
194
195     return FT_Err_Ok;
196   }
197
198
199 #ifdef FT_CONFIG_OPTION_INCREMENTAL
200
201   static void
202   tt_get_metrics_incremental( TT_Loader  loader,
203                               FT_UInt    glyph_index )
204   {
205     TT_Face  face = loader->face;
206
207     FT_Short   left_bearing = 0, top_bearing = 0;
208     FT_UShort  advance_width = 0, advance_height = 0;
209
210
211     /* If this is an incrementally loaded font check whether there are */
212     /* overriding metrics for this glyph.                              */
213     if ( face->root.internal->incremental_interface                           &&
214          face->root.internal->incremental_interface->funcs->get_glyph_metrics )
215     {
216       FT_Incremental_MetricsRec  incr_metrics;
217       FT_Error                   error;
218
219
220       incr_metrics.bearing_x = loader->left_bearing;
221       incr_metrics.bearing_y = 0;
222       incr_metrics.advance   = loader->advance;
223       incr_metrics.advance_v = 0;
224
225       error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
226                 face->root.internal->incremental_interface->object,
227                 glyph_index, FALSE, &incr_metrics );
228       if ( error )
229         goto Exit;
230
231       left_bearing  = (FT_Short)incr_metrics.bearing_x;
232       advance_width = (FT_UShort)incr_metrics.advance;
233
234 #if 0
235
236       /* GWW: Do I do the same for vertical metrics? */
237       incr_metrics.bearing_x = 0;
238       incr_metrics.bearing_y = loader->top_bearing;
239       incr_metrics.advance   = loader->vadvance;
240
241       error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
242                 face->root.internal->incremental_interface->object,
243                 glyph_index, TRUE, &incr_metrics );
244       if ( error )
245         goto Exit;
246
247       top_bearing    = (FT_Short)incr_metrics.bearing_y;
248       advance_height = (FT_UShort)incr_metrics.advance;
249
250 #endif /* 0 */
251
252       loader->left_bearing = left_bearing;
253       loader->advance      = advance_width;
254       loader->top_bearing  = top_bearing;
255       loader->vadvance     = advance_height;
256
257       if ( !loader->linear_def )
258       {
259         loader->linear_def = 1;
260         loader->linear     = advance_width;
261       }
262     }
263
264   Exit:
265     return;
266   }
267
268 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
269
270
271   /**************************************************************************
272    *
273    * The following functions are used by default with TrueType fonts.
274    * However, they can be replaced by alternatives if we need to support
275    * TrueType-compressed formats (like MicroType) in the future.
276    *
277    */
278
279   FT_CALLBACK_DEF( FT_Error )
280   TT_Access_Glyph_Frame( TT_Loader  loader,
281                          FT_UInt    glyph_index,
282                          FT_ULong   offset,
283                          FT_UInt    byte_count )
284   {
285     FT_Error   error;
286     FT_Stream  stream = loader->stream;
287
288     FT_UNUSED( glyph_index );
289
290
291     /* the following line sets the `error' variable through macros! */
292     if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
293       return error;
294
295     loader->cursor = stream->cursor;
296     loader->limit  = stream->limit;
297
298     return FT_Err_Ok;
299   }
300
301
302   FT_CALLBACK_DEF( void )
303   TT_Forget_Glyph_Frame( TT_Loader  loader )
304   {
305     FT_Stream  stream = loader->stream;
306
307
308     FT_FRAME_EXIT();
309   }
310
311
312   FT_CALLBACK_DEF( FT_Error )
313   TT_Load_Glyph_Header( TT_Loader  loader )
314   {
315     FT_Byte*  p     = loader->cursor;
316     FT_Byte*  limit = loader->limit;
317
318
319     if ( p + 10 > limit )
320       return FT_THROW( Invalid_Outline );
321
322     loader->n_contours = FT_NEXT_SHORT( p );
323
324     loader->bbox.xMin = FT_NEXT_SHORT( p );
325     loader->bbox.yMin = FT_NEXT_SHORT( p );
326     loader->bbox.xMax = FT_NEXT_SHORT( p );
327     loader->bbox.yMax = FT_NEXT_SHORT( p );
328
329     FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
330     FT_TRACE5(( "  xMin: %4ld  xMax: %4ld\n", loader->bbox.xMin,
331                                             loader->bbox.xMax ));
332     FT_TRACE5(( "  yMin: %4ld  yMax: %4ld\n", loader->bbox.yMin,
333                                             loader->bbox.yMax ));
334     loader->cursor = p;
335
336     return FT_Err_Ok;
337   }
338
339
340   FT_CALLBACK_DEF( FT_Error )
341   TT_Load_Simple_Glyph( TT_Loader  load )
342   {
343     FT_Error        error;
344     FT_Byte*        p          = load->cursor;
345     FT_Byte*        limit      = load->limit;
346     FT_GlyphLoader  gloader    = load->gloader;
347     FT_Outline*     outline    = &gloader->current.outline;
348     FT_Int          n_contours = load->n_contours;
349     FT_Int          n_points;
350     FT_UShort       n_ins;
351
352     FT_Byte         *flag, *flag_limit;
353     FT_Byte         c, count;
354     FT_Vector       *vec, *vec_limit;
355     FT_Pos          x, y;
356     FT_Short        *cont, *cont_limit, last;
357
358
359     /* check that we can add the contours to the glyph */
360     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
361     if ( error )
362       goto Fail;
363
364     /* check space for contours array + instructions count */
365     if ( n_contours >= 0xFFF || p + 2 * n_contours + 2 > limit )
366       goto Invalid_Outline;
367
368     /* reading the contours' endpoints & number of points */
369     cont       = outline->contours;
370     cont_limit = cont + n_contours;
371
372     last = -1;
373     for ( ; cont < cont_limit; cont++ )
374     {
375       *cont = FT_NEXT_SHORT( p );
376
377       if ( *cont <= last )
378         goto Invalid_Outline;
379
380       last = *cont;
381     }
382
383     n_points = last + 1;
384
385     FT_TRACE5(( "  # of points: %d\n", n_points ));
386
387     /* note that we will add four phantom points later */
388     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
389     if ( error )
390       goto Fail;
391
392     /* space checked above */
393     n_ins = FT_NEXT_USHORT( p );
394
395     FT_TRACE5(( "  Instructions size: %u\n", n_ins ));
396
397     /* check instructions size */
398     if ( p + n_ins > limit )
399     {
400       FT_TRACE1(( "TT_Load_Simple_Glyph: excessive instruction count\n" ));
401       error = FT_THROW( Too_Many_Hints );
402       goto Fail;
403     }
404
405 #ifdef TT_USE_BYTECODE_INTERPRETER
406
407     if ( IS_HINTED( load->load_flags ) )
408     {
409       TT_ExecContext  exec = load->exec;
410       FT_Memory       memory = exec->memory;
411
412
413       if ( exec->glyphSize )
414         FT_FREE( exec->glyphIns );
415       exec->glyphSize = 0;
416
417       /* we don't trust `maxSizeOfInstructions' in the `maxp' table */
418       /* and thus allocate the bytecode array size by ourselves     */
419       if ( n_ins )
420       {
421         if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) )
422           return error;
423
424         FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins );
425
426         exec->glyphSize  = n_ins;
427       }
428     }
429
430 #endif /* TT_USE_BYTECODE_INTERPRETER */
431
432     p += n_ins;
433
434     /* reading the point tags */
435     flag       = (FT_Byte*)outline->tags;
436     flag_limit = flag + n_points;
437
438     FT_ASSERT( flag );
439
440     while ( flag < flag_limit )
441     {
442       if ( p + 1 > limit )
443         goto Invalid_Outline;
444
445       *flag++ = c = FT_NEXT_BYTE( p );
446       if ( c & REPEAT_FLAG )
447       {
448         if ( p + 1 > limit )
449           goto Invalid_Outline;
450
451         count = FT_NEXT_BYTE( p );
452         if ( flag + (FT_Int)count > flag_limit )
453           goto Invalid_Outline;
454
455         for ( ; count > 0; count-- )
456           *flag++ = c;
457       }
458     }
459
460     /* retain the overlap flag */
461     if ( n_points && outline->tags[0] & OVERLAP_SIMPLE )
462       gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
463
464     /* reading the X coordinates */
465
466     vec       = outline->points;
467     vec_limit = vec + n_points;
468     flag      = (FT_Byte*)outline->tags;
469     x         = 0;
470
471     for ( ; vec < vec_limit; vec++, flag++ )
472     {
473       FT_Pos   delta = 0;
474       FT_Byte  f     = *flag;
475
476
477       if ( f & X_SHORT_VECTOR )
478       {
479         if ( p + 1 > limit )
480           goto Invalid_Outline;
481
482         delta = (FT_Pos)FT_NEXT_BYTE( p );
483         if ( !( f & X_POSITIVE ) )
484           delta = -delta;
485       }
486       else if ( !( f & SAME_X ) )
487       {
488         if ( p + 2 > limit )
489           goto Invalid_Outline;
490
491         delta = (FT_Pos)FT_NEXT_SHORT( p );
492       }
493
494       x     += delta;
495       vec->x = x;
496     }
497
498     /* reading the Y coordinates */
499
500     vec       = outline->points;
501     vec_limit = vec + n_points;
502     flag      = (FT_Byte*)outline->tags;
503     y         = 0;
504
505     for ( ; vec < vec_limit; vec++, flag++ )
506     {
507       FT_Pos   delta = 0;
508       FT_Byte  f     = *flag;
509
510
511       if ( f & Y_SHORT_VECTOR )
512       {
513         if ( p + 1 > limit )
514           goto Invalid_Outline;
515
516         delta = (FT_Pos)FT_NEXT_BYTE( p );
517         if ( !( f & Y_POSITIVE ) )
518           delta = -delta;
519       }
520       else if ( !( f & SAME_Y ) )
521       {
522         if ( p + 2 > limit )
523           goto Invalid_Outline;
524
525         delta = (FT_Pos)FT_NEXT_SHORT( p );
526       }
527
528       y     += delta;
529       vec->y = y;
530
531       /* the cast is for stupid compilers */
532       *flag  = (FT_Byte)( f & ON_CURVE_POINT );
533     }
534
535     outline->n_points   = (FT_Short)n_points;
536     outline->n_contours = (FT_Short)n_contours;
537
538     load->cursor = p;
539
540   Fail:
541     return error;
542
543   Invalid_Outline:
544     error = FT_THROW( Invalid_Outline );
545     goto Fail;
546   }
547
548
549   FT_CALLBACK_DEF( FT_Error )
550   TT_Load_Composite_Glyph( TT_Loader  loader )
551   {
552     FT_Error        error;
553     FT_Byte*        p          = loader->cursor;
554     FT_Byte*        limit      = loader->limit;
555     FT_GlyphLoader  gloader    = loader->gloader;
556     FT_Long         num_glyphs = loader->face->root.num_glyphs;
557     FT_SubGlyph     subglyph;
558     FT_UInt         num_subglyphs;
559
560
561     num_subglyphs = 0;
562
563     do
564     {
565       FT_Fixed  xx, xy, yy, yx;
566       FT_UInt   count;
567
568
569       /* check that we can load a new subglyph */
570       error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
571       if ( error )
572         goto Fail;
573
574       /* check space */
575       if ( p + 4 > limit )
576         goto Invalid_Composite;
577
578       subglyph = gloader->current.subglyphs + num_subglyphs;
579
580       subglyph->arg1 = subglyph->arg2 = 0;
581
582       subglyph->flags = FT_NEXT_USHORT( p );
583       subglyph->index = FT_NEXT_USHORT( p );
584
585       /* we reject composites that have components */
586       /* with invalid glyph indices                */
587       if ( subglyph->index >= num_glyphs )
588         goto Invalid_Composite;
589
590       /* check space */
591       count = 2;
592       if ( subglyph->flags & ARGS_ARE_WORDS )
593         count += 2;
594       if ( subglyph->flags & WE_HAVE_A_SCALE )
595         count += 2;
596       else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
597         count += 4;
598       else if ( subglyph->flags & WE_HAVE_A_2X2 )
599         count += 8;
600
601       if ( p + count > limit )
602         goto Invalid_Composite;
603
604       /* read arguments */
605       if ( subglyph->flags & ARGS_ARE_XY_VALUES )
606       {
607         if ( subglyph->flags & ARGS_ARE_WORDS )
608         {
609           subglyph->arg1 = FT_NEXT_SHORT( p );
610           subglyph->arg2 = FT_NEXT_SHORT( p );
611         }
612         else
613         {
614           subglyph->arg1 = FT_NEXT_CHAR( p );
615           subglyph->arg2 = FT_NEXT_CHAR( p );
616         }
617       }
618       else
619       {
620         if ( subglyph->flags & ARGS_ARE_WORDS )
621         {
622           subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p );
623           subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p );
624         }
625         else
626         {
627           subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p );
628           subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p );
629         }
630       }
631
632       /* read transform */
633       xx = yy = 0x10000L;
634       xy = yx = 0;
635
636       if ( subglyph->flags & WE_HAVE_A_SCALE )
637       {
638         xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
639         yy = xx;
640       }
641       else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
642       {
643         xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
644         yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
645       }
646       else if ( subglyph->flags & WE_HAVE_A_2X2 )
647       {
648         xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
649         yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
650         xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
651         yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
652       }
653
654       subglyph->transform.xx = xx;
655       subglyph->transform.xy = xy;
656       subglyph->transform.yx = yx;
657       subglyph->transform.yy = yy;
658
659       num_subglyphs++;
660
661     } while ( subglyph->flags & MORE_COMPONENTS );
662
663     gloader->current.num_subglyphs = num_subglyphs;
664     FT_TRACE5(( "  %d component%s\n",
665                 num_subglyphs,
666                 num_subglyphs > 1 ? "s" : "" ));
667
668 #ifdef FT_DEBUG_LEVEL_TRACE
669     {
670       FT_UInt  i;
671
672
673       subglyph = gloader->current.subglyphs;
674
675       for ( i = 0; i < num_subglyphs; i++ )
676       {
677         if ( num_subglyphs > 1 )
678           FT_TRACE7(( "    subglyph %d:\n", i ));
679
680         FT_TRACE7(( "      glyph index: %d\n", subglyph->index ));
681
682         if ( subglyph->flags & ARGS_ARE_XY_VALUES )
683           FT_TRACE7(( "      offset: x=%d, y=%d\n",
684                       subglyph->arg1,
685                       subglyph->arg2 ));
686         else
687           FT_TRACE7(( "      matching points: base=%d, component=%d\n",
688                       subglyph->arg1,
689                       subglyph->arg2 ));
690
691         if ( subglyph->flags & WE_HAVE_A_SCALE )
692           FT_TRACE7(( "      scaling: %f\n",
693                       (double)subglyph->transform.xx / 65536 ));
694         else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
695           FT_TRACE7(( "      scaling: x=%f, y=%f\n",
696                       (double)subglyph->transform.xx / 65536,
697                       (double)subglyph->transform.yy / 65536 ));
698         else if ( subglyph->flags & WE_HAVE_A_2X2 )
699         {
700           FT_TRACE7(( "      scaling: xx=%f, yx=%f\n",
701                       (double)subglyph->transform.xx / 65536,
702                       (double)subglyph->transform.yx / 65536 ));
703           FT_TRACE7(( "               xy=%f, yy=%f\n",
704                       (double)subglyph->transform.xy / 65536,
705                       (double)subglyph->transform.yy / 65536 ));
706         }
707
708         subglyph++;
709       }
710     }
711 #endif /* FT_DEBUG_LEVEL_TRACE */
712
713 #ifdef TT_USE_BYTECODE_INTERPRETER
714
715     {
716       FT_Stream  stream = loader->stream;
717
718
719       /* we must undo the FT_FRAME_ENTER in order to point */
720       /* to the composite instructions, if we find some.   */
721       /* We will process them later.                       */
722       /*                                                   */
723       loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
724                                     p - limit );
725     }
726
727 #endif
728
729     loader->cursor = p;
730
731   Fail:
732     return error;
733
734   Invalid_Composite:
735     error = FT_THROW( Invalid_Composite );
736     goto Fail;
737   }
738
739
740   FT_LOCAL_DEF( void )
741   TT_Init_Glyph_Loading( TT_Face  face )
742   {
743     face->access_glyph_frame   = TT_Access_Glyph_Frame;
744     face->read_glyph_header    = TT_Load_Glyph_Header;
745     face->read_simple_glyph    = TT_Load_Simple_Glyph;
746     face->read_composite_glyph = TT_Load_Composite_Glyph;
747     face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
748   }
749
750
751   static void
752   tt_prepare_zone( TT_GlyphZone  zone,
753                    FT_GlyphLoad  load,
754                    FT_UInt       start_point,
755                    FT_UInt       start_contour )
756   {
757     zone->n_points    = (FT_UShort)load->outline.n_points + 4 -
758                           (FT_UShort)start_point;
759     zone->n_contours  = load->outline.n_contours -
760                           (FT_Short)start_contour;
761     zone->org         = load->extra_points + start_point;
762     zone->cur         = load->outline.points + start_point;
763     zone->orus        = load->extra_points2 + start_point;
764     zone->tags        = (FT_Byte*)load->outline.tags + start_point;
765     zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
766     zone->first_point = (FT_UShort)start_point;
767   }
768
769
770   /**************************************************************************
771    *
772    * @Function:
773    *   TT_Hint_Glyph
774    *
775    * @Description:
776    *   Hint the glyph using the zone prepared by the caller.  Note that
777    *   the zone is supposed to include four phantom points.
778    */
779   static FT_Error
780   TT_Hint_Glyph( TT_Loader  loader,
781                  FT_Bool    is_composite )
782   {
783 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
784     TT_Face    face   = loader->face;
785     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
786 #endif
787
788     TT_GlyphZone  zone = &loader->zone;
789
790 #ifdef TT_USE_BYTECODE_INTERPRETER
791     TT_ExecContext  exec  = loader->exec;
792     FT_Long         n_ins = exec->glyphSize;
793 #else
794     FT_UNUSED( is_composite );
795 #endif
796
797
798 #ifdef TT_USE_BYTECODE_INTERPRETER
799     /* save original point positions in `org' array */
800     if ( n_ins > 0 )
801       FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
802
803     /* Reset graphics state. */
804     exec->GS = loader->size->GS;
805
806     /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
807     /*      completely refer to the (already) hinted subglyphs.     */
808     if ( is_composite )
809     {
810       exec->metrics.x_scale = 1 << 16;
811       exec->metrics.y_scale = 1 << 16;
812
813       FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
814     }
815     else
816     {
817       exec->metrics.x_scale = loader->size->metrics->x_scale;
818       exec->metrics.y_scale = loader->size->metrics->y_scale;
819     }
820 #endif
821
822     /* round phantom points */
823     zone->cur[zone->n_points - 4].x =
824       FT_PIX_ROUND( zone->cur[zone->n_points - 4].x );
825     zone->cur[zone->n_points - 3].x =
826       FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
827     zone->cur[zone->n_points - 2].y =
828       FT_PIX_ROUND( zone->cur[zone->n_points - 2].y );
829     zone->cur[zone->n_points - 1].y =
830       FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
831
832 #ifdef TT_USE_BYTECODE_INTERPRETER
833
834     if ( n_ins > 0 )
835     {
836       FT_Error  error;
837
838
839       TT_Set_CodeRange( exec, tt_coderange_glyph, exec->glyphIns, n_ins );
840
841       exec->is_composite = is_composite;
842       exec->pts          = *zone;
843
844       error = TT_Run_Context( exec );
845       if ( error && exec->pedantic_hinting )
846         return error;
847
848       /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
849       loader->gloader->current.outline.tags[0] |=
850         ( exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
851     }
852
853 #endif
854
855     /* Save possibly modified glyph phantom points unless in v40 backward  */
856     /* compatibility mode, where no movement on the x axis means no reason */
857     /* to change bearings or advance widths.                               */
858
859 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
860     if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
861          exec->backward_compatibility )
862       return FT_Err_Ok;
863 #endif
864
865     loader->pp1 = zone->cur[zone->n_points - 4];
866     loader->pp2 = zone->cur[zone->n_points - 3];
867     loader->pp3 = zone->cur[zone->n_points - 2];
868     loader->pp4 = zone->cur[zone->n_points - 1];
869
870     return FT_Err_Ok;
871   }
872
873
874   /**************************************************************************
875    *
876    * @Function:
877    *   TT_Process_Simple_Glyph
878    *
879    * @Description:
880    *   Once a simple glyph has been loaded, it needs to be processed.
881    *   Usually, this means scaling and hinting through bytecode
882    *   interpretation.
883    */
884   static FT_Error
885   TT_Process_Simple_Glyph( TT_Loader  loader )
886   {
887     FT_Error        error    = FT_Err_Ok;
888     FT_GlyphLoader  gloader  = loader->gloader;
889     FT_Outline*     outline  = &gloader->current.outline;
890     FT_Int          n_points = outline->n_points;
891
892 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
893     FT_Memory   memory    = loader->face->root.memory;
894     FT_Vector*  unrounded = NULL;
895 #endif
896
897
898     /* set phantom points */
899     outline->points[n_points    ] = loader->pp1;
900     outline->points[n_points + 1] = loader->pp2;
901     outline->points[n_points + 2] = loader->pp3;
902     outline->points[n_points + 3] = loader->pp4;
903
904     n_points += 4;
905
906 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
907
908     if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
909     {
910       if ( FT_QNEW_ARRAY( unrounded, n_points ) )
911         goto Exit;
912
913       /* Deltas apply to the unscaled data. */
914       error = TT_Vary_Apply_Glyph_Deltas( loader,
915                                           outline,
916                                           unrounded );
917       if ( error )
918         goto Exit;
919     }
920
921 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
922
923     if ( IS_HINTED( loader->load_flags ) )
924     {
925       tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
926
927       FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
928                      loader->zone.n_points );
929     }
930
931     {
932       FT_Vector*  vec   = outline->points;
933       FT_Vector*  limit = outline->points + n_points;
934
935       FT_Fixed  x_scale = 0; /* pacify compiler */
936       FT_Fixed  y_scale = 0;
937
938       FT_Bool  do_scale = FALSE;
939
940
941       {
942         /* scale the glyph */
943         if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
944         {
945           x_scale = loader->size->metrics->x_scale;
946           y_scale = loader->size->metrics->y_scale;
947
948           do_scale = TRUE;
949         }
950       }
951
952       if ( do_scale )
953       {
954 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
955         if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
956         {
957           FT_Vector*  u = unrounded;
958
959
960           for ( ; vec < limit; vec++, u++ )
961           {
962             vec->x = ADD_LONG( FT_MulFix( u->x, x_scale ), 32 ) >> 6;
963             vec->y = ADD_LONG( FT_MulFix( u->y, y_scale ), 32 ) >> 6;
964           }
965         }
966         else
967 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
968         {
969           for ( ; vec < limit; vec++ )
970           {
971             vec->x = FT_MulFix( vec->x, x_scale );
972             vec->y = FT_MulFix( vec->y, y_scale );
973           }
974         }
975       }
976
977 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
978       /* if we have a HVAR table, `pp1' and/or `pp2' */
979       /* are already adjusted but unscaled           */
980       if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) &&
981            IS_HINTED( loader->load_flags )                                 )
982       {
983         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
984         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
985         /* pp1.y and pp2.y are always zero */
986       }
987       else
988 #endif
989       {
990         loader->pp1 = outline->points[n_points - 4];
991         loader->pp2 = outline->points[n_points - 3];
992       }
993
994 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
995       /* if we have a VVAR table, `pp3' and/or `pp4' */
996       /* are already adjusted but unscaled           */
997       if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) &&
998            IS_HINTED( loader->load_flags )                                 )
999       {
1000         loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1001         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1002         loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1003         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1004       }
1005       else
1006 #endif
1007       {
1008         loader->pp3 = outline->points[n_points - 2];
1009         loader->pp4 = outline->points[n_points - 1];
1010       }
1011     }
1012
1013     if ( IS_HINTED( loader->load_flags ) )
1014       error = TT_Hint_Glyph( loader, 0 );
1015
1016 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1017   Exit:
1018     FT_FREE( unrounded );
1019 #endif
1020
1021     return error;
1022   }
1023
1024
1025   /**************************************************************************
1026    *
1027    * @Function:
1028    *   TT_Process_Composite_Component
1029    *
1030    * @Description:
1031    *   Once a composite component has been loaded, it needs to be
1032    *   processed.  Usually, this means transforming and translating.
1033    */
1034   static FT_Error
1035   TT_Process_Composite_Component( TT_Loader    loader,
1036                                   FT_SubGlyph  subglyph,
1037                                   FT_UInt      start_point,
1038                                   FT_UInt      num_base_points )
1039   {
1040     FT_GlyphLoader  gloader = loader->gloader;
1041     FT_Outline      current;
1042     FT_Bool         have_scale;
1043     FT_Pos          x, y;
1044
1045
1046     current.points   = gloader->base.outline.points +
1047                          num_base_points;
1048     current.n_points = gloader->base.outline.n_points -
1049                          (short)num_base_points;
1050
1051     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
1052                                               WE_HAVE_AN_XY_SCALE |
1053                                               WE_HAVE_A_2X2       ) );
1054
1055     /* perform the transform required for this subglyph */
1056     if ( have_scale )
1057       FT_Outline_Transform( &current, &subglyph->transform );
1058
1059     /* get offset */
1060     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
1061     {
1062       FT_UInt     num_points = (FT_UInt)gloader->base.outline.n_points;
1063       FT_UInt     k = (FT_UInt)subglyph->arg1;
1064       FT_UInt     l = (FT_UInt)subglyph->arg2;
1065       FT_Vector*  p1;
1066       FT_Vector*  p2;
1067
1068
1069       /* match l-th point of the newly loaded component to the k-th point */
1070       /* of the previously loaded components.                             */
1071
1072       /* change to the point numbers used by our outline */
1073       k += start_point;
1074       l += num_base_points;
1075       if ( k >= num_base_points ||
1076            l >= num_points      )
1077         return FT_THROW( Invalid_Composite );
1078
1079       p1 = gloader->base.outline.points + k;
1080       p2 = gloader->base.outline.points + l;
1081
1082       x = SUB_LONG( p1->x, p2->x );
1083       y = SUB_LONG( p1->y, p2->y );
1084     }
1085     else
1086     {
1087       x = subglyph->arg1;
1088       y = subglyph->arg2;
1089
1090       if ( !x && !y )
1091         return FT_Err_Ok;
1092
1093       /* Use a default value dependent on                                  */
1094       /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old */
1095       /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit.            */
1096
1097       if ( have_scale &&
1098 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
1099            !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
1100 #else
1101             ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
1102 #endif
1103       {
1104
1105 #if 0
1106
1107         /********************************************************************
1108          *
1109          * This algorithm is what Apple documents.  But it doesn't work.
1110          */
1111         int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
1112                                             : -subglyph->transform.xx;
1113         int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
1114                                             : -subglyph->transform.yx;
1115         int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
1116                                             : -subglyph->transform.xy;
1117         int  d = subglyph->transform.yy > 0 ?  subglyph->transform.yy
1118                                             : -subglyph->transform.yy;
1119         int  m = a > b ? a : b;
1120         int  n = c > d ? c : d;
1121
1122
1123         if ( a - b <= 33 && a - b >= -33 )
1124           m *= 2;
1125         if ( c - d <= 33 && c - d >= -33 )
1126           n *= 2;
1127         x = FT_MulFix( x, m );
1128         y = FT_MulFix( y, n );
1129
1130 #else /* 1 */
1131
1132         /********************************************************************
1133          *
1134          * This algorithm is a guess and works much better than the above.
1135          */
1136         FT_Fixed  mac_xscale = FT_Hypot( subglyph->transform.xx,
1137                                          subglyph->transform.xy );
1138         FT_Fixed  mac_yscale = FT_Hypot( subglyph->transform.yy,
1139                                          subglyph->transform.yx );
1140
1141
1142         x = FT_MulFix( x, mac_xscale );
1143         y = FT_MulFix( y, mac_yscale );
1144
1145 #endif /* 1 */
1146
1147       }
1148
1149       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1150       {
1151         FT_Fixed  x_scale = loader->size->metrics->x_scale;
1152         FT_Fixed  y_scale = loader->size->metrics->y_scale;
1153
1154
1155         x = FT_MulFix( x, x_scale );
1156         y = FT_MulFix( y, y_scale );
1157
1158         if ( subglyph->flags & ROUND_XY_TO_GRID )
1159         {
1160           TT_Face    face   = loader->face;
1161           TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
1162
1163
1164           if ( IS_HINTED( loader->load_flags ) )
1165           {
1166             /*
1167              * We round the horizontal offset only if there is hinting along
1168              * the x axis; this corresponds to integer advance width values.
1169              *
1170              * Theoretically, a glyph's bytecode can toggle ClearType's
1171              * `backward compatibility' mode, which would allow modification
1172              * of the advance width.  In reality, however, applications
1173              * neither allow nor expect modified advance widths if subpixel
1174              * rendering is active.
1175              *
1176              */
1177             if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 )
1178               x = FT_PIX_ROUND( x );
1179
1180             y = FT_PIX_ROUND( y );
1181           }
1182         }
1183       }
1184     }
1185
1186     if ( x || y )
1187       FT_Outline_Translate( &current, x, y );
1188
1189     return FT_Err_Ok;
1190   }
1191
1192
1193   /**************************************************************************
1194    *
1195    * @Function:
1196    *   TT_Process_Composite_Glyph
1197    *
1198    * @Description:
1199    *   This is slightly different from TT_Process_Simple_Glyph, in that
1200    *   its sole purpose is to hint the glyph.  Thus this function is
1201    *   only available when bytecode interpreter is enabled.
1202    */
1203   static FT_Error
1204   TT_Process_Composite_Glyph( TT_Loader  loader,
1205                               FT_UInt    start_point,
1206                               FT_UInt    start_contour )
1207   {
1208     FT_Error     error;
1209     FT_Outline*  outline = &loader->gloader->base.outline;
1210     FT_Stream    stream = loader->stream;
1211     FT_UShort    n_ins;
1212     FT_UInt      i;
1213
1214
1215     /* make room for phantom points */
1216     error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1217                                          outline->n_points + 4,
1218                                          0 );
1219     if ( error )
1220       return error;
1221
1222     outline->points[outline->n_points    ] = loader->pp1;
1223     outline->points[outline->n_points + 1] = loader->pp2;
1224     outline->points[outline->n_points + 2] = loader->pp3;
1225     outline->points[outline->n_points + 3] = loader->pp4;
1226
1227 #ifdef TT_USE_BYTECODE_INTERPRETER
1228
1229     {
1230       TT_ExecContext  exec = loader->exec;
1231       FT_Memory       memory = exec->memory;
1232
1233
1234       if ( exec->glyphSize )
1235         FT_FREE( exec->glyphIns );
1236       exec->glyphSize = 0;
1237
1238       /* TT_Load_Composite_Glyph only gives us the offset of instructions */
1239       /* so we read them here                                             */
1240       if ( FT_STREAM_SEEK( loader->ins_pos ) ||
1241            FT_READ_USHORT( n_ins )           )
1242         return error;
1243
1244       FT_TRACE5(( "  Instructions size = %hu\n", n_ins ));
1245
1246       if ( !n_ins )
1247         return FT_Err_Ok;
1248
1249       /* don't trust `maxSizeOfInstructions'; */
1250       /* only do a rough safety check         */
1251       if ( n_ins > loader->byte_len )
1252       {
1253         FT_TRACE1(( "TT_Process_Composite_Glyph:"
1254                     " too many instructions (%hu) for glyph with length %u\n",
1255                     n_ins, loader->byte_len ));
1256         return FT_THROW( Too_Many_Hints );
1257       }
1258
1259       if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins )  ||
1260            FT_STREAM_READ( exec->glyphIns, n_ins ) )
1261         return error;
1262
1263       exec->glyphSize = n_ins;
1264     }
1265
1266 #endif
1267
1268     tt_prepare_zone( &loader->zone, &loader->gloader->base,
1269                      start_point, start_contour );
1270
1271     /* Some points are likely touched during execution of  */
1272     /* instructions on components.  So let's untouch them. */
1273     for ( i = 0; i < loader->zone.n_points - 4U; i++ )
1274       loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
1275
1276     return TT_Hint_Glyph( loader, 1 );
1277   }
1278
1279
1280   /*
1281    * Calculate the phantom points
1282    *
1283    * Defining the right side bearing (rsb) as
1284    *
1285    *   rsb = aw - (lsb + xmax - xmin)
1286    *
1287    * (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
1288    * and `xmax' the glyph's minimum and maximum x value), the OpenType
1289    * specification defines the initial position of horizontal phantom points
1290    * as
1291    *
1292    *   pp1 = (round(xmin - lsb), 0)      ,
1293    *   pp2 = (round(pp1 + aw), 0)        .
1294    *
1295    * Note that the rounding to the grid (in the device space) is not
1296    * documented currently in the specification.
1297    *
1298    * However, the specification lacks the precise definition of vertical
1299    * phantom points.  Greg Hitchcock provided the following explanation.
1300    *
1301    * - a `vmtx' table is present
1302    *
1303    *   For any glyph, the minimum and maximum y values (`ymin' and `ymax')
1304    *   are given in the `glyf' table, the top side bearing (tsb) and advance
1305    *   height (ah) are given in the `vmtx' table.  The bottom side bearing
1306    *   (bsb) is then calculated as
1307    *
1308    *     bsb = ah - (tsb + ymax - ymin)       ,
1309    *
1310    *   and the initial position of vertical phantom points is
1311    *
1312    *     pp3 = (x, round(ymax + tsb))       ,
1313    *     pp4 = (x, round(pp3 - ah))         .
1314    *
1315    *   See below for value `x'.
1316    *
1317    * - no `vmtx' table in the font
1318    *
1319    *   If there is an `OS/2' table, we set
1320    *
1321    *     DefaultAscender = sTypoAscender       ,
1322    *     DefaultDescender = sTypoDescender     ,
1323    *
1324    *   otherwise we use data from the `hhea' table:
1325    *
1326    *     DefaultAscender = Ascender         ,
1327    *     DefaultDescender = Descender       .
1328    *
1329    *   With these two variables we can now set
1330    *
1331    *     ah = DefaultAscender - sDefaultDescender    ,
1332    *     tsb = DefaultAscender - yMax                ,
1333    *
1334    *   and proceed as if a `vmtx' table was present.
1335    *
1336    * Usually we have
1337    *
1338    *   x = aw / 2      ,                                                (1)
1339    *
1340    * but there is one compatibility case where it can be set to
1341    *
1342    *   x = -DefaultDescender -
1343    *         ((DefaultAscender - DefaultDescender - aw) / 2)     .      (2)
1344    *
1345    * and another one with
1346    *
1347    *   x = 0     .                                                      (3)
1348    *
1349    * In Windows, the history of those values is quite complicated,
1350    * depending on the hinting engine (that is, the graphics framework).
1351    *
1352    *   framework        from                 to       formula
1353    *  ----------------------------------------------------------
1354    *    GDI       Windows 98               current      (1)
1355    *              (Windows 2000 for NT)
1356    *    GDI+      Windows XP               Windows 7    (2)
1357    *    GDI+      Windows 8                current      (3)
1358    *    DWrite    Windows 7                current      (3)
1359    *
1360    * For simplicity, FreeType uses (1) for grayscale subpixel hinting and
1361    * (3) for everything else.
1362    *
1363    */
1364   static void
1365   tt_loader_set_pp( TT_Loader  loader )
1366   {
1367     loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
1368     loader->pp1.y = 0;
1369     loader->pp2.x = loader->pp1.x + loader->advance;
1370     loader->pp2.y = 0;
1371
1372     loader->pp3.x = 0;
1373     loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
1374     loader->pp4.x = 0;
1375     loader->pp4.y = loader->pp3.y - loader->vadvance;
1376
1377 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1378     {
1379       TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
1380
1381
1382       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
1383            loader->exec                                             &&
1384            loader->exec->subpixel_hinting_lean                      &&
1385            loader->exec->grayscale_cleartype                        )
1386       {
1387         loader->pp3.x = loader->advance / 2;
1388         loader->pp4.x = loader->advance / 2;
1389       }
1390     }
1391 #endif
1392   }
1393
1394
1395   /* a utility function to retrieve i-th node from given FT_List */
1396   static FT_ListNode
1397   ft_list_get_node_at( FT_List  list,
1398                        FT_UInt  idx )
1399   {
1400     FT_ListNode  cur;
1401
1402
1403     if ( !list )
1404       return NULL;
1405
1406     for ( cur = list->head; cur; cur = cur->next )
1407     {
1408       if ( !idx )
1409         return cur;
1410
1411       idx--;
1412     }
1413
1414     return NULL;
1415   }
1416
1417
1418   /**************************************************************************
1419    *
1420    * @Function:
1421    *   load_truetype_glyph
1422    *
1423    * @Description:
1424    *   Loads a given truetype glyph.  Handles composites and uses a
1425    *   TT_Loader object.
1426    */
1427   static FT_Error
1428   load_truetype_glyph( TT_Loader  loader,
1429                        FT_UInt    glyph_index,
1430                        FT_UInt    recurse_count,
1431                        FT_Bool    header_only )
1432   {
1433     FT_Error        error   = FT_Err_Ok;
1434     FT_Fixed        x_scale, y_scale;
1435     FT_ULong        offset;
1436     TT_Face         face    = loader->face;
1437     FT_GlyphLoader  gloader = loader->gloader;
1438
1439     FT_Bool  opened_frame = 0;
1440
1441 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1442     FT_StreamRec    inc_stream;
1443     FT_Data         glyph_data;
1444     FT_Bool         glyph_data_loaded = 0;
1445 #endif
1446
1447
1448 #ifdef FT_DEBUG_LEVEL_TRACE
1449     if ( recurse_count )
1450       FT_TRACE5(( "  nesting level: %d\n", recurse_count ));
1451 #endif
1452
1453     /* some fonts have an incorrect value of `maxComponentDepth' */
1454     if ( recurse_count > face->max_profile.maxComponentDepth )
1455     {
1456       FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n",
1457                   recurse_count ));
1458       face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
1459     }
1460
1461 #ifndef FT_CONFIG_OPTION_INCREMENTAL
1462     /* check glyph index */
1463     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1464     {
1465       error = FT_THROW( Invalid_Glyph_Index );
1466       goto Exit;
1467     }
1468 #endif
1469
1470     loader->glyph_index = glyph_index;
1471
1472     if ( loader->load_flags & FT_LOAD_NO_SCALE )
1473     {
1474       x_scale = 0x10000L;
1475       y_scale = 0x10000L;
1476     }
1477     else
1478     {
1479       x_scale = loader->size->metrics->x_scale;
1480       y_scale = loader->size->metrics->y_scale;
1481     }
1482
1483     /* Set `offset' to the start of the glyph relative to the start of */
1484     /* the `glyf' table, and `byte_len' to the length of the glyph in  */
1485     /* bytes.                                                          */
1486
1487 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1488
1489     /* If we are loading glyph data via the incremental interface, set */
1490     /* the loader stream to a memory stream reading the data returned  */
1491     /* by the interface.                                               */
1492     if ( face->root.internal->incremental_interface )
1493     {
1494       error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1495                 face->root.internal->incremental_interface->object,
1496                 glyph_index, &glyph_data );
1497       if ( error )
1498         goto Exit;
1499
1500       glyph_data_loaded = 1;
1501       offset            = 0;
1502       loader->byte_len  = glyph_data.length;
1503
1504       FT_ZERO( &inc_stream );
1505       FT_Stream_OpenMemory( &inc_stream,
1506                             glyph_data.pointer,
1507                             glyph_data.length );
1508
1509       loader->stream = &inc_stream;
1510     }
1511     else
1512
1513 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1514     {
1515       FT_ULong  len;
1516
1517
1518       offset = tt_face_get_location( FT_FACE( face ), glyph_index, &len );
1519
1520       loader->byte_len = (FT_UInt)len;
1521     }
1522
1523     if ( loader->byte_len > 0 )
1524     {
1525 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1526       /* for the incremental interface, `glyf_offset' is always zero */
1527       if ( !face->glyf_offset                          &&
1528            !face->root.internal->incremental_interface )
1529 #else
1530       if ( !face->glyf_offset )
1531 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1532       {
1533         FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
1534         error = FT_THROW( Invalid_Table );
1535         goto Exit;
1536       }
1537
1538       error = face->access_glyph_frame( loader, glyph_index,
1539                                         face->glyf_offset + offset,
1540                                         loader->byte_len );
1541       if ( error )
1542         goto Exit;
1543
1544       /* read glyph header first */
1545       error = face->read_glyph_header( loader );
1546
1547       face->forget_glyph_frame( loader );
1548
1549       if ( error )
1550         goto Exit;
1551     }
1552
1553     /* a space glyph */
1554     if ( loader->byte_len == 0 || loader->n_contours == 0 )
1555     {
1556       loader->bbox.xMin = 0;
1557       loader->bbox.xMax = 0;
1558       loader->bbox.yMin = 0;
1559       loader->bbox.yMax = 0;
1560     }
1561
1562     /* the metrics must be computed after loading the glyph header */
1563     /* since we need the glyph's `yMax' value in case the vertical */
1564     /* metrics must be emulated                                    */
1565     error = tt_get_metrics( loader, glyph_index );
1566     if ( error )
1567       goto Exit;
1568
1569     if ( header_only )
1570       goto Exit;
1571
1572     if ( loader->byte_len == 0 || loader->n_contours == 0 )
1573     {
1574 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1575       tt_get_metrics_incremental( loader, glyph_index );
1576 #endif
1577       tt_loader_set_pp( loader );
1578
1579
1580 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1581
1582       if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1583            FT_IS_VARIATION( FT_FACE( face ) )      )
1584       {
1585         /* a small outline structure with four elements for */
1586         /* communication with `TT_Vary_Apply_Glyph_Deltas'  */
1587         FT_Vector   points[4];
1588         FT_Outline  outline;
1589
1590         /* unrounded values */
1591         FT_Vector  unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1592
1593
1594         points[0] = loader->pp1;
1595         points[1] = loader->pp2;
1596         points[2] = loader->pp3;
1597         points[3] = loader->pp4;
1598
1599         outline.n_points   = 0;
1600         outline.n_contours = 0;
1601         outline.points     = points;
1602         outline.tags       = NULL;
1603         outline.contours   = NULL;
1604
1605         /* this must be done before scaling */
1606         error = TT_Vary_Apply_Glyph_Deltas( loader,
1607                                             &outline,
1608                                             unrounded );
1609         if ( error )
1610           goto Exit;
1611       }
1612
1613 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1614
1615       /* scale phantom points, if necessary; */
1616       /* they get rounded in `TT_Hint_Glyph' */
1617       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1618       {
1619         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1620         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1621         /* pp1.y and pp2.y are always zero */
1622
1623         loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1624         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1625         loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1626         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1627       }
1628
1629       error = FT_Err_Ok;
1630       goto Exit;
1631     }
1632
1633 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1634     tt_get_metrics_incremental( loader, glyph_index );
1635 #endif
1636     tt_loader_set_pp( loader );
1637
1638
1639     /***********************************************************************/
1640     /***********************************************************************/
1641     /***********************************************************************/
1642
1643     /* we now open a frame again, right after the glyph header */
1644     /* (which consists of 10 bytes)                            */
1645     error = face->access_glyph_frame( loader, glyph_index,
1646                                       face->glyf_offset + offset + 10,
1647                                       loader->byte_len - 10 );
1648     if ( error )
1649       goto Exit;
1650
1651     opened_frame = 1;
1652
1653     /* if it is a simple glyph, load it */
1654
1655     if ( loader->n_contours > 0 )
1656     {
1657       error = face->read_simple_glyph( loader );
1658       if ( error )
1659         goto Exit;
1660
1661       /* all data have been read */
1662       face->forget_glyph_frame( loader );
1663       opened_frame = 0;
1664
1665       error = TT_Process_Simple_Glyph( loader );
1666       if ( error )
1667         goto Exit;
1668
1669       FT_GlyphLoader_Add( gloader );
1670     }
1671
1672     /***********************************************************************/
1673     /***********************************************************************/
1674     /***********************************************************************/
1675
1676     /* otherwise, load a composite! */
1677     else if ( loader->n_contours < 0 )
1678     {
1679       FT_Memory  memory = face->root.memory;
1680
1681       FT_UInt   start_point;
1682       FT_UInt   start_contour;
1683       FT_ULong  ins_pos;  /* position of composite instructions, if any */
1684
1685       FT_ListNode  node, node2;
1686
1687
1688       /* normalize the `n_contours' value */
1689       loader->n_contours = -1;
1690
1691       /*
1692        * We store the glyph index directly in the `node->data' pointer,
1693        * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
1694        * double cast to make this portable.  Note, however, that this needs
1695        * pointers with a width of at least 32 bits.
1696        */
1697
1698       /* clear the nodes filled by sibling chains */
1699       node = ft_list_get_node_at( &loader->composites, recurse_count );
1700       for ( node2 = node; node2; node2 = node2->next )
1701         node2->data = (void*)-1;
1702
1703       /* check whether we already have a composite glyph with this index */
1704       if ( FT_List_Find( &loader->composites,
1705                          FT_UINT_TO_POINTER( glyph_index ) ) )
1706       {
1707         FT_TRACE1(( "TT_Load_Composite_Glyph:"
1708                     " infinite recursion detected\n" ));
1709         error = FT_THROW( Invalid_Composite );
1710         goto Exit;
1711       }
1712
1713       else if ( node )
1714         node->data = FT_UINT_TO_POINTER( glyph_index );
1715
1716       else
1717       {
1718         if ( FT_QNEW( node ) )
1719           goto Exit;
1720         node->data = FT_UINT_TO_POINTER( glyph_index );
1721         FT_List_Add( &loader->composites, node );
1722       }
1723
1724       start_point   = (FT_UInt)gloader->base.outline.n_points;
1725       start_contour = (FT_UInt)gloader->base.outline.n_contours;
1726
1727       /* for each subglyph, read composite header */
1728       error = face->read_composite_glyph( loader );
1729       if ( error )
1730         goto Exit;
1731
1732       /* store the offset of instructions */
1733       ins_pos = loader->ins_pos;
1734
1735       /* all data we need are read */
1736       face->forget_glyph_frame( loader );
1737       opened_frame = 0;
1738
1739 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1740
1741       if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1742            FT_IS_VARIATION( FT_FACE( face ) )      )
1743       {
1744         short        i, limit;
1745         FT_SubGlyph  subglyph;
1746
1747         FT_Outline  outline = { 0, 0, NULL, NULL, NULL, 0 };
1748         FT_Vector*  unrounded = NULL;
1749
1750
1751         limit = (short)gloader->current.num_subglyphs;
1752
1753         /* construct an outline structure for              */
1754         /* communication with `TT_Vary_Apply_Glyph_Deltas' */
1755         if ( FT_QNEW_ARRAY( outline.points, limit + 4 ) ||
1756              FT_QNEW_ARRAY( outline.tags, limit )       ||
1757              FT_QNEW_ARRAY( outline.contours, limit )   ||
1758              FT_QNEW_ARRAY( unrounded, limit + 4 )      )
1759           goto Exit1;
1760
1761         outline.n_contours = outline.n_points = limit;
1762
1763         subglyph = gloader->current.subglyphs;
1764
1765         for ( i = 0; i < limit; i++, subglyph++ )
1766         {
1767           /* applying deltas for anchor points doesn't make sense, */
1768           /* but we don't have to specially check this since       */
1769           /* unused delta values are zero anyways                  */
1770           outline.points[i].x = subglyph->arg1;
1771           outline.points[i].y = subglyph->arg2;
1772           outline.tags[i]     = ON_CURVE_POINT;
1773           outline.contours[i] = i;
1774         }
1775
1776         outline.points[i++] = loader->pp1;
1777         outline.points[i++] = loader->pp2;
1778         outline.points[i++] = loader->pp3;
1779         outline.points[i  ] = loader->pp4;
1780
1781         /* this call provides additional offsets */
1782         /* for each component's translation      */
1783         if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( loader,
1784                                                        &outline,
1785                                                        unrounded ) ) )
1786           goto Exit1;
1787
1788         subglyph = gloader->current.subglyphs;
1789
1790         for ( i = 0; i < limit; i++, subglyph++ )
1791         {
1792           if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1793           {
1794             subglyph->arg1 = (FT_Int16)outline.points[i].x;
1795             subglyph->arg2 = (FT_Int16)outline.points[i].y;
1796           }
1797         }
1798
1799       Exit1:
1800         FT_FREE( outline.points );
1801         FT_FREE( outline.tags );
1802         FT_FREE( outline.contours );
1803         FT_FREE( unrounded );
1804
1805         if ( error )
1806           goto Exit;
1807       }
1808
1809 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1810
1811       /* scale phantom points, if necessary; */
1812       /* they get rounded in `TT_Hint_Glyph' */
1813       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1814       {
1815         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1816         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1817         /* pp1.y and pp2.y are always zero */
1818
1819         loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1820         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1821         loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1822         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1823       }
1824
1825       /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
1826       /* `as is' in the glyph slot (the client application will be     */
1827       /* responsible for interpreting these data)...                   */
1828       if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1829       {
1830         FT_GlyphLoader_Add( gloader );
1831         loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
1832
1833         goto Exit;
1834       }
1835
1836       /*********************************************************************/
1837       /*********************************************************************/
1838       /*********************************************************************/
1839
1840       {
1841         FT_UInt      n, num_base_points;
1842         FT_SubGlyph  subglyph       = NULL;
1843
1844         FT_UInt      num_points     = start_point;
1845         FT_UInt      num_subglyphs  = gloader->current.num_subglyphs;
1846         FT_UInt      num_base_subgs = gloader->base.num_subglyphs;
1847
1848         FT_Stream    old_stream     = loader->stream;
1849         FT_UInt      old_byte_len   = loader->byte_len;
1850
1851
1852         FT_GlyphLoader_Add( gloader );
1853
1854         /* read each subglyph independently */
1855         for ( n = 0; n < num_subglyphs; n++ )
1856         {
1857           FT_Vector  pp[4];
1858
1859           FT_Int  linear_hadvance;
1860           FT_Int  linear_vadvance;
1861
1862
1863           /* Each time we call `load_truetype_glyph' in this loop, the */
1864           /* value of `gloader.base.subglyphs' can change due to table */
1865           /* reallocations.  We thus need to recompute the subglyph    */
1866           /* pointer on each iteration.                                */
1867           subglyph = gloader->base.subglyphs + num_base_subgs + n;
1868
1869           pp[0] = loader->pp1;
1870           pp[1] = loader->pp2;
1871           pp[2] = loader->pp3;
1872           pp[3] = loader->pp4;
1873
1874           linear_hadvance = loader->linear;
1875           linear_vadvance = loader->vadvance;
1876
1877           num_base_points = (FT_UInt)gloader->base.outline.n_points;
1878
1879           error = load_truetype_glyph( loader,
1880                                        (FT_UInt)subglyph->index,
1881                                        recurse_count + 1,
1882                                        FALSE );
1883           if ( error )
1884             goto Exit;
1885
1886           /* restore subglyph pointer */
1887           subglyph = gloader->base.subglyphs + num_base_subgs + n;
1888
1889           /* restore phantom points if necessary */
1890           if ( !( subglyph->flags & USE_MY_METRICS ) )
1891           {
1892             loader->pp1 = pp[0];
1893             loader->pp2 = pp[1];
1894             loader->pp3 = pp[2];
1895             loader->pp4 = pp[3];
1896
1897             loader->linear   = linear_hadvance;
1898             loader->vadvance = linear_vadvance;
1899           }
1900
1901           num_points = (FT_UInt)gloader->base.outline.n_points;
1902
1903           if ( num_points == num_base_points )
1904             continue;
1905
1906           /* gloader->base.outline consists of three parts:           */
1907           /*                                                          */
1908           /* 0 ----> start_point ----> num_base_points ----> n_points */
1909           /*    (1)               (2)                   (3)           */
1910           /*                                                          */
1911           /* (1) points that exist from the beginning                 */
1912           /* (2) component points that have been loaded so far        */
1913           /* (3) points of the newly loaded component                 */
1914           error = TT_Process_Composite_Component( loader,
1915                                                   subglyph,
1916                                                   start_point,
1917                                                   num_base_points );
1918           if ( error )
1919             goto Exit;
1920         }
1921
1922         loader->stream   = old_stream;
1923         loader->byte_len = old_byte_len;
1924
1925         /* process the glyph */
1926         loader->ins_pos = ins_pos;
1927         if ( IS_HINTED( loader->load_flags ) &&
1928 #ifdef TT_USE_BYTECODE_INTERPRETER
1929              subglyph                        &&
1930              subglyph->flags & WE_HAVE_INSTR &&
1931 #endif
1932              num_points > start_point )
1933         {
1934           error = TT_Process_Composite_Glyph( loader,
1935                                               start_point,
1936                                               start_contour );
1937           if ( error )
1938             goto Exit;
1939         }
1940       }
1941
1942       /* retain the overlap flag */
1943       if ( gloader->base.num_subglyphs                         &&
1944            gloader->base.subglyphs[0].flags & OVERLAP_COMPOUND )
1945         gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
1946     }
1947
1948     /***********************************************************************/
1949     /***********************************************************************/
1950     /***********************************************************************/
1951
1952   Exit:
1953
1954     if ( opened_frame )
1955       face->forget_glyph_frame( loader );
1956
1957 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1958
1959     if ( glyph_data_loaded )
1960       face->root.internal->incremental_interface->funcs->free_glyph_data(
1961         face->root.internal->incremental_interface->object,
1962         &glyph_data );
1963
1964 #endif
1965
1966     return error;
1967   }
1968
1969
1970   static FT_Error
1971   compute_glyph_metrics( TT_Loader  loader,
1972                          FT_UInt    glyph_index )
1973   {
1974     TT_Face       face  = loader->face;
1975     TT_Size       size  = loader->size;
1976     TT_GlyphSlot  glyph = loader->glyph;
1977     FT_BBox       bbox;
1978     FT_Fixed      y_scale;
1979
1980
1981     y_scale = 0x10000L;
1982     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1983       y_scale = size->metrics->y_scale;
1984
1985     if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
1986       FT_Outline_Get_CBox( &glyph->outline, &bbox );
1987     else
1988       bbox = loader->bbox;
1989
1990     /* get the device-independent horizontal advance; it is scaled later */
1991     /* by the base layer.                                                */
1992     glyph->linearHoriAdvance = loader->linear;
1993
1994     glyph->metrics.horiBearingX = bbox.xMin;
1995     glyph->metrics.horiBearingY = bbox.yMax;
1996     if ( loader->widthp )
1997       glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64;
1998     else
1999       glyph->metrics.horiAdvance = SUB_LONG( loader->pp2.x, loader->pp1.x );
2000
2001     /* set glyph dimensions */
2002     glyph->metrics.width  = SUB_LONG( bbox.xMax, bbox.xMin );
2003     glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin );
2004
2005     /* Now take care of vertical metrics.  In the case where there is */
2006     /* no vertical information within the font (relatively common),   */
2007     /* create some metrics manually                                   */
2008     {
2009       FT_Pos  top;      /* scaled vertical top side bearing  */
2010       FT_Pos  advance;  /* scaled vertical advance height    */
2011
2012
2013       /* Get the unscaled top bearing and advance height. */
2014       if ( face->vertical_info                   &&
2015            face->vertical.number_Of_VMetrics > 0 )
2016       {
2017         top = (FT_Short)FT_DivFix( SUB_LONG( loader->pp3.y, bbox.yMax ),
2018                                    y_scale );
2019
2020         if ( loader->pp3.y <= loader->pp4.y )
2021           advance = 0;
2022         else
2023           advance = (FT_UShort)FT_DivFix( SUB_LONG( loader->pp3.y,
2024                                                     loader->pp4.y ),
2025                                           y_scale );
2026       }
2027       else
2028       {
2029         FT_Pos  height;
2030
2031
2032         /* XXX Compute top side bearing and advance height in  */
2033         /*     Get_VMetrics instead of here.                   */
2034
2035         /* NOTE: The OS/2 values are the only `portable' ones, */
2036         /*       which is why we use them, if there is an OS/2 */
2037         /*       table in the font.  Otherwise, we use the     */
2038         /*       values defined in the horizontal header.      */
2039
2040         height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax,
2041                                                 bbox.yMin ),
2042                                       y_scale );
2043         if ( face->os2.version != 0xFFFFU )
2044           advance = (FT_Pos)( face->os2.sTypoAscender -
2045                               face->os2.sTypoDescender );
2046         else
2047           advance = (FT_Pos)( face->horizontal.Ascender -
2048                               face->horizontal.Descender );
2049
2050         top = ( advance - height ) / 2;
2051       }
2052
2053 #ifdef FT_CONFIG_OPTION_INCREMENTAL
2054       {
2055         FT_Incremental_InterfaceRec*  incr;
2056         FT_Incremental_MetricsRec     incr_metrics;
2057         FT_Error                      error;
2058
2059
2060         incr = face->root.internal->incremental_interface;
2061
2062         /* If this is an incrementally loaded font see if there are */
2063         /* overriding metrics for this glyph.                       */
2064         if ( incr && incr->funcs->get_glyph_metrics )
2065         {
2066           incr_metrics.bearing_x = 0;
2067           incr_metrics.bearing_y = top;
2068           incr_metrics.advance   = advance;
2069
2070           error = incr->funcs->get_glyph_metrics( incr->object,
2071                                                   glyph_index,
2072                                                   TRUE,
2073                                                   &incr_metrics );
2074           if ( error )
2075             return error;
2076
2077           top     = incr_metrics.bearing_y;
2078           advance = incr_metrics.advance;
2079         }
2080       }
2081
2082       /* GWW: Do vertical metrics get loaded incrementally too? */
2083
2084 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
2085
2086       glyph->linearVertAdvance = advance;
2087
2088       /* scale the metrics */
2089       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
2090       {
2091         top     = FT_MulFix( top,     y_scale );
2092         advance = FT_MulFix( advance, y_scale );
2093       }
2094
2095       /* XXX: for now, we have no better algorithm for the lsb, but it */
2096       /*      should work fine.                                        */
2097       /*                                                               */
2098       glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX,
2099                                               glyph->metrics.horiAdvance / 2 );
2100       glyph->metrics.vertBearingY = top;
2101       glyph->metrics.vertAdvance  = advance;
2102     }
2103
2104     return FT_Err_Ok;
2105   }
2106
2107
2108 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2109
2110   static FT_Error
2111   load_sbit_image( TT_Size       size,
2112                    TT_GlyphSlot  glyph,
2113                    FT_UInt       glyph_index,
2114                    FT_Int32      load_flags )
2115   {
2116     TT_Face             face   = (TT_Face)glyph->face;
2117     SFNT_Service        sfnt   = (SFNT_Service)face->sfnt;
2118     FT_Stream           stream = face->root.stream;
2119     FT_Error            error;
2120     TT_SBit_MetricsRec  sbit_metrics;
2121
2122
2123     error = sfnt->load_sbit_image( face,
2124                                    size->strike_index,
2125                                    glyph_index,
2126                                    (FT_UInt)load_flags,
2127                                    stream,
2128                                    &glyph->bitmap,
2129                                    &sbit_metrics );
2130     if ( !error )
2131     {
2132       glyph->outline.n_points   = 0;
2133       glyph->outline.n_contours = 0;
2134
2135       glyph->metrics.width  = (FT_Pos)sbit_metrics.width  * 64;
2136       glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64;
2137
2138       glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
2139       glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
2140       glyph->metrics.horiAdvance  = (FT_Pos)sbit_metrics.horiAdvance  * 64;
2141
2142       glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
2143       glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
2144       glyph->metrics.vertAdvance  = (FT_Pos)sbit_metrics.vertAdvance  * 64;
2145
2146       glyph->format = FT_GLYPH_FORMAT_BITMAP;
2147
2148       if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2149       {
2150         glyph->bitmap_left = sbit_metrics.vertBearingX;
2151         glyph->bitmap_top  = sbit_metrics.vertBearingY;
2152       }
2153       else
2154       {
2155         glyph->bitmap_left = sbit_metrics.horiBearingX;
2156         glyph->bitmap_top  = sbit_metrics.horiBearingY;
2157       }
2158     }
2159
2160     return error;
2161   }
2162
2163 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2164
2165
2166   static FT_Error
2167   tt_loader_init( TT_Loader     loader,
2168                   TT_Size       size,
2169                   TT_GlyphSlot  glyph,
2170                   FT_Int32      load_flags,
2171                   FT_Bool       glyf_table_only )
2172   {
2173     TT_Face    face   = (TT_Face)glyph->face;
2174     FT_Stream  stream = face->root.stream;
2175
2176 #ifdef TT_USE_BYTECODE_INTERPRETER
2177     FT_Error   error;
2178     FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2179 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2180     TT_Driver  driver   = (TT_Driver)FT_FACE_DRIVER( glyph->face );
2181 #endif
2182 #endif
2183
2184
2185     FT_ZERO( loader );
2186
2187 #ifdef TT_USE_BYTECODE_INTERPRETER
2188
2189     /* load execution context */
2190     if ( IS_HINTED( load_flags ) && !glyf_table_only )
2191     {
2192       TT_ExecContext  exec;
2193       FT_Bool         grayscale = TRUE;
2194 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2195       FT_Bool         subpixel_hinting_lean;
2196       FT_Bool         grayscale_cleartype;
2197 #endif
2198
2199       FT_Bool  reexecute = FALSE;
2200
2201
2202       if ( size->bytecode_ready < 0 || size->cvt_ready < 0 )
2203       {
2204         error = tt_size_ready_bytecode( size, pedantic );
2205         if ( error )
2206           return error;
2207       }
2208       else if ( size->bytecode_ready )
2209         return size->bytecode_ready;
2210       else if ( size->cvt_ready )
2211         return size->cvt_ready;
2212
2213       /* query new execution context */
2214       exec = size->context;
2215       if ( !exec )
2216         return FT_THROW( Could_Not_Find_Context );
2217
2218       grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2219                              FT_RENDER_MODE_MONO             );
2220
2221 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2222       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2223       {
2224         subpixel_hinting_lean =
2225           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2226                    FT_RENDER_MODE_MONO               );
2227         grayscale_cleartype =
2228           FT_BOOL( subpixel_hinting_lean         &&
2229                    !( ( load_flags         &
2230                         FT_LOAD_TARGET_LCD )   ||
2231                       ( load_flags           &
2232                         FT_LOAD_TARGET_LCD_V ) ) );
2233         exec->vertical_lcd_lean =
2234           FT_BOOL( subpixel_hinting_lean    &&
2235                    ( load_flags           &
2236                      FT_LOAD_TARGET_LCD_V ) );
2237         grayscale = FT_BOOL( grayscale && !subpixel_hinting_lean );
2238       }
2239       else
2240       {
2241         subpixel_hinting_lean   = FALSE;
2242         grayscale_cleartype     = FALSE;
2243         exec->vertical_lcd_lean = FALSE;
2244       }
2245 #endif
2246
2247       error = TT_Load_Context( exec, face, size );
2248       if ( error )
2249         return error;
2250
2251       {
2252 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2253         if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2254         {
2255           /* a change from mono to subpixel rendering (and vice versa) */
2256           /* requires a re-execution of the CVT program                */
2257           if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
2258           {
2259             FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
2260                         " re-executing `prep' table\n" ));
2261
2262             exec->subpixel_hinting_lean = subpixel_hinting_lean;
2263             reexecute                   = TRUE;
2264           }
2265
2266           /* a change from colored to grayscale subpixel rendering (and */
2267           /* vice versa) requires a re-execution of the CVT program     */
2268           if ( grayscale_cleartype != exec->grayscale_cleartype )
2269           {
2270             FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
2271                         " re-executing `prep' table\n" ));
2272
2273             exec->grayscale_cleartype = grayscale_cleartype;
2274             reexecute                 = TRUE;
2275           }
2276         }
2277 #endif
2278
2279         /* a change from mono to grayscale rendering (and vice versa) */
2280         /* requires a re-execution of the CVT program                 */
2281         if ( grayscale != exec->grayscale )
2282         {
2283           FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
2284                       " re-executing `prep' table\n" ));
2285
2286           exec->grayscale = grayscale;
2287           reexecute       = TRUE;
2288         }
2289       }
2290
2291       if ( reexecute )
2292       {
2293         error = tt_size_run_prep( size, pedantic );
2294         if ( error )
2295           return error;
2296         error = TT_Load_Context( exec, face, size );
2297         if ( error )
2298           return error;
2299       }
2300
2301       /* check whether the cvt program has disabled hinting */
2302       if ( exec->GS.instruct_control & 1 )
2303         load_flags |= FT_LOAD_NO_HINTING;
2304
2305       /* load default graphics state -- if needed */
2306       if ( exec->GS.instruct_control & 2 )
2307         exec->GS = tt_default_graphics_state;
2308
2309 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2310       /*
2311        * Toggle backward compatibility according to what font wants, except
2312        * when
2313        *
2314        * 1) we have a `tricky' font that heavily relies on the interpreter to
2315        *    render glyphs correctly, for example DFKai-SB, or
2316        * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
2317        *
2318        * In those cases, backward compatibility needs to be turned off to get
2319        * correct rendering.  The rendering is then completely up to the
2320        * font's programming.
2321        *
2322        */
2323       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
2324            subpixel_hinting_lean                                    &&
2325            !FT_IS_TRICKY( glyph->face )                             )
2326         exec->backward_compatibility = !( exec->GS.instruct_control & 4 );
2327       else
2328         exec->backward_compatibility = FALSE;
2329 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
2330
2331       exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2332       loader->exec = exec;
2333       loader->instructions = exec->glyphIns;
2334
2335       /* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */
2336       /* is set or backward compatibility mode of the v38 or v40  */
2337       /* interpreters is active.  See `ttinterp.h' for details on */
2338       /* backward compatibility mode.                             */
2339       if ( IS_HINTED( loader->load_flags )                                &&
2340            !( loader->load_flags & FT_LOAD_COMPUTE_METRICS )              &&
2341 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2342            !( driver->interpreter_version == TT_INTERPRETER_VERSION_40  &&
2343               exec->backward_compatibility                              ) &&
2344 #endif
2345            !face->postscript.isFixedPitch                                 )
2346       {
2347         loader->widthp = size->widthp;
2348       }
2349       else
2350         loader->widthp = NULL;
2351     }
2352
2353 #endif /* TT_USE_BYTECODE_INTERPRETER */
2354
2355     /* get face's glyph loader */
2356     if ( !glyf_table_only )
2357     {
2358       FT_GlyphLoader  gloader = glyph->internal->loader;
2359
2360
2361       FT_GlyphLoader_Rewind( gloader );
2362       loader->gloader = gloader;
2363     }
2364
2365     loader->load_flags = (FT_ULong)load_flags;
2366
2367     loader->face   = face;
2368     loader->size   = size;
2369     loader->glyph  = (FT_GlyphSlot)glyph;
2370     loader->stream = stream;
2371
2372     loader->composites.head = NULL;
2373     loader->composites.tail = NULL;
2374
2375     return FT_Err_Ok;
2376   }
2377
2378
2379   static void
2380   tt_loader_done( TT_Loader  loader )
2381   {
2382     FT_List_Finalize( &loader->composites,
2383                       NULL,
2384                       loader->face->root.memory,
2385                       NULL );
2386   }
2387
2388
2389   /**************************************************************************
2390    *
2391    * @Function:
2392    *   TT_Load_Glyph
2393    *
2394    * @Description:
2395    *   A function used to load a single glyph within a given glyph slot,
2396    *   for a given size.
2397    *
2398    * @InOut:
2399    *   glyph ::
2400    *     A handle to a target slot object where the glyph
2401    *     will be loaded.
2402    *
2403    * @Input:
2404    *   size ::
2405    *     A handle to the source face size at which the glyph
2406    *     must be scaled/loaded.
2407    *
2408    *   glyph_index ::
2409    *     The index of the glyph in the font file.
2410    *
2411    *   load_flags ::
2412    *     A flag indicating what to load for this glyph.  The
2413    *     FT_LOAD_XXX constants can be used to control the
2414    *     glyph loading process (e.g., whether the outline
2415    *     should be scaled, whether to load bitmaps or not,
2416    *     whether to hint the outline, etc).
2417    *
2418    * @Return:
2419    *   FreeType error code.  0 means success.
2420    */
2421   FT_LOCAL_DEF( FT_Error )
2422   TT_Load_Glyph( TT_Size       size,
2423                  TT_GlyphSlot  glyph,
2424                  FT_UInt       glyph_index,
2425                  FT_Int32      load_flags )
2426   {
2427     TT_Face       face = (TT_Face)glyph->face;
2428     FT_Error      error;
2429     TT_LoaderRec  loader;
2430
2431
2432     FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
2433
2434 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2435
2436     /* try to load embedded bitmap (if any) */
2437     if ( size->strike_index != 0xFFFFFFFFUL      &&
2438          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
2439          IS_DEFAULT_INSTANCE( glyph->face )      )
2440     {
2441       FT_Fixed  x_scale = size->root.metrics.x_scale;
2442       FT_Fixed  y_scale = size->root.metrics.y_scale;
2443
2444
2445       error = load_sbit_image( size, glyph, glyph_index, load_flags );
2446       if ( FT_ERR_EQ( error, Missing_Bitmap ) )
2447       {
2448         /* the bitmap strike is incomplete and misses the requested glyph; */
2449         /* if we have a bitmap-only font, return an empty glyph            */
2450         if ( !FT_IS_SCALABLE( glyph->face ) )
2451         {
2452           FT_Short  left_bearing = 0;
2453           FT_Short  top_bearing  = 0;
2454
2455           FT_UShort  advance_width  = 0;
2456           FT_UShort  advance_height = 0;
2457
2458
2459           /* to return an empty glyph, however, we need metrics data   */
2460           /* from the `hmtx' (or `vmtx') table; the assumption is that */
2461           /* empty glyphs are missing intentionally, representing      */
2462           /* whitespace - not having at least horizontal metrics is    */
2463           /* thus considered an error                                  */
2464           if ( !face->horz_metrics_size )
2465             return error;
2466
2467           /* we now construct an empty bitmap glyph */
2468           TT_Get_HMetrics( face, glyph_index,
2469                            &left_bearing,
2470                            &advance_width );
2471           TT_Get_VMetrics( face, glyph_index,
2472                            0,
2473                            &top_bearing,
2474                            &advance_height );
2475
2476           glyph->outline.n_points   = 0;
2477           glyph->outline.n_contours = 0;
2478
2479           glyph->metrics.width  = 0;
2480           glyph->metrics.height = 0;
2481
2482           glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale );
2483           glyph->metrics.horiBearingY = 0;
2484           glyph->metrics.horiAdvance  = FT_MulFix( advance_width, x_scale );
2485
2486           glyph->metrics.vertBearingX = 0;
2487           glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale );
2488           glyph->metrics.vertAdvance  = FT_MulFix( advance_height, y_scale );
2489
2490           glyph->format            = FT_GLYPH_FORMAT_BITMAP;
2491           glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
2492
2493           glyph->bitmap_left = 0;
2494           glyph->bitmap_top  = 0;
2495
2496           return FT_Err_Ok;
2497         }
2498       }
2499       else if ( error )
2500       {
2501         /* return error if font is not scalable */
2502         if ( !FT_IS_SCALABLE( glyph->face ) )
2503           return error;
2504       }
2505       else
2506       {
2507         if ( FT_IS_SCALABLE( glyph->face ) ||
2508              FT_HAS_SBIX( glyph->face )    )
2509         {
2510           /* for the bbox we need the header only */
2511           (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
2512           (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
2513           tt_loader_done( &loader );
2514           glyph->linearHoriAdvance = loader.linear;
2515           glyph->linearVertAdvance = loader.vadvance;
2516
2517           /* Bitmaps from the 'sbix' table need special treatment:  */
2518           /* if there is a glyph contour, the bitmap origin must be */
2519           /* shifted to be relative to the lower left corner of the */
2520           /* glyph bounding box, also taking the left-side bearing  */
2521           /* (or top bearing) into account.                         */
2522           if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX &&
2523                loader.n_contours > 0                            )
2524           {
2525             FT_Int  bitmap_left;
2526             FT_Int  bitmap_top;
2527
2528
2529             if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2530             {
2531               /* This is a guess, since Apple's CoreText engine doesn't */
2532               /* really do vertical typesetting.                        */
2533               bitmap_left = loader.bbox.xMin;
2534               bitmap_top  = loader.top_bearing;
2535             }
2536             else
2537             {
2538               bitmap_left = loader.left_bearing;
2539               bitmap_top  = loader.bbox.yMin;
2540             }
2541
2542             glyph->bitmap_left += FT_MulFix( bitmap_left, x_scale ) >> 6;
2543             glyph->bitmap_top  += FT_MulFix( bitmap_top,  y_scale ) >> 6;
2544           }
2545
2546           /* sanity checks: if `xxxAdvance' in the sbit metric */
2547           /* structure isn't set, use `linearXXXAdvance'      */
2548           if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
2549             glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance,
2550                                                     x_scale );
2551           if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
2552             glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance,
2553                                                     y_scale );
2554         }
2555
2556         return FT_Err_Ok;
2557       }
2558     }
2559
2560     if ( load_flags & FT_LOAD_SBITS_ONLY )
2561     {
2562       error = FT_THROW( Invalid_Argument );
2563       goto Exit;
2564     }
2565
2566 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2567
2568     /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
2569     if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
2570     {
2571       error = FT_THROW( Invalid_Size_Handle );
2572       goto Exit;
2573     }
2574
2575 #ifdef FT_CONFIG_OPTION_SVG
2576
2577     /* check for OT-SVG */
2578     if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 &&
2579          ( load_flags & FT_LOAD_COLOR )       &&
2580          face->svg                            )
2581     {
2582       SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
2583
2584
2585       FT_TRACE3(( "Trying to load SVG glyph\n" ));
2586
2587       error = sfnt->load_svg_doc( glyph, glyph_index );
2588       if ( !error )
2589       {
2590         FT_Fixed  x_scale = size->root.metrics.x_scale;
2591         FT_Fixed  y_scale = size->root.metrics.y_scale;
2592
2593         FT_Short   leftBearing;
2594         FT_Short   topBearing;
2595         FT_UShort  advanceX;
2596         FT_UShort  advanceY;
2597
2598
2599         FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
2600
2601         glyph->format = FT_GLYPH_FORMAT_SVG;
2602
2603         sfnt->get_metrics( face,
2604                            FALSE,
2605                            glyph_index,
2606                            &leftBearing,
2607                            &advanceX );
2608         sfnt->get_metrics( face,
2609                            TRUE,
2610                            glyph_index,
2611                            &topBearing,
2612                            &advanceY );
2613
2614         glyph->linearHoriAdvance = advanceX;
2615         glyph->linearVertAdvance = advanceY;
2616
2617         glyph->metrics.horiAdvance = FT_MulFix( advanceX, x_scale );
2618         glyph->metrics.vertAdvance = FT_MulFix( advanceY, y_scale );
2619
2620         return error;
2621       }
2622
2623       FT_TRACE3(( "Failed to load SVG glyph\n" ));
2624     }
2625
2626     /* return immediately if we only want SVG glyphs */
2627     if ( load_flags & FT_LOAD_SVG_ONLY )
2628     {
2629       error = FT_THROW( Invalid_Argument );
2630       goto Exit;
2631     }
2632
2633 #endif /* FT_CONFIG_OPTION_SVG */
2634
2635     error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
2636     if ( error )
2637       goto Exit;
2638
2639     /* done if we are only interested in the `hdmx` advance */
2640     if ( load_flags & FT_LOAD_ADVANCE_ONLY         &&
2641          !( load_flags & FT_LOAD_VERTICAL_LAYOUT ) &&
2642          loader.widthp                             )
2643     {
2644       glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64;
2645       goto Done;
2646     }
2647
2648     glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
2649     glyph->num_subglyphs = 0;
2650     glyph->outline.flags = 0;
2651
2652     /* main loading loop */
2653     error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
2654     if ( !error )
2655     {
2656       if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
2657       {
2658         glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
2659         glyph->subglyphs     = loader.gloader->base.subglyphs;
2660       }
2661       else
2662       {
2663         glyph->outline        = loader.gloader->base.outline;
2664         glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
2665
2666         /* Translate array so that (0,0) is the glyph's origin.  Note  */
2667         /* that this behaviour is independent on the value of bit 1 of */
2668         /* the `flags' field in the `head' table -- at least major     */
2669         /* applications like Acroread indicate that.                   */
2670         if ( loader.pp1.x )
2671           FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
2672       }
2673
2674 #ifdef TT_USE_BYTECODE_INTERPRETER
2675
2676       if ( IS_HINTED( load_flags ) )
2677       {
2678         glyph->control_data = loader.exec->glyphIns;
2679         glyph->control_len  = loader.exec->glyphSize;
2680
2681         if ( loader.exec->GS.scan_control )
2682         {
2683           /* convert scan conversion mode to FT_OUTLINE_XXX flags */
2684           switch ( loader.exec->GS.scan_type )
2685           {
2686           case 0: /* simple drop-outs including stubs */
2687             glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
2688             break;
2689           case 1: /* simple drop-outs excluding stubs */
2690             /* nothing; it's the default rendering mode */
2691             break;
2692           case 4: /* smart drop-outs including stubs */
2693             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
2694                                     FT_OUTLINE_INCLUDE_STUBS;
2695             break;
2696           case 5: /* smart drop-outs excluding stubs  */
2697             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
2698             break;
2699
2700           default: /* no drop-out control */
2701             glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2702             break;
2703           }
2704         }
2705         else
2706           glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2707       }
2708
2709 #endif /* TT_USE_BYTECODE_INTERPRETER */
2710
2711       error = compute_glyph_metrics( &loader, glyph_index );
2712     }
2713
2714     /* Set the `high precision' bit flag.                           */
2715     /* This is _critical_ to get correct output for monochrome      */
2716     /* TrueType glyphs at all sizes using the bytecode interpreter. */
2717     /*                                                              */
2718     if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
2719          size->metrics->y_ppem < 24         )
2720       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
2721
2722     FT_TRACE1(( "  subglyphs = %u, contours = %hd, points = %hd,"
2723                 " flags = 0x%.3x\n",
2724                 loader.gloader->base.num_subglyphs,
2725                 glyph->outline.n_contours,
2726                 glyph->outline.n_points,
2727                 glyph->outline.flags ));
2728
2729   Done:
2730     tt_loader_done( &loader );
2731
2732   Exit:
2733 #ifdef FT_DEBUG_LEVEL_TRACE
2734     if ( error )
2735       FT_TRACE1(( "  failed (error code 0x%x)\n",
2736                   error ));
2737 #endif
2738
2739     return error;
2740   }
2741
2742
2743 /* END */