tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ttgload.c (80881B)


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