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