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