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