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