Home | History | Annotate | Download | only in cff
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  cffgload.c                                                             */
      4 /*                                                                         */
      5 /*    OpenType Glyph Loader (body).                                        */
      6 /*                                                                         */
      7 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
      8 /*            2010 by                                                      */
      9 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
     10 /*                                                                         */
     11 /*  This file is part of the FreeType project, and may only be used,       */
     12 /*  modified, and distributed under the terms of the FreeType project      */
     13 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     14 /*  this file you indicate that you have read the license and              */
     15 /*  understand and accept it fully.                                        */
     16 /*                                                                         */
     17 /***************************************************************************/
     18 
     19 
     20 #include <ft2build.h>
     21 #include FT_INTERNAL_DEBUG_H
     22 #include FT_INTERNAL_STREAM_H
     23 #include FT_INTERNAL_SFNT_H
     24 #include FT_OUTLINE_H
     25 
     26 #include "cffobjs.h"
     27 #include "cffload.h"
     28 #include "cffgload.h"
     29 
     30 #include "cfferrs.h"
     31 
     32 
     33   /*************************************************************************/
     34   /*                                                                       */
     35   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     36   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     37   /* messages during execution.                                            */
     38   /*                                                                       */
     39 #undef  FT_COMPONENT
     40 #define FT_COMPONENT  trace_cffgload
     41 
     42 
     43   typedef enum  CFF_Operator_
     44   {
     45     cff_op_unknown = 0,
     46 
     47     cff_op_rmoveto,
     48     cff_op_hmoveto,
     49     cff_op_vmoveto,
     50 
     51     cff_op_rlineto,
     52     cff_op_hlineto,
     53     cff_op_vlineto,
     54 
     55     cff_op_rrcurveto,
     56     cff_op_hhcurveto,
     57     cff_op_hvcurveto,
     58     cff_op_rcurveline,
     59     cff_op_rlinecurve,
     60     cff_op_vhcurveto,
     61     cff_op_vvcurveto,
     62 
     63     cff_op_flex,
     64     cff_op_hflex,
     65     cff_op_hflex1,
     66     cff_op_flex1,
     67 
     68     cff_op_endchar,
     69 
     70     cff_op_hstem,
     71     cff_op_vstem,
     72     cff_op_hstemhm,
     73     cff_op_vstemhm,
     74 
     75     cff_op_hintmask,
     76     cff_op_cntrmask,
     77     cff_op_dotsection,  /* deprecated, acts as no-op */
     78 
     79     cff_op_abs,
     80     cff_op_add,
     81     cff_op_sub,
     82     cff_op_div,
     83     cff_op_neg,
     84     cff_op_random,
     85     cff_op_mul,
     86     cff_op_sqrt,
     87 
     88     cff_op_blend,
     89 
     90     cff_op_drop,
     91     cff_op_exch,
     92     cff_op_index,
     93     cff_op_roll,
     94     cff_op_dup,
     95 
     96     cff_op_put,
     97     cff_op_get,
     98     cff_op_store,
     99     cff_op_load,
    100 
    101     cff_op_and,
    102     cff_op_or,
    103     cff_op_not,
    104     cff_op_eq,
    105     cff_op_ifelse,
    106 
    107     cff_op_callsubr,
    108     cff_op_callgsubr,
    109     cff_op_return,
    110 
    111     /* Type 1 opcodes: invalid but seen in real life */
    112     cff_op_hsbw,
    113     cff_op_closepath,
    114     cff_op_callothersubr,
    115     cff_op_pop,
    116     cff_op_seac,
    117     cff_op_sbw,
    118     cff_op_setcurrentpoint,
    119 
    120     /* do not remove */
    121     cff_op_max
    122 
    123   } CFF_Operator;
    124 
    125 
    126 #define CFF_COUNT_CHECK_WIDTH  0x80
    127 #define CFF_COUNT_EXACT        0x40
    128 #define CFF_COUNT_CLEAR_STACK  0x20
    129 
    130   /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are  */
    131   /* used for checking the width and requested numbers of arguments    */
    132   /* only; they are set to zero afterwards                             */
    133 
    134   /* the other two flags are informative only and unused currently     */
    135 
    136   static const FT_Byte  cff_argument_counts[] =
    137   {
    138     0,  /* unknown */
    139 
    140     2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
    141     1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
    142     1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
    143 
    144     0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
    145     0 | CFF_COUNT_CLEAR_STACK,
    146     0 | CFF_COUNT_CLEAR_STACK,
    147 
    148     0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
    149     0 | CFF_COUNT_CLEAR_STACK,
    150     0 | CFF_COUNT_CLEAR_STACK,
    151     0 | CFF_COUNT_CLEAR_STACK,
    152     0 | CFF_COUNT_CLEAR_STACK,
    153     0 | CFF_COUNT_CLEAR_STACK,
    154     0 | CFF_COUNT_CLEAR_STACK,
    155 
    156     13, /* flex */
    157     7,
    158     9,
    159     11,
    160 
    161     0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
    162 
    163     2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
    164     2 | CFF_COUNT_CHECK_WIDTH,
    165     2 | CFF_COUNT_CHECK_WIDTH,
    166     2 | CFF_COUNT_CHECK_WIDTH,
    167 
    168     0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
    169     0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
    170     0, /* dotsection */
    171 
    172     1, /* abs */
    173     2,
    174     2,
    175     2,
    176     1,
    177     0,
    178     2,
    179     1,
    180 
    181     1, /* blend */
    182 
    183     1, /* drop */
    184     2,
    185     1,
    186     2,
    187     1,
    188 
    189     2, /* put */
    190     1,
    191     4,
    192     3,
    193 
    194     2, /* and */
    195     2,
    196     1,
    197     2,
    198     4,
    199 
    200     1, /* callsubr */
    201     1,
    202     0,
    203 
    204     2, /* hsbw */
    205     0,
    206     0,
    207     0,
    208     5, /* seac */
    209     4, /* sbw */
    210     2  /* setcurrentpoint */
    211   };
    212 
    213 
    214   /*************************************************************************/
    215   /*************************************************************************/
    216   /*************************************************************************/
    217   /**********                                                      *********/
    218   /**********                                                      *********/
    219   /**********             GENERIC CHARSTRING PARSING               *********/
    220   /**********                                                      *********/
    221   /**********                                                      *********/
    222   /*************************************************************************/
    223   /*************************************************************************/
    224   /*************************************************************************/
    225 
    226 
    227   /*************************************************************************/
    228   /*                                                                       */
    229   /* <Function>                                                            */
    230   /*    cff_builder_init                                                   */
    231   /*                                                                       */
    232   /* <Description>                                                         */
    233   /*    Initializes a given glyph builder.                                 */
    234   /*                                                                       */
    235   /* <InOut>                                                               */
    236   /*    builder :: A pointer to the glyph builder to initialize.           */
    237   /*                                                                       */
    238   /* <Input>                                                               */
    239   /*    face    :: The current face object.                                */
    240   /*                                                                       */
    241   /*    size    :: The current size object.                                */
    242   /*                                                                       */
    243   /*    glyph   :: The current glyph object.                               */
    244   /*                                                                       */
    245   /*    hinting :: Whether hinting is active.                              */
    246   /*                                                                       */
    247   static void
    248   cff_builder_init( CFF_Builder*   builder,
    249                     TT_Face        face,
    250                     CFF_Size       size,
    251                     CFF_GlyphSlot  glyph,
    252                     FT_Bool        hinting )
    253   {
    254     builder->path_begun  = 0;
    255     builder->load_points = 1;
    256 
    257     builder->face   = face;
    258     builder->glyph  = glyph;
    259     builder->memory = face->root.memory;
    260 
    261     if ( glyph )
    262     {
    263       FT_GlyphLoader  loader = glyph->root.internal->loader;
    264 
    265 
    266       builder->loader  = loader;
    267       builder->base    = &loader->base.outline;
    268       builder->current = &loader->current.outline;
    269       FT_GlyphLoader_Rewind( loader );
    270 
    271       builder->hints_globals = 0;
    272       builder->hints_funcs   = 0;
    273 
    274       if ( hinting && size )
    275       {
    276         CFF_Internal  internal = (CFF_Internal)size->root.internal;
    277 
    278 
    279         builder->hints_globals = (void *)internal->topfont;
    280         builder->hints_funcs   = glyph->root.internal->glyph_hints;
    281       }
    282     }
    283 
    284     builder->pos_x = 0;
    285     builder->pos_y = 0;
    286 
    287     builder->left_bearing.x = 0;
    288     builder->left_bearing.y = 0;
    289     builder->advance.x      = 0;
    290     builder->advance.y      = 0;
    291   }
    292 
    293 
    294   /*************************************************************************/
    295   /*                                                                       */
    296   /* <Function>                                                            */
    297   /*    cff_builder_done                                                   */
    298   /*                                                                       */
    299   /* <Description>                                                         */
    300   /*    Finalizes a given glyph builder.  Its contents can still be used   */
    301   /*    after the call, but the function saves important information       */
    302   /*    within the corresponding glyph slot.                               */
    303   /*                                                                       */
    304   /* <Input>                                                               */
    305   /*    builder :: A pointer to the glyph builder to finalize.             */
    306   /*                                                                       */
    307   static void
    308   cff_builder_done( CFF_Builder*  builder )
    309   {
    310     CFF_GlyphSlot  glyph = builder->glyph;
    311 
    312 
    313     if ( glyph )
    314       glyph->root.outline = *builder->base;
    315   }
    316 
    317 
    318   /*************************************************************************/
    319   /*                                                                       */
    320   /* <Function>                                                            */
    321   /*    cff_compute_bias                                                   */
    322   /*                                                                       */
    323   /* <Description>                                                         */
    324   /*    Computes the bias value in dependence of the number of glyph       */
    325   /*    subroutines.                                                       */
    326   /*                                                                       */
    327   /* <Input>                                                               */
    328   /*    in_charstring_type :: The `CharstringType' value of the top DICT   */
    329   /*                          dictionary.                                  */
    330   /*                                                                       */
    331   /*    num_subrs          :: The number of glyph subroutines.             */
    332   /*                                                                       */
    333   /* <Return>                                                              */
    334   /*    The bias value.                                                    */
    335   static FT_Int
    336   cff_compute_bias( FT_Int   in_charstring_type,
    337                     FT_UInt  num_subrs )
    338   {
    339     FT_Int  result;
    340 
    341 
    342     if ( in_charstring_type == 1 )
    343       result = 0;
    344     else if ( num_subrs < 1240 )
    345       result = 107;
    346     else if ( num_subrs < 33900U )
    347       result = 1131;
    348     else
    349       result = 32768U;
    350 
    351     return result;
    352   }
    353 
    354 
    355   /*************************************************************************/
    356   /*                                                                       */
    357   /* <Function>                                                            */
    358   /*    cff_decoder_init                                                   */
    359   /*                                                                       */
    360   /* <Description>                                                         */
    361   /*    Initializes a given glyph decoder.                                 */
    362   /*                                                                       */
    363   /* <InOut>                                                               */
    364   /*    decoder :: A pointer to the glyph builder to initialize.           */
    365   /*                                                                       */
    366   /* <Input>                                                               */
    367   /*    face      :: The current face object.                              */
    368   /*                                                                       */
    369   /*    size      :: The current size object.                              */
    370   /*                                                                       */
    371   /*    slot      :: The current glyph object.                             */
    372   /*                                                                       */
    373   /*    hinting   :: Whether hinting is active.                            */
    374   /*                                                                       */
    375   /*    hint_mode :: The hinting mode.                                     */
    376   /*                                                                       */
    377   FT_LOCAL_DEF( void )
    378   cff_decoder_init( CFF_Decoder*    decoder,
    379                     TT_Face         face,
    380                     CFF_Size        size,
    381                     CFF_GlyphSlot   slot,
    382                     FT_Bool         hinting,
    383                     FT_Render_Mode  hint_mode )
    384   {
    385     CFF_Font  cff = (CFF_Font)face->extra.data;
    386 
    387 
    388     /* clear everything */
    389     FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
    390 
    391     /* initialize builder */
    392     cff_builder_init( &decoder->builder, face, size, slot, hinting );
    393 
    394     /* initialize Type2 decoder */
    395     decoder->cff          = cff;
    396     decoder->num_globals  = cff->global_subrs_index.count;
    397     decoder->globals      = cff->global_subrs;
    398     decoder->globals_bias = cff_compute_bias(
    399                               cff->top_font.font_dict.charstring_type,
    400                               decoder->num_globals );
    401 
    402     decoder->hint_mode    = hint_mode;
    403   }
    404 
    405 
    406   /* this function is used to select the subfont */
    407   /* and the locals subrs array                  */
    408   FT_LOCAL_DEF( FT_Error )
    409   cff_decoder_prepare( CFF_Decoder*  decoder,
    410                        CFF_Size      size,
    411                        FT_UInt       glyph_index )
    412   {
    413     CFF_Builder  *builder = &decoder->builder;
    414     CFF_Font      cff     = (CFF_Font)builder->face->extra.data;
    415     CFF_SubFont   sub     = &cff->top_font;
    416     FT_Error      error   = CFF_Err_Ok;
    417 
    418 
    419     /* manage CID fonts */
    420     if ( cff->num_subfonts )
    421     {
    422       FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
    423 
    424 
    425       if ( fd_index >= cff->num_subfonts )
    426       {
    427         FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
    428         error = CFF_Err_Invalid_File_Format;
    429         goto Exit;
    430       }
    431 
    432       FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index ));
    433 
    434       sub = cff->subfonts[fd_index];
    435 
    436       if ( builder->hints_funcs && size )
    437       {
    438         CFF_Internal  internal = (CFF_Internal)size->root.internal;
    439 
    440 
    441         /* for CFFs without subfonts, this value has already been set */
    442         builder->hints_globals = (void *)internal->subfonts[fd_index];
    443       }
    444     }
    445 #ifdef FT_DEBUG_LEVEL_TRACE
    446     else
    447       FT_TRACE3(( "glyph index %d:\n", glyph_index ));
    448 #endif
    449 
    450     decoder->num_locals    = sub->local_subrs_index.count;
    451     decoder->locals        = sub->local_subrs;
    452     decoder->locals_bias   = cff_compute_bias(
    453                                decoder->cff->top_font.font_dict.charstring_type,
    454                                decoder->num_locals );
    455 
    456     decoder->glyph_width   = sub->private_dict.default_width;
    457     decoder->nominal_width = sub->private_dict.nominal_width;
    458 
    459   Exit:
    460     return error;
    461   }
    462 
    463 
    464   /* check that there is enough space for `count' more points */
    465   static FT_Error
    466   check_points( CFF_Builder*  builder,
    467                 FT_Int        count )
    468   {
    469     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
    470   }
    471 
    472 
    473   /* add a new point, do not check space */
    474   static void
    475   cff_builder_add_point( CFF_Builder*  builder,
    476                          FT_Pos        x,
    477                          FT_Pos        y,
    478                          FT_Byte       flag )
    479   {
    480     FT_Outline*  outline = builder->current;
    481 
    482 
    483     if ( builder->load_points )
    484     {
    485       FT_Vector*  point   = outline->points + outline->n_points;
    486       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
    487 
    488 
    489       point->x = x >> 16;
    490       point->y = y >> 16;
    491       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
    492     }
    493 
    494     outline->n_points++;
    495   }
    496 
    497 
    498   /* check space for a new on-curve point, then add it */
    499   static FT_Error
    500   cff_builder_add_point1( CFF_Builder*  builder,
    501                           FT_Pos        x,
    502                           FT_Pos        y )
    503   {
    504     FT_Error  error;
    505 
    506 
    507     error = check_points( builder, 1 );
    508     if ( !error )
    509       cff_builder_add_point( builder, x, y, 1 );
    510 
    511     return error;
    512   }
    513 
    514 
    515   /* check space for a new contour, then add it */
    516   static FT_Error
    517   cff_builder_add_contour( CFF_Builder*  builder )
    518   {
    519     FT_Outline*  outline = builder->current;
    520     FT_Error     error;
    521 
    522 
    523     if ( !builder->load_points )
    524     {
    525       outline->n_contours++;
    526       return CFF_Err_Ok;
    527     }
    528 
    529     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
    530     if ( !error )
    531     {
    532       if ( outline->n_contours > 0 )
    533         outline->contours[outline->n_contours - 1] =
    534           (short)( outline->n_points - 1 );
    535 
    536       outline->n_contours++;
    537     }
    538 
    539     return error;
    540   }
    541 
    542 
    543   /* if a path was begun, add its first on-curve point */
    544   static FT_Error
    545   cff_builder_start_point( CFF_Builder*  builder,
    546                            FT_Pos        x,
    547                            FT_Pos        y )
    548   {
    549     FT_Error  error = CFF_Err_Ok;
    550 
    551 
    552     /* test whether we are building a new contour */
    553     if ( !builder->path_begun )
    554     {
    555       builder->path_begun = 1;
    556       error = cff_builder_add_contour( builder );
    557       if ( !error )
    558         error = cff_builder_add_point1( builder, x, y );
    559     }
    560 
    561     return error;
    562   }
    563 
    564 
    565   /* close the current contour */
    566   static void
    567   cff_builder_close_contour( CFF_Builder*  builder )
    568   {
    569     FT_Outline*  outline = builder->current;
    570     FT_Int       first;
    571 
    572 
    573     if ( !outline )
    574       return;
    575 
    576     first = outline->n_contours <= 1
    577             ? 0 : outline->contours[outline->n_contours - 2] + 1;
    578 
    579     /* We must not include the last point in the path if it */
    580     /* is located on the first point.                       */
    581     if ( outline->n_points > 1 )
    582     {
    583       FT_Vector*  p1      = outline->points + first;
    584       FT_Vector*  p2      = outline->points + outline->n_points - 1;
    585       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
    586 
    587 
    588       /* `delete' last point only if it coincides with the first    */
    589       /* point and if it is not a control point (which can happen). */
    590       if ( p1->x == p2->x && p1->y == p2->y )
    591         if ( *control == FT_CURVE_TAG_ON )
    592           outline->n_points--;
    593     }
    594 
    595     if ( outline->n_contours > 0 )
    596     {
    597       /* Don't add contours only consisting of one point, i.e., */
    598       /* check whether begin point and last point are the same. */
    599       if ( first == outline->n_points - 1 )
    600       {
    601         outline->n_contours--;
    602         outline->n_points--;
    603       }
    604       else
    605         outline->contours[outline->n_contours - 1] =
    606           (short)( outline->n_points - 1 );
    607     }
    608   }
    609 
    610 
    611   static FT_Int
    612   cff_lookup_glyph_by_stdcharcode( CFF_Font  cff,
    613                                    FT_Int    charcode )
    614   {
    615     FT_UInt    n;
    616     FT_UShort  glyph_sid;
    617 
    618 
    619     /* CID-keyed fonts don't have glyph names */
    620     if ( !cff->charset.sids )
    621       return -1;
    622 
    623     /* check range of standard char code */
    624     if ( charcode < 0 || charcode > 255 )
    625       return -1;
    626 
    627     /* Get code to SID mapping from `cff_standard_encoding'. */
    628     glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
    629 
    630     for ( n = 0; n < cff->num_glyphs; n++ )
    631     {
    632       if ( cff->charset.sids[n] == glyph_sid )
    633         return n;
    634     }
    635 
    636     return -1;
    637   }
    638 
    639 
    640   static FT_Error
    641   cff_get_glyph_data( TT_Face    face,
    642                       FT_UInt    glyph_index,
    643                       FT_Byte**  pointer,
    644                       FT_ULong*  length )
    645   {
    646 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    647     /* For incremental fonts get the character data using the */
    648     /* callback function.                                     */
    649     if ( face->root.internal->incremental_interface )
    650     {
    651       FT_Data   data;
    652       FT_Error  error =
    653                   face->root.internal->incremental_interface->funcs->get_glyph_data(
    654                     face->root.internal->incremental_interface->object,
    655                     glyph_index, &data );
    656 
    657 
    658       *pointer = (FT_Byte*)data.pointer;
    659       *length = data.length;
    660 
    661       return error;
    662     }
    663     else
    664 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
    665 
    666     {
    667       CFF_Font  cff  = (CFF_Font)(face->extra.data);
    668 
    669 
    670       return cff_index_access_element( &cff->charstrings_index, glyph_index,
    671                                        pointer, length );
    672     }
    673   }
    674 
    675 
    676   static void
    677   cff_free_glyph_data( TT_Face    face,
    678                        FT_Byte**  pointer,
    679                        FT_ULong   length )
    680   {
    681 #ifndef FT_CONFIG_OPTION_INCREMENTAL
    682     FT_UNUSED( length );
    683 #endif
    684 
    685 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    686     /* For incremental fonts get the character data using the */
    687     /* callback function.                                     */
    688     if ( face->root.internal->incremental_interface )
    689     {
    690       FT_Data data;
    691 
    692 
    693       data.pointer = *pointer;
    694       data.length  = length;
    695 
    696       face->root.internal->incremental_interface->funcs->free_glyph_data(
    697         face->root.internal->incremental_interface->object, &data );
    698     }
    699     else
    700 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
    701 
    702     {
    703       CFF_Font  cff = (CFF_Font)(face->extra.data);
    704 
    705 
    706       cff_index_forget_element( &cff->charstrings_index, pointer );
    707     }
    708   }
    709 
    710 
    711   static FT_Error
    712   cff_operator_seac( CFF_Decoder*  decoder,
    713                      FT_Pos        asb,
    714                      FT_Pos        adx,
    715                      FT_Pos        ady,
    716                      FT_Int        bchar,
    717                      FT_Int        achar )
    718   {
    719     FT_Error      error;
    720     CFF_Builder*  builder = &decoder->builder;
    721     FT_Int        bchar_index, achar_index;
    722     TT_Face       face = decoder->builder.face;
    723     FT_Vector     left_bearing, advance;
    724     FT_Byte*      charstring;
    725     FT_ULong      charstring_len;
    726     FT_Pos        glyph_width;
    727 
    728 
    729     if ( decoder->seac )
    730     {
    731       FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
    732       return CFF_Err_Syntax_Error;
    733     }
    734 
    735     adx += decoder->builder.left_bearing.x;
    736     ady += decoder->builder.left_bearing.y;
    737 
    738 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    739     /* Incremental fonts don't necessarily have valid charsets.        */
    740     /* They use the character code, not the glyph index, in this case. */
    741     if ( face->root.internal->incremental_interface )
    742     {
    743       bchar_index = bchar;
    744       achar_index = achar;
    745     }
    746     else
    747 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
    748     {
    749       CFF_Font cff = (CFF_Font)(face->extra.data);
    750 
    751 
    752       bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
    753       achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
    754     }
    755 
    756     if ( bchar_index < 0 || achar_index < 0 )
    757     {
    758       FT_ERROR(( "cff_operator_seac:"
    759                  " invalid seac character code arguments\n" ));
    760       return CFF_Err_Syntax_Error;
    761     }
    762 
    763     /* If we are trying to load a composite glyph, do not load the */
    764     /* accent character and return the array of subglyphs.         */
    765     if ( builder->no_recurse )
    766     {
    767       FT_GlyphSlot    glyph  = (FT_GlyphSlot)builder->glyph;
    768       FT_GlyphLoader  loader = glyph->internal->loader;
    769       FT_SubGlyph     subg;
    770 
    771 
    772       /* reallocate subglyph array if necessary */
    773       error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
    774       if ( error )
    775         goto Exit;
    776 
    777       subg = loader->current.subglyphs;
    778 
    779       /* subglyph 0 = base character */
    780       subg->index = bchar_index;
    781       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
    782                     FT_SUBGLYPH_FLAG_USE_MY_METRICS;
    783       subg->arg1  = 0;
    784       subg->arg2  = 0;
    785       subg++;
    786 
    787       /* subglyph 1 = accent character */
    788       subg->index = achar_index;
    789       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
    790       subg->arg1  = (FT_Int)( adx >> 16 );
    791       subg->arg2  = (FT_Int)( ady >> 16 );
    792 
    793       /* set up remaining glyph fields */
    794       glyph->num_subglyphs = 2;
    795       glyph->subglyphs     = loader->base.subglyphs;
    796       glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
    797 
    798       loader->current.num_subglyphs = 2;
    799     }
    800 
    801     FT_GlyphLoader_Prepare( builder->loader );
    802 
    803     /* First load `bchar' in builder */
    804     error = cff_get_glyph_data( face, bchar_index,
    805                                 &charstring, &charstring_len );
    806     if ( !error )
    807     {
    808       /* the seac operator must not be nested */
    809       decoder->seac = TRUE;
    810       error = cff_decoder_parse_charstrings( decoder, charstring,
    811                                              charstring_len );
    812       decoder->seac = FALSE;
    813 
    814       cff_free_glyph_data( face, &charstring, charstring_len );
    815 
    816       if ( error )
    817         goto Exit;
    818     }
    819 
    820     /* Save the left bearing, advance and glyph width of the base */
    821     /* character as they will be erased by the next load.         */
    822 
    823     left_bearing = builder->left_bearing;
    824     advance      = builder->advance;
    825     glyph_width  = decoder->glyph_width;
    826 
    827     builder->left_bearing.x = 0;
    828     builder->left_bearing.y = 0;
    829 
    830     builder->pos_x = adx - asb;
    831     builder->pos_y = ady;
    832 
    833     /* Now load `achar' on top of the base outline. */
    834     error = cff_get_glyph_data( face, achar_index,
    835                                 &charstring, &charstring_len );
    836     if ( !error )
    837     {
    838       /* the seac operator must not be nested */
    839       decoder->seac = TRUE;
    840       error = cff_decoder_parse_charstrings( decoder, charstring,
    841                                              charstring_len );
    842       decoder->seac = FALSE;
    843 
    844       cff_free_glyph_data( face, &charstring, charstring_len );
    845 
    846       if ( error )
    847         goto Exit;
    848     }
    849 
    850     /* Restore the left side bearing, advance and glyph width */
    851     /* of the base character.                                 */
    852     builder->left_bearing = left_bearing;
    853     builder->advance      = advance;
    854     decoder->glyph_width  = glyph_width;
    855 
    856     builder->pos_x = 0;
    857     builder->pos_y = 0;
    858 
    859   Exit:
    860     return error;
    861   }
    862 
    863 
    864   /*************************************************************************/
    865   /*                                                                       */
    866   /* <Function>                                                            */
    867   /*    cff_decoder_parse_charstrings                                      */
    868   /*                                                                       */
    869   /* <Description>                                                         */
    870   /*    Parses a given Type 2 charstrings program.                         */
    871   /*                                                                       */
    872   /* <InOut>                                                               */
    873   /*    decoder         :: The current Type 1 decoder.                     */
    874   /*                                                                       */
    875   /* <Input>                                                               */
    876   /*    charstring_base :: The base of the charstring stream.              */
    877   /*                                                                       */
    878   /*    charstring_len  :: The length in bytes of the charstring stream.   */
    879   /*                                                                       */
    880   /* <Return>                                                              */
    881   /*    FreeType error code.  0 means success.                             */
    882   /*                                                                       */
    883   FT_LOCAL_DEF( FT_Error )
    884   cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
    885                                  FT_Byte*      charstring_base,
    886                                  FT_ULong      charstring_len )
    887   {
    888     FT_Error           error;
    889     CFF_Decoder_Zone*  zone;
    890     FT_Byte*           ip;
    891     FT_Byte*           limit;
    892     CFF_Builder*       builder = &decoder->builder;
    893     FT_Pos             x, y;
    894     FT_Fixed           seed;
    895     FT_Fixed*          stack;
    896     FT_Int             charstring_type =
    897                          decoder->cff->top_font.font_dict.charstring_type;
    898 
    899     T2_Hints_Funcs     hinter;
    900 
    901 
    902     /* set default width */
    903     decoder->num_hints  = 0;
    904     decoder->read_width = 1;
    905 
    906     /* compute random seed from stack address of parameter */
    907     seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed              ^
    908                          (FT_PtrDist)(char*)&decoder           ^
    909                          (FT_PtrDist)(char*)&charstring_base ) &
    910                          FT_ULONG_MAX ) ;
    911     seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
    912     if ( seed == 0 )
    913       seed = 0x7384;
    914 
    915     /* initialize the decoder */
    916     decoder->top  = decoder->stack;
    917     decoder->zone = decoder->zones;
    918     zone          = decoder->zones;
    919     stack         = decoder->top;
    920 
    921     hinter = (T2_Hints_Funcs)builder->hints_funcs;
    922 
    923     builder->path_begun = 0;
    924 
    925     zone->base           = charstring_base;
    926     limit = zone->limit  = charstring_base + charstring_len;
    927     ip    = zone->cursor = zone->base;
    928 
    929     error = CFF_Err_Ok;
    930 
    931     x = builder->pos_x;
    932     y = builder->pos_y;
    933 
    934     /* begin hints recording session, if any */
    935     if ( hinter )
    936       hinter->open( hinter->hints );
    937 
    938     /* now execute loop */
    939     while ( ip < limit )
    940     {
    941       CFF_Operator  op;
    942       FT_Byte       v;
    943 
    944 
    945       /********************************************************************/
    946       /*                                                                  */
    947       /* Decode operator or operand                                       */
    948       /*                                                                  */
    949       v = *ip++;
    950       if ( v >= 32 || v == 28 )
    951       {
    952         FT_Int    shift = 16;
    953         FT_Int32  val;
    954 
    955 
    956         /* this is an operand, push it on the stack */
    957         if ( v == 28 )
    958         {
    959           if ( ip + 1 >= limit )
    960             goto Syntax_Error;
    961           val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
    962           ip += 2;
    963         }
    964         else if ( v < 247 )
    965           val = (FT_Int32)v - 139;
    966         else if ( v < 251 )
    967         {
    968           if ( ip >= limit )
    969             goto Syntax_Error;
    970           val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108;
    971         }
    972         else if ( v < 255 )
    973         {
    974           if ( ip >= limit )
    975             goto Syntax_Error;
    976           val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108;
    977         }
    978         else
    979         {
    980           if ( ip + 3 >= limit )
    981             goto Syntax_Error;
    982           val = ( (FT_Int32)ip[0] << 24 ) |
    983                 ( (FT_Int32)ip[1] << 16 ) |
    984                 ( (FT_Int32)ip[2] <<  8 ) |
    985                             ip[3];
    986           ip    += 4;
    987           if ( charstring_type == 2 )
    988             shift = 0;
    989         }
    990         if ( decoder->top - stack >= CFF_MAX_OPERANDS )
    991           goto Stack_Overflow;
    992 
    993         val           <<= shift;
    994         *decoder->top++ = val;
    995 
    996 #ifdef FT_DEBUG_LEVEL_TRACE
    997         if ( !( val & 0xFFFFL ) )
    998           FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) ));
    999         else
   1000           FT_TRACE4(( " %.2f", val / 65536.0 ));
   1001 #endif
   1002 
   1003       }
   1004       else
   1005       {
   1006         /* The specification says that normally arguments are to be taken */
   1007         /* from the bottom of the stack.  However, this seems not to be   */
   1008         /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
   1009         /* arguments similar to a PS interpreter.                         */
   1010 
   1011         FT_Fixed*  args     = decoder->top;
   1012         FT_Int     num_args = (FT_Int)( args - decoder->stack );
   1013         FT_Int     req_args;
   1014 
   1015 
   1016         /* find operator */
   1017         op = cff_op_unknown;
   1018 
   1019         switch ( v )
   1020         {
   1021         case 1:
   1022           op = cff_op_hstem;
   1023           break;
   1024         case 3:
   1025           op = cff_op_vstem;
   1026           break;
   1027         case 4:
   1028           op = cff_op_vmoveto;
   1029           break;
   1030         case 5:
   1031           op = cff_op_rlineto;
   1032           break;
   1033         case 6:
   1034           op = cff_op_hlineto;
   1035           break;
   1036         case 7:
   1037           op = cff_op_vlineto;
   1038           break;
   1039         case 8:
   1040           op = cff_op_rrcurveto;
   1041           break;
   1042         case 9:
   1043           op = cff_op_closepath;
   1044           break;
   1045         case 10:
   1046           op = cff_op_callsubr;
   1047           break;
   1048         case 11:
   1049           op = cff_op_return;
   1050           break;
   1051         case 12:
   1052           {
   1053             if ( ip >= limit )
   1054               goto Syntax_Error;
   1055             v = *ip++;
   1056 
   1057             switch ( v )
   1058             {
   1059             case 0:
   1060               op = cff_op_dotsection;
   1061               break;
   1062             case 1: /* this is actually the Type1 vstem3 operator */
   1063               op = cff_op_vstem;
   1064               break;
   1065             case 2: /* this is actually the Type1 hstem3 operator */
   1066               op = cff_op_hstem;
   1067               break;
   1068             case 3:
   1069               op = cff_op_and;
   1070               break;
   1071             case 4:
   1072               op = cff_op_or;
   1073               break;
   1074             case 5:
   1075               op = cff_op_not;
   1076               break;
   1077             case 6:
   1078               op = cff_op_seac;
   1079               break;
   1080             case 7:
   1081               op = cff_op_sbw;
   1082               break;
   1083             case 8:
   1084               op = cff_op_store;
   1085               break;
   1086             case 9:
   1087               op = cff_op_abs;
   1088               break;
   1089             case 10:
   1090               op = cff_op_add;
   1091               break;
   1092             case 11:
   1093               op = cff_op_sub;
   1094               break;
   1095             case 12:
   1096               op = cff_op_div;
   1097               break;
   1098             case 13:
   1099               op = cff_op_load;
   1100               break;
   1101             case 14:
   1102               op = cff_op_neg;
   1103               break;
   1104             case 15:
   1105               op = cff_op_eq;
   1106               break;
   1107             case 16:
   1108               op = cff_op_callothersubr;
   1109               break;
   1110             case 17:
   1111               op = cff_op_pop;
   1112               break;
   1113             case 18:
   1114               op = cff_op_drop;
   1115               break;
   1116             case 20:
   1117               op = cff_op_put;
   1118               break;
   1119             case 21:
   1120               op = cff_op_get;
   1121               break;
   1122             case 22:
   1123               op = cff_op_ifelse;
   1124               break;
   1125             case 23:
   1126               op = cff_op_random;
   1127               break;
   1128             case 24:
   1129               op = cff_op_mul;
   1130               break;
   1131             case 26:
   1132               op = cff_op_sqrt;
   1133               break;
   1134             case 27:
   1135               op = cff_op_dup;
   1136               break;
   1137             case 28:
   1138               op = cff_op_exch;
   1139               break;
   1140             case 29:
   1141               op = cff_op_index;
   1142               break;
   1143             case 30:
   1144               op = cff_op_roll;
   1145               break;
   1146             case 33:
   1147               op = cff_op_setcurrentpoint;
   1148               break;
   1149             case 34:
   1150               op = cff_op_hflex;
   1151               break;
   1152             case 35:
   1153               op = cff_op_flex;
   1154               break;
   1155             case 36:
   1156               op = cff_op_hflex1;
   1157               break;
   1158             case 37:
   1159               op = cff_op_flex1;
   1160               break;
   1161             default:
   1162               /* decrement ip for syntax error message */
   1163               ip--;
   1164             }
   1165           }
   1166           break;
   1167         case 13:
   1168           op = cff_op_hsbw;
   1169           break;
   1170         case 14:
   1171           op = cff_op_endchar;
   1172           break;
   1173         case 16:
   1174           op = cff_op_blend;
   1175           break;
   1176         case 18:
   1177           op = cff_op_hstemhm;
   1178           break;
   1179         case 19:
   1180           op = cff_op_hintmask;
   1181           break;
   1182         case 20:
   1183           op = cff_op_cntrmask;
   1184           break;
   1185         case 21:
   1186           op = cff_op_rmoveto;
   1187           break;
   1188         case 22:
   1189           op = cff_op_hmoveto;
   1190           break;
   1191         case 23:
   1192           op = cff_op_vstemhm;
   1193           break;
   1194         case 24:
   1195           op = cff_op_rcurveline;
   1196           break;
   1197         case 25:
   1198           op = cff_op_rlinecurve;
   1199           break;
   1200         case 26:
   1201           op = cff_op_vvcurveto;
   1202           break;
   1203         case 27:
   1204           op = cff_op_hhcurveto;
   1205           break;
   1206         case 29:
   1207           op = cff_op_callgsubr;
   1208           break;
   1209         case 30:
   1210           op = cff_op_vhcurveto;
   1211           break;
   1212         case 31:
   1213           op = cff_op_hvcurveto;
   1214           break;
   1215         default:
   1216           break;
   1217         }
   1218 
   1219         if ( op == cff_op_unknown )
   1220           goto Syntax_Error;
   1221 
   1222         /* check arguments */
   1223         req_args = cff_argument_counts[op];
   1224         if ( req_args & CFF_COUNT_CHECK_WIDTH )
   1225         {
   1226           if ( num_args > 0 && decoder->read_width )
   1227           {
   1228             /* If `nominal_width' is non-zero, the number is really a      */
   1229             /* difference against `nominal_width'.  Else, the number here  */
   1230             /* is truly a width, not a difference against `nominal_width'. */
   1231             /* If the font does not set `nominal_width', then              */
   1232             /* `nominal_width' defaults to zero, and so we can set         */
   1233             /* `glyph_width' to `nominal_width' plus number on the stack   */
   1234             /* -- for either case.                                         */
   1235 
   1236             FT_Int  set_width_ok;
   1237 
   1238 
   1239             switch ( op )
   1240             {
   1241             case cff_op_hmoveto:
   1242             case cff_op_vmoveto:
   1243               set_width_ok = num_args & 2;
   1244               break;
   1245 
   1246             case cff_op_hstem:
   1247             case cff_op_vstem:
   1248             case cff_op_hstemhm:
   1249             case cff_op_vstemhm:
   1250             case cff_op_rmoveto:
   1251             case cff_op_hintmask:
   1252             case cff_op_cntrmask:
   1253               set_width_ok = num_args & 1;
   1254               break;
   1255 
   1256             case cff_op_endchar:
   1257               /* If there is a width specified for endchar, we either have */
   1258               /* 1 argument or 5 arguments.  We like to argue.             */
   1259               set_width_ok = ( num_args == 5 ) || ( num_args == 1 );
   1260               break;
   1261 
   1262             default:
   1263               set_width_ok = 0;
   1264               break;
   1265             }
   1266 
   1267             if ( set_width_ok )
   1268             {
   1269               decoder->glyph_width = decoder->nominal_width +
   1270                                        ( stack[0] >> 16 );
   1271 
   1272               if ( decoder->width_only )
   1273               {
   1274                 /* we only want the advance width; stop here */
   1275                 break;
   1276               }
   1277 
   1278               /* Consumed an argument. */
   1279               num_args--;
   1280             }
   1281           }
   1282 
   1283           decoder->read_width = 0;
   1284           req_args            = 0;
   1285         }
   1286 
   1287         req_args &= 0x000F;
   1288         if ( num_args < req_args )
   1289           goto Stack_Underflow;
   1290         args     -= req_args;
   1291         num_args -= req_args;
   1292 
   1293         /* At this point, `args' points to the first argument of the  */
   1294         /* operand in case `req_args' isn't zero.  Otherwise, we have */
   1295         /* to adjust `args' manually.                                 */
   1296 
   1297         /* Note that we only pop arguments from the stack which we    */
   1298         /* really need and can digest so that we can continue in case */
   1299         /* of superfluous stack elements.                             */
   1300 
   1301         switch ( op )
   1302         {
   1303         case cff_op_hstem:
   1304         case cff_op_vstem:
   1305         case cff_op_hstemhm:
   1306         case cff_op_vstemhm:
   1307           /* the number of arguments is always even here */
   1308           FT_TRACE4((
   1309               op == cff_op_hstem   ? " hstem\n"   :
   1310             ( op == cff_op_vstem   ? " vstem\n"   :
   1311             ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) ));
   1312 
   1313           if ( hinter )
   1314             hinter->stems( hinter->hints,
   1315                            ( op == cff_op_hstem || op == cff_op_hstemhm ),
   1316                            num_args / 2,
   1317                            args - ( num_args & ~1 ) );
   1318 
   1319           decoder->num_hints += num_args / 2;
   1320           args = stack;
   1321           break;
   1322 
   1323         case cff_op_hintmask:
   1324         case cff_op_cntrmask:
   1325           FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
   1326 
   1327           /* implement vstem when needed --                        */
   1328           /* the specification doesn't say it, but this also works */
   1329           /* with the 'cntrmask' operator                          */
   1330           /*                                                       */
   1331           if ( num_args > 0 )
   1332           {
   1333             if ( hinter )
   1334               hinter->stems( hinter->hints,
   1335                              0,
   1336                              num_args / 2,
   1337                              args - ( num_args & ~1 ) );
   1338 
   1339             decoder->num_hints += num_args / 2;
   1340           }
   1341 
   1342           /* In a valid charstring there must be at least one byte */
   1343           /* after `hintmask' or `cntrmask' (e.g., for a `return'  */
   1344           /* instruction).  Additionally, there must be space for  */
   1345           /* `num_hints' bits.                                     */
   1346 
   1347           if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit )
   1348             goto Syntax_Error;
   1349 
   1350           if ( hinter )
   1351           {
   1352             if ( op == cff_op_hintmask )
   1353               hinter->hintmask( hinter->hints,
   1354                                 builder->current->n_points,
   1355                                 decoder->num_hints,
   1356                                 ip );
   1357             else
   1358               hinter->counter( hinter->hints,
   1359                                decoder->num_hints,
   1360                                ip );
   1361           }
   1362 
   1363 #ifdef FT_DEBUG_LEVEL_TRACE
   1364           {
   1365             FT_UInt maskbyte;
   1366 
   1367 
   1368             FT_TRACE4(( " (maskbytes:" ));
   1369 
   1370             for ( maskbyte = 0;
   1371                   maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 );
   1372                   maskbyte++, ip++ )
   1373               FT_TRACE4(( " 0x%02X", *ip ));
   1374 
   1375             FT_TRACE4(( ")\n" ));
   1376           }
   1377 #else
   1378           ip += ( decoder->num_hints + 7 ) >> 3;
   1379 #endif
   1380           args = stack;
   1381           break;
   1382 
   1383         case cff_op_rmoveto:
   1384           FT_TRACE4(( " rmoveto\n" ));
   1385 
   1386           cff_builder_close_contour( builder );
   1387           builder->path_begun = 0;
   1388           x   += args[-2];
   1389           y   += args[-1];
   1390           args = stack;
   1391           break;
   1392 
   1393         case cff_op_vmoveto:
   1394           FT_TRACE4(( " vmoveto\n" ));
   1395 
   1396           cff_builder_close_contour( builder );
   1397           builder->path_begun = 0;
   1398           y   += args[-1];
   1399           args = stack;
   1400           break;
   1401 
   1402         case cff_op_hmoveto:
   1403           FT_TRACE4(( " hmoveto\n" ));
   1404 
   1405           cff_builder_close_contour( builder );
   1406           builder->path_begun = 0;
   1407           x   += args[-1];
   1408           args = stack;
   1409           break;
   1410 
   1411         case cff_op_rlineto:
   1412           FT_TRACE4(( " rlineto\n" ));
   1413 
   1414           if ( cff_builder_start_point ( builder, x, y ) ||
   1415                check_points( builder, num_args / 2 )     )
   1416             goto Fail;
   1417 
   1418           if ( num_args < 2 )
   1419             goto Stack_Underflow;
   1420 
   1421           args -= num_args & ~1;
   1422           while ( args < decoder->top )
   1423           {
   1424             x += args[0];
   1425             y += args[1];
   1426             cff_builder_add_point( builder, x, y, 1 );
   1427             args += 2;
   1428           }
   1429           args = stack;
   1430           break;
   1431 
   1432         case cff_op_hlineto:
   1433         case cff_op_vlineto:
   1434           {
   1435             FT_Int  phase = ( op == cff_op_hlineto );
   1436 
   1437 
   1438             FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
   1439                                              : " vlineto\n" ));
   1440 
   1441             if ( num_args < 1 )
   1442               goto Stack_Underflow;
   1443 
   1444             if ( cff_builder_start_point ( builder, x, y ) ||
   1445                  check_points( builder, num_args )         )
   1446               goto Fail;
   1447 
   1448             args = stack;
   1449             while ( args < decoder->top )
   1450             {
   1451               if ( phase )
   1452                 x += args[0];
   1453               else
   1454                 y += args[0];
   1455 
   1456               if ( cff_builder_add_point1( builder, x, y ) )
   1457                 goto Fail;
   1458 
   1459               args++;
   1460               phase ^= 1;
   1461             }
   1462             args = stack;
   1463           }
   1464           break;
   1465 
   1466         case cff_op_rrcurveto:
   1467           {
   1468             FT_Int  nargs;
   1469 
   1470 
   1471             FT_TRACE4(( " rrcurveto\n" ));
   1472 
   1473             if ( num_args < 6 )
   1474               goto Stack_Underflow;
   1475 
   1476             nargs = num_args - num_args % 6;
   1477 
   1478             if ( cff_builder_start_point ( builder, x, y ) ||
   1479                  check_points( builder, nargs / 2 )     )
   1480               goto Fail;
   1481 
   1482             args -= nargs;
   1483             while ( args < decoder->top )
   1484             {
   1485               x += args[0];
   1486               y += args[1];
   1487               cff_builder_add_point( builder, x, y, 0 );
   1488               x += args[2];
   1489               y += args[3];
   1490               cff_builder_add_point( builder, x, y, 0 );
   1491               x += args[4];
   1492               y += args[5];
   1493               cff_builder_add_point( builder, x, y, 1 );
   1494               args += 6;
   1495             }
   1496             args = stack;
   1497           }
   1498           break;
   1499 
   1500         case cff_op_vvcurveto:
   1501           {
   1502             FT_Int  nargs;
   1503 
   1504 
   1505             FT_TRACE4(( " vvcurveto\n" ));
   1506 
   1507             if ( num_args < 4 )
   1508               goto Stack_Underflow;
   1509 
   1510             /* if num_args isn't of the form 4n or 4n+1, */
   1511             /* we reduce it to 4n+1                      */
   1512 
   1513             nargs = num_args - num_args % 4;
   1514             if ( num_args - nargs > 0 )
   1515               nargs += 1;
   1516 
   1517             if ( cff_builder_start_point( builder, x, y ) )
   1518               goto Fail;
   1519 
   1520             args -= nargs;
   1521 
   1522             if ( nargs & 1 )
   1523             {
   1524               x += args[0];
   1525               args++;
   1526               nargs--;
   1527             }
   1528 
   1529             if ( check_points( builder, 3 * ( nargs / 4 ) ) )
   1530               goto Fail;
   1531 
   1532             while ( args < decoder->top )
   1533             {
   1534               y += args[0];
   1535               cff_builder_add_point( builder, x, y, 0 );
   1536               x += args[1];
   1537               y += args[2];
   1538               cff_builder_add_point( builder, x, y, 0 );
   1539               y += args[3];
   1540               cff_builder_add_point( builder, x, y, 1 );
   1541               args += 4;
   1542             }
   1543             args = stack;
   1544           }
   1545           break;
   1546 
   1547         case cff_op_hhcurveto:
   1548           {
   1549             FT_Int  nargs;
   1550 
   1551 
   1552             FT_TRACE4(( " hhcurveto\n" ));
   1553 
   1554             if ( num_args < 4 )
   1555               goto Stack_Underflow;
   1556 
   1557             /* if num_args isn't of the form 4n or 4n+1, */
   1558             /* we reduce it to 4n+1                      */
   1559 
   1560             nargs = num_args - num_args % 4;
   1561             if ( num_args - nargs > 0 )
   1562               nargs += 1;
   1563 
   1564             if ( cff_builder_start_point( builder, x, y ) )
   1565               goto Fail;
   1566 
   1567             args -= nargs;
   1568             if ( nargs & 1 )
   1569             {
   1570               y += args[0];
   1571               args++;
   1572               nargs--;
   1573             }
   1574 
   1575             if ( check_points( builder, 3 * ( nargs / 4 ) ) )
   1576               goto Fail;
   1577 
   1578             while ( args < decoder->top )
   1579             {
   1580               x += args[0];
   1581               cff_builder_add_point( builder, x, y, 0 );
   1582               x += args[1];
   1583               y += args[2];
   1584               cff_builder_add_point( builder, x, y, 0 );
   1585               x += args[3];
   1586               cff_builder_add_point( builder, x, y, 1 );
   1587               args += 4;
   1588             }
   1589             args = stack;
   1590           }
   1591           break;
   1592 
   1593         case cff_op_vhcurveto:
   1594         case cff_op_hvcurveto:
   1595           {
   1596             FT_Int  phase;
   1597             FT_Int  nargs;
   1598 
   1599 
   1600             FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n"
   1601                                                : " hvcurveto\n" ));
   1602 
   1603             if ( cff_builder_start_point( builder, x, y ) )
   1604               goto Fail;
   1605 
   1606             if ( num_args < 4 )
   1607               goto Stack_Underflow;
   1608 
   1609             /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
   1610             /* we reduce it to the largest one which fits             */
   1611 
   1612             nargs = num_args - num_args % 4;
   1613             if ( num_args - nargs > 0 )
   1614               nargs += 1;
   1615 
   1616             args -= nargs;
   1617             if ( check_points( builder, ( nargs / 4 ) * 3 ) )
   1618               goto Stack_Underflow;
   1619 
   1620             phase = ( op == cff_op_hvcurveto );
   1621 
   1622             while ( nargs >= 4 )
   1623             {
   1624               nargs -= 4;
   1625               if ( phase )
   1626               {
   1627                 x += args[0];
   1628                 cff_builder_add_point( builder, x, y, 0 );
   1629                 x += args[1];
   1630                 y += args[2];
   1631                 cff_builder_add_point( builder, x, y, 0 );
   1632                 y += args[3];
   1633                 if ( nargs == 1 )
   1634                   x += args[4];
   1635                 cff_builder_add_point( builder, x, y, 1 );
   1636               }
   1637               else
   1638               {
   1639                 y += args[0];
   1640                 cff_builder_add_point( builder, x, y, 0 );
   1641                 x += args[1];
   1642                 y += args[2];
   1643                 cff_builder_add_point( builder, x, y, 0 );
   1644                 x += args[3];
   1645                 if ( nargs == 1 )
   1646                   y += args[4];
   1647                 cff_builder_add_point( builder, x, y, 1 );
   1648               }
   1649               args  += 4;
   1650               phase ^= 1;
   1651             }
   1652             args = stack;
   1653           }
   1654           break;
   1655 
   1656         case cff_op_rlinecurve:
   1657           {
   1658             FT_Int  num_lines;
   1659             FT_Int  nargs;
   1660 
   1661 
   1662             FT_TRACE4(( " rlinecurve\n" ));
   1663 
   1664             if ( num_args < 8 )
   1665               goto Stack_Underflow;
   1666 
   1667             nargs     = num_args & ~1;
   1668             num_lines = ( nargs - 6 ) / 2;
   1669 
   1670             if ( cff_builder_start_point( builder, x, y ) ||
   1671                  check_points( builder, num_lines + 3 )   )
   1672               goto Fail;
   1673 
   1674             args -= nargs;
   1675 
   1676             /* first, add the line segments */
   1677             while ( num_lines > 0 )
   1678             {
   1679               x += args[0];
   1680               y += args[1];
   1681               cff_builder_add_point( builder, x, y, 1 );
   1682               args += 2;
   1683               num_lines--;
   1684             }
   1685 
   1686             /* then the curve */
   1687             x += args[0];
   1688             y += args[1];
   1689             cff_builder_add_point( builder, x, y, 0 );
   1690             x += args[2];
   1691             y += args[3];
   1692             cff_builder_add_point( builder, x, y, 0 );
   1693             x += args[4];
   1694             y += args[5];
   1695             cff_builder_add_point( builder, x, y, 1 );
   1696             args = stack;
   1697           }
   1698           break;
   1699 
   1700         case cff_op_rcurveline:
   1701           {
   1702             FT_Int  num_curves;
   1703             FT_Int  nargs;
   1704 
   1705 
   1706             FT_TRACE4(( " rcurveline\n" ));
   1707 
   1708             if ( num_args < 8 )
   1709               goto Stack_Underflow;
   1710 
   1711             nargs      = num_args - 2;
   1712             nargs      = nargs - nargs % 6 + 2;
   1713             num_curves = ( nargs - 2 ) / 6;
   1714 
   1715             if ( cff_builder_start_point ( builder, x, y ) ||
   1716                  check_points( builder, num_curves * 3 + 2 ) )
   1717               goto Fail;
   1718 
   1719             args -= nargs;
   1720 
   1721             /* first, add the curves */
   1722             while ( num_curves > 0 )
   1723             {
   1724               x += args[0];
   1725               y += args[1];
   1726               cff_builder_add_point( builder, x, y, 0 );
   1727               x += args[2];
   1728               y += args[3];
   1729               cff_builder_add_point( builder, x, y, 0 );
   1730               x += args[4];
   1731               y += args[5];
   1732               cff_builder_add_point( builder, x, y, 1 );
   1733               args += 6;
   1734               num_curves--;
   1735             }
   1736 
   1737             /* then the final line */
   1738             x += args[0];
   1739             y += args[1];
   1740             cff_builder_add_point( builder, x, y, 1 );
   1741             args = stack;
   1742           }
   1743           break;
   1744 
   1745         case cff_op_hflex1:
   1746           {
   1747             FT_Pos start_y;
   1748 
   1749 
   1750             FT_TRACE4(( " hflex1\n" ));
   1751 
   1752             /* adding five more points: 4 control points, 1 on-curve point */
   1753             /* -- make sure we have enough space for the start point if it */
   1754             /* needs to be added                                           */
   1755             if ( cff_builder_start_point( builder, x, y ) ||
   1756                  check_points( builder, 6 )               )
   1757               goto Fail;
   1758 
   1759             /* record the starting point's y position for later use */
   1760             start_y = y;
   1761 
   1762             /* first control point */
   1763             x += args[0];
   1764             y += args[1];
   1765             cff_builder_add_point( builder, x, y, 0 );
   1766 
   1767             /* second control point */
   1768             x += args[2];
   1769             y += args[3];
   1770             cff_builder_add_point( builder, x, y, 0 );
   1771 
   1772             /* join point; on curve, with y-value the same as the last */
   1773             /* control point's y-value                                 */
   1774             x += args[4];
   1775             cff_builder_add_point( builder, x, y, 1 );
   1776 
   1777             /* third control point, with y-value the same as the join */
   1778             /* point's y-value                                        */
   1779             x += args[5];
   1780             cff_builder_add_point( builder, x, y, 0 );
   1781 
   1782             /* fourth control point */
   1783             x += args[6];
   1784             y += args[7];
   1785             cff_builder_add_point( builder, x, y, 0 );
   1786 
   1787             /* ending point, with y-value the same as the start   */
   1788             x += args[8];
   1789             y  = start_y;
   1790             cff_builder_add_point( builder, x, y, 1 );
   1791 
   1792             args = stack;
   1793             break;
   1794           }
   1795 
   1796         case cff_op_hflex:
   1797           {
   1798             FT_Pos start_y;
   1799 
   1800 
   1801             FT_TRACE4(( " hflex\n" ));
   1802 
   1803             /* adding six more points; 4 control points, 2 on-curve points */
   1804             if ( cff_builder_start_point( builder, x, y ) ||
   1805                  check_points( builder, 6 )               )
   1806               goto Fail;
   1807 
   1808             /* record the starting point's y-position for later use */
   1809             start_y = y;
   1810 
   1811             /* first control point */
   1812             x += args[0];
   1813             cff_builder_add_point( builder, x, y, 0 );
   1814 
   1815             /* second control point */
   1816             x += args[1];
   1817             y += args[2];
   1818             cff_builder_add_point( builder, x, y, 0 );
   1819 
   1820             /* join point; on curve, with y-value the same as the last */
   1821             /* control point's y-value                                 */
   1822             x += args[3];
   1823             cff_builder_add_point( builder, x, y, 1 );
   1824 
   1825             /* third control point, with y-value the same as the join */
   1826             /* point's y-value                                        */
   1827             x += args[4];
   1828             cff_builder_add_point( builder, x, y, 0 );
   1829 
   1830             /* fourth control point */
   1831             x += args[5];
   1832             y  = start_y;
   1833             cff_builder_add_point( builder, x, y, 0 );
   1834 
   1835             /* ending point, with y-value the same as the start point's */
   1836             /* y-value -- we don't add this point, though               */
   1837             x += args[6];
   1838             cff_builder_add_point( builder, x, y, 1 );
   1839 
   1840             args = stack;
   1841             break;
   1842           }
   1843 
   1844         case cff_op_flex1:
   1845           {
   1846             FT_Pos     start_x, start_y; /* record start x, y values for */
   1847                                          /* alter use                    */
   1848             FT_Fixed   dx = 0, dy = 0;   /* used in horizontal/vertical  */
   1849                                          /* algorithm below              */
   1850             FT_Int     horizontal, count;
   1851             FT_Fixed*  temp;
   1852 
   1853 
   1854             FT_TRACE4(( " flex1\n" ));
   1855 
   1856             /* adding six more points; 4 control points, 2 on-curve points */
   1857             if ( cff_builder_start_point( builder, x, y ) ||
   1858                  check_points( builder, 6 )               )
   1859               goto Fail;
   1860 
   1861             /* record the starting point's x, y position for later use */
   1862             start_x = x;
   1863             start_y = y;
   1864 
   1865             /* XXX: figure out whether this is supposed to be a horizontal */
   1866             /*      or vertical flex; the Type 2 specification is vague... */
   1867 
   1868             temp = args;
   1869 
   1870             /* grab up to the last argument */
   1871             for ( count = 5; count > 0; count-- )
   1872             {
   1873               dx += temp[0];
   1874               dy += temp[1];
   1875               temp += 2;
   1876             }
   1877 
   1878             if ( dx < 0 )
   1879               dx = -dx;
   1880             if ( dy < 0 )
   1881               dy = -dy;
   1882 
   1883             /* strange test, but here it is... */
   1884             horizontal = ( dx > dy );
   1885 
   1886             for ( count = 5; count > 0; count-- )
   1887             {
   1888               x += args[0];
   1889               y += args[1];
   1890               cff_builder_add_point( builder, x, y,
   1891                                      (FT_Bool)( count == 3 ) );
   1892               args += 2;
   1893             }
   1894 
   1895             /* is last operand an x- or y-delta? */
   1896             if ( horizontal )
   1897             {
   1898               x += args[0];
   1899               y  = start_y;
   1900             }
   1901             else
   1902             {
   1903               x  = start_x;
   1904               y += args[0];
   1905             }
   1906 
   1907             cff_builder_add_point( builder, x, y, 1 );
   1908 
   1909             args = stack;
   1910             break;
   1911            }
   1912 
   1913         case cff_op_flex:
   1914           {
   1915             FT_UInt  count;
   1916 
   1917 
   1918             FT_TRACE4(( " flex\n" ));
   1919 
   1920             if ( cff_builder_start_point( builder, x, y ) ||
   1921                  check_points( builder, 6 )               )
   1922               goto Fail;
   1923 
   1924             for ( count = 6; count > 0; count-- )
   1925             {
   1926               x += args[0];
   1927               y += args[1];
   1928               cff_builder_add_point( builder, x, y,
   1929                                      (FT_Bool)( count == 4 || count == 1 ) );
   1930               args += 2;
   1931             }
   1932 
   1933             args = stack;
   1934           }
   1935           break;
   1936 
   1937         case cff_op_seac:
   1938             FT_TRACE4(( " seac\n" ));
   1939 
   1940             error = cff_operator_seac( decoder,
   1941                                        args[0], args[1], args[2],
   1942                                        (FT_Int)( args[3] >> 16 ),
   1943                                        (FT_Int)( args[4] >> 16 ) );
   1944 
   1945             /* add current outline to the glyph slot */
   1946             FT_GlyphLoader_Add( builder->loader );
   1947 
   1948             /* return now! */
   1949             FT_TRACE4(( "\n" ));
   1950             return error;
   1951 
   1952         case cff_op_endchar:
   1953           FT_TRACE4(( " endchar\n" ));
   1954 
   1955           /* We are going to emulate the seac operator. */
   1956           if ( num_args >= 4 )
   1957           {
   1958             /* Save glyph width so that the subglyphs don't overwrite it. */
   1959             FT_Pos  glyph_width = decoder->glyph_width;
   1960 
   1961             error = cff_operator_seac( decoder,
   1962                                        0L, args[-4], args[-3],
   1963                                        (FT_Int)( args[-2] >> 16 ),
   1964                                        (FT_Int)( args[-1] >> 16 ) );
   1965 
   1966             decoder->glyph_width = glyph_width;
   1967           }
   1968           else
   1969           {
   1970             if ( !error )
   1971               error = CFF_Err_Ok;
   1972 
   1973             cff_builder_close_contour( builder );
   1974 
   1975             /* close hints recording session */
   1976             if ( hinter )
   1977             {
   1978               if ( hinter->close( hinter->hints,
   1979                                   builder->current->n_points ) )
   1980                 goto Syntax_Error;
   1981 
   1982               /* apply hints to the loaded glyph outline now */
   1983               hinter->apply( hinter->hints,
   1984                              builder->current,
   1985                              (PSH_Globals)builder->hints_globals,
   1986                              decoder->hint_mode );
   1987             }
   1988 
   1989             /* add current outline to the glyph slot */
   1990             FT_GlyphLoader_Add( builder->loader );
   1991           }
   1992 
   1993           /* return now! */
   1994           FT_TRACE4(( "\n" ));
   1995           return error;
   1996 
   1997         case cff_op_abs:
   1998           FT_TRACE4(( " abs\n" ));
   1999 
   2000           if ( args[0] < 0 )
   2001             args[0] = -args[0];
   2002           args++;
   2003           break;
   2004 
   2005         case cff_op_add:
   2006           FT_TRACE4(( " add\n" ));
   2007 
   2008           args[0] += args[1];
   2009           args++;
   2010           break;
   2011 
   2012         case cff_op_sub:
   2013           FT_TRACE4(( " sub\n" ));
   2014 
   2015           args[0] -= args[1];
   2016           args++;
   2017           break;
   2018 
   2019         case cff_op_div:
   2020           FT_TRACE4(( " div\n" ));
   2021 
   2022           args[0] = FT_DivFix( args[0], args[1] );
   2023           args++;
   2024           break;
   2025 
   2026         case cff_op_neg:
   2027           FT_TRACE4(( " neg\n" ));
   2028 
   2029           args[0] = -args[0];
   2030           args++;
   2031           break;
   2032 
   2033         case cff_op_random:
   2034           {
   2035             FT_Fixed  Rand;
   2036 
   2037 
   2038             FT_TRACE4(( " rand\n" ));
   2039 
   2040             Rand = seed;
   2041             if ( Rand >= 0x8000L )
   2042               Rand++;
   2043 
   2044             args[0] = Rand;
   2045             seed    = FT_MulFix( seed, 0x10000L - seed );
   2046             if ( seed == 0 )
   2047               seed += 0x2873;
   2048             args++;
   2049           }
   2050           break;
   2051 
   2052         case cff_op_mul:
   2053           FT_TRACE4(( " mul\n" ));
   2054 
   2055           args[0] = FT_MulFix( args[0], args[1] );
   2056           args++;
   2057           break;
   2058 
   2059         case cff_op_sqrt:
   2060           FT_TRACE4(( " sqrt\n" ));
   2061 
   2062           if ( args[0] > 0 )
   2063           {
   2064             FT_Int    count = 9;
   2065             FT_Fixed  root  = args[0];
   2066             FT_Fixed  new_root;
   2067 
   2068 
   2069             for (;;)
   2070             {
   2071               new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
   2072               if ( new_root == root || count <= 0 )
   2073                 break;
   2074               root = new_root;
   2075             }
   2076             args[0] = new_root;
   2077           }
   2078           else
   2079             args[0] = 0;
   2080           args++;
   2081           break;
   2082 
   2083         case cff_op_drop:
   2084           /* nothing */
   2085           FT_TRACE4(( " drop\n" ));
   2086 
   2087           break;
   2088 
   2089         case cff_op_exch:
   2090           {
   2091             FT_Fixed  tmp;
   2092 
   2093 
   2094             FT_TRACE4(( " exch\n" ));
   2095 
   2096             tmp     = args[0];
   2097             args[0] = args[1];
   2098             args[1] = tmp;
   2099             args   += 2;
   2100           }
   2101           break;
   2102 
   2103         case cff_op_index:
   2104           {
   2105             FT_Int  idx = (FT_Int)( args[0] >> 16 );
   2106 
   2107 
   2108             FT_TRACE4(( " index\n" ));
   2109 
   2110             if ( idx < 0 )
   2111               idx = 0;
   2112             else if ( idx > num_args - 2 )
   2113               idx = num_args - 2;
   2114             args[0] = args[-( idx + 1 )];
   2115             args++;
   2116           }
   2117           break;
   2118 
   2119         case cff_op_roll:
   2120           {
   2121             FT_Int  count = (FT_Int)( args[0] >> 16 );
   2122             FT_Int  idx   = (FT_Int)( args[1] >> 16 );
   2123 
   2124 
   2125             FT_TRACE4(( " roll\n" ));
   2126 
   2127             if ( count <= 0 )
   2128               count = 1;
   2129 
   2130             args -= count;
   2131             if ( args < stack )
   2132               goto Stack_Underflow;
   2133 
   2134             if ( idx >= 0 )
   2135             {
   2136               while ( idx > 0 )
   2137               {
   2138                 FT_Fixed  tmp = args[count - 1];
   2139                 FT_Int    i;
   2140 
   2141 
   2142                 for ( i = count - 2; i >= 0; i-- )
   2143                   args[i + 1] = args[i];
   2144                 args[0] = tmp;
   2145                 idx--;
   2146               }
   2147             }
   2148             else
   2149             {
   2150               while ( idx < 0 )
   2151               {
   2152                 FT_Fixed  tmp = args[0];
   2153                 FT_Int    i;
   2154 
   2155 
   2156                 for ( i = 0; i < count - 1; i++ )
   2157                   args[i] = args[i + 1];
   2158                 args[count - 1] = tmp;
   2159                 idx++;
   2160               }
   2161             }
   2162             args += count;
   2163           }
   2164           break;
   2165 
   2166         case cff_op_dup:
   2167           FT_TRACE4(( " dup\n" ));
   2168 
   2169           args[1] = args[0];
   2170           args += 2;
   2171           break;
   2172 
   2173         case cff_op_put:
   2174           {
   2175             FT_Fixed  val = args[0];
   2176             FT_Int    idx = (FT_Int)( args[1] >> 16 );
   2177 
   2178 
   2179             FT_TRACE4(( " put\n" ));
   2180 
   2181             if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
   2182               decoder->buildchar[idx] = val;
   2183           }
   2184           break;
   2185 
   2186         case cff_op_get:
   2187           {
   2188             FT_Int    idx = (FT_Int)( args[0] >> 16 );
   2189             FT_Fixed  val = 0;
   2190 
   2191 
   2192             FT_TRACE4(( " get\n" ));
   2193 
   2194             if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
   2195               val = decoder->buildchar[idx];
   2196 
   2197             args[0] = val;
   2198             args++;
   2199           }
   2200           break;
   2201 
   2202         case cff_op_store:
   2203           FT_TRACE4(( " store\n"));
   2204 
   2205           goto Unimplemented;
   2206 
   2207         case cff_op_load:
   2208           FT_TRACE4(( " load\n" ));
   2209 
   2210           goto Unimplemented;
   2211 
   2212         case cff_op_dotsection:
   2213           /* this operator is deprecated and ignored by the parser */
   2214           FT_TRACE4(( " dotsection\n" ));
   2215           break;
   2216 
   2217         case cff_op_closepath:
   2218           /* this is an invalid Type 2 operator; however, there        */
   2219           /* exist fonts which are incorrectly converted from probably */
   2220           /* Type 1 to CFF, and some parsers seem to accept it         */
   2221 
   2222           FT_TRACE4(( " closepath (invalid op)\n" ));
   2223 
   2224           args = stack;
   2225           break;
   2226 
   2227         case cff_op_hsbw:
   2228           /* this is an invalid Type 2 operator; however, there        */
   2229           /* exist fonts which are incorrectly converted from probably */
   2230           /* Type 1 to CFF, and some parsers seem to accept it         */
   2231 
   2232           FT_TRACE4(( " hsbw (invalid op)\n" ));
   2233 
   2234           decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 );
   2235 
   2236           decoder->builder.left_bearing.x = args[0];
   2237           decoder->builder.left_bearing.y = 0;
   2238 
   2239           x    = decoder->builder.pos_x + args[0];
   2240           y    = decoder->builder.pos_y;
   2241           args = stack;
   2242           break;
   2243 
   2244         case cff_op_sbw:
   2245           /* this is an invalid Type 2 operator; however, there        */
   2246           /* exist fonts which are incorrectly converted from probably */
   2247           /* Type 1 to CFF, and some parsers seem to accept it         */
   2248 
   2249           FT_TRACE4(( " sbw (invalid op)\n" ));
   2250 
   2251           decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 );
   2252 
   2253           decoder->builder.left_bearing.x = args[0];
   2254           decoder->builder.left_bearing.y = args[1];
   2255 
   2256           x    = decoder->builder.pos_x + args[0];
   2257           y    = decoder->builder.pos_y + args[1];
   2258           args = stack;
   2259           break;
   2260 
   2261         case cff_op_setcurrentpoint:
   2262           /* this is an invalid Type 2 operator; however, there        */
   2263           /* exist fonts which are incorrectly converted from probably */
   2264           /* Type 1 to CFF, and some parsers seem to accept it         */
   2265 
   2266           FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
   2267 
   2268           x    = decoder->builder.pos_x + args[0];
   2269           y    = decoder->builder.pos_y + args[1];
   2270           args = stack;
   2271           break;
   2272 
   2273         case cff_op_callothersubr:
   2274           /* this is an invalid Type 2 operator; however, there        */
   2275           /* exist fonts which are incorrectly converted from probably */
   2276           /* Type 1 to CFF, and some parsers seem to accept it         */
   2277 
   2278           FT_TRACE4(( " callothersubr (invalid op)\n" ));
   2279 
   2280           /* subsequent `pop' operands should add the arguments,       */
   2281           /* this is the implementation described for `unknown' other  */
   2282           /* subroutines in the Type1 spec.                            */
   2283           /*                                                           */
   2284           /* XXX Fix return arguments (see discussion below).          */
   2285           args -= 2 + ( args[-2] >> 16 );
   2286           if ( args < stack )
   2287             goto Stack_Underflow;
   2288           break;
   2289 
   2290         case cff_op_pop:
   2291           /* this is an invalid Type 2 operator; however, there        */
   2292           /* exist fonts which are incorrectly converted from probably */
   2293           /* Type 1 to CFF, and some parsers seem to accept it         */
   2294 
   2295           FT_TRACE4(( " pop (invalid op)\n" ));
   2296 
   2297           /* XXX Increasing `args' is wrong: After a certain number of */
   2298           /* `pop's we get a stack overflow.  Reason for doing it is   */
   2299           /* code like this (actually found in a CFF font):            */
   2300           /*                                                           */
   2301           /*   17 1 3 callothersubr                                    */
   2302           /*   pop                                                     */
   2303           /*   callsubr                                                */
   2304           /*                                                           */
   2305           /* Since we handle `callothersubr' as a no-op, and           */
   2306           /* `callsubr' needs at least one argument, `pop' can't be a  */
   2307           /* no-op too as it basically should be.                      */
   2308           /*                                                           */
   2309           /* The right solution would be to provide real support for   */
   2310           /* `callothersubr' as done in `t1decode.c', however, given   */
   2311           /* the fact that CFF fonts with `pop' are invalid, it is     */
   2312           /* questionable whether it is worth the time.                */
   2313           args++;
   2314           break;
   2315 
   2316         case cff_op_and:
   2317           {
   2318             FT_Fixed  cond = args[0] && args[1];
   2319 
   2320 
   2321             FT_TRACE4(( " and\n" ));
   2322 
   2323             args[0] = cond ? 0x10000L : 0;
   2324             args++;
   2325           }
   2326           break;
   2327 
   2328         case cff_op_or:
   2329           {
   2330             FT_Fixed  cond = args[0] || args[1];
   2331 
   2332 
   2333             FT_TRACE4(( " or\n" ));
   2334 
   2335             args[0] = cond ? 0x10000L : 0;
   2336             args++;
   2337           }
   2338           break;
   2339 
   2340         case cff_op_eq:
   2341           {
   2342             FT_Fixed  cond = !args[0];
   2343 
   2344 
   2345             FT_TRACE4(( " eq\n" ));
   2346 
   2347             args[0] = cond ? 0x10000L : 0;
   2348             args++;
   2349           }
   2350           break;
   2351 
   2352         case cff_op_ifelse:
   2353           {
   2354             FT_Fixed  cond = ( args[2] <= args[3] );
   2355 
   2356 
   2357             FT_TRACE4(( " ifelse\n" ));
   2358 
   2359             if ( !cond )
   2360               args[0] = args[1];
   2361             args++;
   2362           }
   2363           break;
   2364 
   2365         case cff_op_callsubr:
   2366           {
   2367             FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
   2368                                       decoder->locals_bias );
   2369 
   2370 
   2371             FT_TRACE4(( " callsubr(%d)\n", idx ));
   2372 
   2373             if ( idx >= decoder->num_locals )
   2374             {
   2375               FT_ERROR(( "cff_decoder_parse_charstrings:"
   2376                          " invalid local subr index\n" ));
   2377               goto Syntax_Error;
   2378             }
   2379 
   2380             if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
   2381             {
   2382               FT_ERROR(( "cff_decoder_parse_charstrings:"
   2383                          " too many nested subrs\n" ));
   2384               goto Syntax_Error;
   2385             }
   2386 
   2387             zone->cursor = ip;  /* save current instruction pointer */
   2388 
   2389             zone++;
   2390             zone->base   = decoder->locals[idx];
   2391             zone->limit  = decoder->locals[idx + 1];
   2392             zone->cursor = zone->base;
   2393 
   2394             if ( !zone->base || zone->limit == zone->base )
   2395             {
   2396               FT_ERROR(( "cff_decoder_parse_charstrings:"
   2397                          " invoking empty subrs\n" ));
   2398               goto Syntax_Error;
   2399             }
   2400 
   2401             decoder->zone = zone;
   2402             ip            = zone->base;
   2403             limit         = zone->limit;
   2404           }
   2405           break;
   2406 
   2407         case cff_op_callgsubr:
   2408           {
   2409             FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
   2410                                       decoder->globals_bias );
   2411 
   2412 
   2413             FT_TRACE4(( " callgsubr(%d)\n", idx ));
   2414 
   2415             if ( idx >= decoder->num_globals )
   2416             {
   2417               FT_ERROR(( "cff_decoder_parse_charstrings:"
   2418                          " invalid global subr index\n" ));
   2419               goto Syntax_Error;
   2420             }
   2421 
   2422             if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
   2423             {
   2424               FT_ERROR(( "cff_decoder_parse_charstrings:"
   2425                          " too many nested subrs\n" ));
   2426               goto Syntax_Error;
   2427             }
   2428 
   2429             zone->cursor = ip;  /* save current instruction pointer */
   2430 
   2431             zone++;
   2432             zone->base   = decoder->globals[idx];
   2433             zone->limit  = decoder->globals[idx + 1];
   2434             zone->cursor = zone->base;
   2435 
   2436             if ( !zone->base || zone->limit == zone->base )
   2437             {
   2438               FT_ERROR(( "cff_decoder_parse_charstrings:"
   2439                          " invoking empty subrs\n" ));
   2440               goto Syntax_Error;
   2441             }
   2442 
   2443             decoder->zone = zone;
   2444             ip            = zone->base;
   2445             limit         = zone->limit;
   2446           }
   2447           break;
   2448 
   2449         case cff_op_return:
   2450           FT_TRACE4(( " return\n" ));
   2451 
   2452           if ( decoder->zone <= decoder->zones )
   2453           {
   2454             FT_ERROR(( "cff_decoder_parse_charstrings:"
   2455                        " unexpected return\n" ));
   2456             goto Syntax_Error;
   2457           }
   2458 
   2459           decoder->zone--;
   2460           zone  = decoder->zone;
   2461           ip    = zone->cursor;
   2462           limit = zone->limit;
   2463           break;
   2464 
   2465         default:
   2466         Unimplemented:
   2467           FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
   2468 
   2469           if ( ip[-1] == 12 )
   2470             FT_ERROR(( " %d", ip[0] ));
   2471           FT_ERROR(( "\n" ));
   2472 
   2473           return CFF_Err_Unimplemented_Feature;
   2474         }
   2475 
   2476         decoder->top = args;
   2477 
   2478         if ( decoder->top - stack >= CFF_MAX_OPERANDS )
   2479           goto Stack_Overflow;
   2480 
   2481       } /* general operator processing */
   2482 
   2483     } /* while ip < limit */
   2484 
   2485     FT_TRACE4(( "..end..\n\n" ));
   2486 
   2487   Fail:
   2488     return error;
   2489 
   2490   Syntax_Error:
   2491     FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
   2492     return CFF_Err_Invalid_File_Format;
   2493 
   2494   Stack_Underflow:
   2495     FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
   2496     return CFF_Err_Too_Few_Arguments;
   2497 
   2498   Stack_Overflow:
   2499     FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
   2500     return CFF_Err_Stack_Overflow;
   2501   }
   2502 
   2503 
   2504   /*************************************************************************/
   2505   /*************************************************************************/
   2506   /*************************************************************************/
   2507   /**********                                                      *********/
   2508   /**********                                                      *********/
   2509   /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
   2510   /**********                                                      *********/
   2511   /**********    The following code is in charge of computing      *********/
   2512   /**********    the maximum advance width of the font.  It        *********/
   2513   /**********    quickly processes each glyph charstring to        *********/
   2514   /**********    extract the value from either a `sbw' or `seac'   *********/
   2515   /**********    operator.                                         *********/
   2516   /**********                                                      *********/
   2517   /*************************************************************************/
   2518   /*************************************************************************/
   2519   /*************************************************************************/
   2520 
   2521 
   2522 #if 0 /* unused until we support pure CFF fonts */
   2523 
   2524 
   2525   FT_LOCAL_DEF( FT_Error )
   2526   cff_compute_max_advance( TT_Face  face,
   2527                            FT_Int*  max_advance )
   2528   {
   2529     FT_Error     error = CFF_Err_Ok;
   2530     CFF_Decoder  decoder;
   2531     FT_Int       glyph_index;
   2532     CFF_Font     cff = (CFF_Font)face->other;
   2533 
   2534 
   2535     *max_advance = 0;
   2536 
   2537     /* Initialize load decoder */
   2538     cff_decoder_init( &decoder, face, 0, 0, 0, 0 );
   2539 
   2540     decoder.builder.metrics_only = 1;
   2541     decoder.builder.load_points  = 0;
   2542 
   2543     /* For each glyph, parse the glyph charstring and extract */
   2544     /* the advance width.                                     */
   2545     for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
   2546           glyph_index++ )
   2547     {
   2548       FT_Byte*  charstring;
   2549       FT_ULong  charstring_len;
   2550 
   2551 
   2552       /* now get load the unscaled outline */
   2553       error = cff_get_glyph_data( face, glyph_index,
   2554                                   &charstring, &charstring_len );
   2555       if ( !error )
   2556       {
   2557         error = cff_decoder_prepare( &decoder, size, glyph_index );
   2558         if ( !error )
   2559           error = cff_decoder_parse_charstrings( &decoder,
   2560                                                  charstring,
   2561                                                  charstring_len );
   2562 
   2563         cff_free_glyph_data( face, &charstring, &charstring_len );
   2564       }
   2565 
   2566       /* ignore the error if one has occurred -- skip to next glyph */
   2567       error = CFF_Err_Ok;
   2568     }
   2569 
   2570     *max_advance = decoder.builder.advance.x;
   2571 
   2572     return CFF_Err_Ok;
   2573   }
   2574 
   2575 
   2576 #endif /* 0 */
   2577 
   2578 
   2579   FT_LOCAL_DEF( FT_Error )
   2580   cff_slot_load( CFF_GlyphSlot  glyph,
   2581                  CFF_Size       size,
   2582                  FT_UInt        glyph_index,
   2583                  FT_Int32       load_flags )
   2584   {
   2585     FT_Error     error;
   2586     CFF_Decoder  decoder;
   2587     TT_Face      face = (TT_Face)glyph->root.face;
   2588     FT_Bool      hinting, force_scaling;
   2589     CFF_Font     cff  = (CFF_Font)face->extra.data;
   2590 
   2591     FT_Matrix    font_matrix;
   2592     FT_Vector    font_offset;
   2593 
   2594 
   2595     force_scaling = FALSE;
   2596 
   2597     /* in a CID-keyed font, consider `glyph_index' as a CID and map */
   2598     /* it immediately to the real glyph_index -- if it isn't a      */
   2599     /* subsetted font, glyph_indices and CIDs are identical, though */
   2600     if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
   2601          cff->charset.cids                               )
   2602     {
   2603       /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */
   2604       if ( glyph_index != 0 )
   2605       {
   2606         glyph_index = cff_charset_cid_to_gindex( &cff->charset,
   2607                                                  glyph_index );
   2608         if ( glyph_index == 0 )
   2609           return CFF_Err_Invalid_Argument;
   2610       }
   2611     }
   2612     else if ( glyph_index >= cff->num_glyphs )
   2613       return CFF_Err_Invalid_Argument;
   2614 
   2615     if ( load_flags & FT_LOAD_NO_RECURSE )
   2616       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
   2617 
   2618     glyph->x_scale = 0x10000L;
   2619     glyph->y_scale = 0x10000L;
   2620     if ( size )
   2621     {
   2622       glyph->x_scale = size->root.metrics.x_scale;
   2623       glyph->y_scale = size->root.metrics.y_scale;
   2624     }
   2625 
   2626 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
   2627 
   2628     /* try to load embedded bitmap if any              */
   2629     /*                                                 */
   2630     /* XXX: The convention should be emphasized in     */
   2631     /*      the documents because it can be confusing. */
   2632     if ( size )
   2633     {
   2634       CFF_Face      cff_face = (CFF_Face)size->root.face;
   2635       SFNT_Service  sfnt     = (SFNT_Service)cff_face->sfnt;
   2636       FT_Stream     stream   = cff_face->root.stream;
   2637 
   2638 
   2639       if ( size->strike_index != 0xFFFFFFFFUL      &&
   2640            sfnt->load_eblc                         &&
   2641            ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
   2642       {
   2643         TT_SBit_MetricsRec  metrics;
   2644 
   2645 
   2646         error = sfnt->load_sbit_image( face,
   2647                                        size->strike_index,
   2648                                        glyph_index,
   2649                                        (FT_Int)load_flags,
   2650                                        stream,
   2651                                        &glyph->root.bitmap,
   2652                                        &metrics );
   2653 
   2654         if ( !error )
   2655         {
   2656           glyph->root.outline.n_points   = 0;
   2657           glyph->root.outline.n_contours = 0;
   2658 
   2659           glyph->root.metrics.width  = (FT_Pos)metrics.width  << 6;
   2660           glyph->root.metrics.height = (FT_Pos)metrics.height << 6;
   2661 
   2662           glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
   2663           glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
   2664           glyph->root.metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
   2665 
   2666           glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
   2667           glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
   2668           glyph->root.metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
   2669 
   2670           glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
   2671 
   2672           if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
   2673           {
   2674             glyph->root.bitmap_left = metrics.vertBearingX;
   2675             glyph->root.bitmap_top  = metrics.vertBearingY;
   2676           }
   2677           else
   2678           {
   2679             glyph->root.bitmap_left = metrics.horiBearingX;
   2680             glyph->root.bitmap_top  = metrics.horiBearingY;
   2681           }
   2682           return error;
   2683         }
   2684       }
   2685     }
   2686 
   2687 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
   2688 
   2689     /* return immediately if we only want the embedded bitmaps */
   2690     if ( load_flags & FT_LOAD_SBITS_ONLY )
   2691       return CFF_Err_Invalid_Argument;
   2692 
   2693     /* if we have a CID subfont, use its matrix (which has already */
   2694     /* been multiplied with the root matrix)                       */
   2695 
   2696     /* this scaling is only relevant if the PS hinter isn't active */
   2697     if ( cff->num_subfonts )
   2698     {
   2699       FT_ULong  top_upm, sub_upm;
   2700       FT_Byte   fd_index = cff_fd_select_get( &cff->fd_select,
   2701                                               glyph_index );
   2702 
   2703       if ( fd_index >= cff->num_subfonts )
   2704         fd_index = cff->num_subfonts - 1;
   2705 
   2706       top_upm = cff->top_font.font_dict.units_per_em;
   2707       sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em;
   2708 
   2709 
   2710       font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
   2711       font_offset = cff->subfonts[fd_index]->font_dict.font_offset;
   2712 
   2713       if ( top_upm != sub_upm )
   2714       {
   2715         glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm );
   2716         glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm );
   2717 
   2718         force_scaling = TRUE;
   2719       }
   2720     }
   2721     else
   2722     {
   2723       font_matrix = cff->top_font.font_dict.font_matrix;
   2724       font_offset = cff->top_font.font_dict.font_offset;
   2725     }
   2726 
   2727     glyph->root.outline.n_points   = 0;
   2728     glyph->root.outline.n_contours = 0;
   2729 
   2730     hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
   2731                        ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
   2732 
   2733     glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;  /* by default */
   2734 
   2735     {
   2736       FT_Byte*  charstring;
   2737       FT_ULong  charstring_len;
   2738 
   2739 
   2740       cff_decoder_init( &decoder, face, size, glyph, hinting,
   2741                         FT_LOAD_TARGET_MODE( load_flags ) );
   2742 
   2743       if ( load_flags & FT_LOAD_ADVANCE_ONLY )
   2744         decoder.width_only = TRUE;
   2745 
   2746       decoder.builder.no_recurse =
   2747         (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );
   2748 
   2749       /* now load the unscaled outline */
   2750       error = cff_get_glyph_data( face, glyph_index,
   2751                                   &charstring, &charstring_len );
   2752       if ( error )
   2753         goto Glyph_Build_Finished;
   2754 
   2755       error = cff_decoder_prepare( &decoder, size, glyph_index );
   2756       if ( error )
   2757         goto Glyph_Build_Finished;
   2758 
   2759       error = cff_decoder_parse_charstrings( &decoder,
   2760                                              charstring,
   2761                                              charstring_len );
   2762 
   2763       cff_free_glyph_data( face, &charstring, charstring_len );
   2764 
   2765       if ( error )
   2766         goto Glyph_Build_Finished;
   2767 
   2768 #ifdef FT_CONFIG_OPTION_INCREMENTAL
   2769       /* Control data and length may not be available for incremental */
   2770       /* fonts.                                                       */
   2771       if ( face->root.internal->incremental_interface )
   2772       {
   2773         glyph->root.control_data = 0;
   2774         glyph->root.control_len = 0;
   2775       }
   2776       else
   2777 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
   2778 
   2779       /* We set control_data and control_len if charstrings is loaded. */
   2780       /* See how charstring loads at cff_index_access_element() in     */
   2781       /* cffload.c.                                                    */
   2782       {
   2783         CFF_Index  csindex = &cff->charstrings_index;
   2784 
   2785 
   2786         if ( csindex->offsets )
   2787         {
   2788           glyph->root.control_data = csindex->bytes +
   2789                                      csindex->offsets[glyph_index] - 1;
   2790           glyph->root.control_len  = charstring_len;
   2791         }
   2792       }
   2793 
   2794   Glyph_Build_Finished:
   2795       /* save new glyph tables, if no error */
   2796       if ( !error )
   2797         cff_builder_done( &decoder.builder );
   2798       /* XXX: anything to do for broken glyph entry? */
   2799     }
   2800 
   2801 #ifdef FT_CONFIG_OPTION_INCREMENTAL
   2802 
   2803     /* Incremental fonts can optionally override the metrics. */
   2804     if ( !error                                                               &&
   2805          face->root.internal->incremental_interface                           &&
   2806          face->root.internal->incremental_interface->funcs->get_glyph_metrics )
   2807     {
   2808       FT_Incremental_MetricsRec  metrics;
   2809 
   2810 
   2811       metrics.bearing_x = decoder.builder.left_bearing.x;
   2812       metrics.bearing_y = 0;
   2813       metrics.advance   = decoder.builder.advance.x;
   2814       metrics.advance_v = decoder.builder.advance.y;
   2815 
   2816       error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
   2817                 face->root.internal->incremental_interface->object,
   2818                 glyph_index, FALSE, &metrics );
   2819 
   2820       decoder.builder.left_bearing.x = metrics.bearing_x;
   2821       decoder.builder.advance.x      = metrics.advance;
   2822       decoder.builder.advance.y      = metrics.advance_v;
   2823     }
   2824 
   2825 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
   2826 
   2827     if ( !error )
   2828     {
   2829       /* Now, set the metrics -- this is rather simple, as   */
   2830       /* the left side bearing is the xMin, and the top side */
   2831       /* bearing the yMax.                                   */
   2832 
   2833       /* For composite glyphs, return only left side bearing and */
   2834       /* advance width.                                          */
   2835       if ( load_flags & FT_LOAD_NO_RECURSE )
   2836       {
   2837         FT_Slot_Internal  internal = glyph->root.internal;
   2838 
   2839 
   2840         glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
   2841         glyph->root.metrics.horiAdvance  = decoder.glyph_width;
   2842         internal->glyph_matrix           = font_matrix;
   2843         internal->glyph_delta            = font_offset;
   2844         internal->glyph_transformed      = 1;
   2845       }
   2846       else
   2847       {
   2848         FT_BBox            cbox;
   2849         FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
   2850         FT_Vector          advance;
   2851         FT_Bool            has_vertical_info;
   2852 
   2853 
   2854         /* copy the _unscaled_ advance width */
   2855         metrics->horiAdvance                    = decoder.glyph_width;
   2856         glyph->root.linearHoriAdvance           = decoder.glyph_width;
   2857         glyph->root.internal->glyph_transformed = 0;
   2858 
   2859 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
   2860         has_vertical_info = FT_BOOL( face->vertical_info                   &&
   2861                                      face->vertical.number_Of_VMetrics > 0 &&
   2862                                      face->vertical.long_metrics           );
   2863 #else
   2864         has_vertical_info = FT_BOOL( face->vertical_info                   &&
   2865                                      face->vertical.number_Of_VMetrics > 0 );
   2866 #endif
   2867 
   2868         /* get the vertical metrics from the vtmx table if we have one */
   2869         if ( has_vertical_info )
   2870         {
   2871           FT_Short   vertBearingY = 0;
   2872           FT_UShort  vertAdvance  = 0;
   2873 
   2874 
   2875           ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
   2876                                                      glyph_index,
   2877                                                      &vertBearingY,
   2878                                                      &vertAdvance );
   2879           metrics->vertBearingY = vertBearingY;
   2880           metrics->vertAdvance  = vertAdvance;
   2881         }
   2882         else
   2883         {
   2884           /* make up vertical ones */
   2885           if ( face->os2.version != 0xFFFFU )
   2886             metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -
   2887                                              face->os2.sTypoDescender );
   2888           else
   2889             metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -
   2890                                              face->horizontal.Descender );
   2891         }
   2892 
   2893         glyph->root.linearVertAdvance = metrics->vertAdvance;
   2894 
   2895         glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
   2896 
   2897         glyph->root.outline.flags = 0;
   2898         if ( size && size->root.metrics.y_ppem < 24 )
   2899           glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
   2900 
   2901         glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
   2902 
   2903         if ( !( font_matrix.xx == 0x10000L &&
   2904                 font_matrix.yy == 0x10000L &&
   2905                 font_matrix.xy == 0        &&
   2906                 font_matrix.yx == 0        ) )
   2907           FT_Outline_Transform( &glyph->root.outline, &font_matrix );
   2908 
   2909         if ( !( font_offset.x == 0 &&
   2910                 font_offset.y == 0 ) )
   2911           FT_Outline_Translate( &glyph->root.outline,
   2912                                 font_offset.x, font_offset.y );
   2913 
   2914         advance.x = metrics->horiAdvance;
   2915         advance.y = 0;
   2916         FT_Vector_Transform( &advance, &font_matrix );
   2917         metrics->horiAdvance = advance.x + font_offset.x;
   2918 
   2919         advance.x = 0;
   2920         advance.y = metrics->vertAdvance;
   2921         FT_Vector_Transform( &advance, &font_matrix );
   2922         metrics->vertAdvance = advance.y + font_offset.y;
   2923 
   2924         if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
   2925         {
   2926           /* scale the outline and the metrics */
   2927           FT_Int       n;
   2928           FT_Outline*  cur     = &glyph->root.outline;
   2929           FT_Vector*   vec     = cur->points;
   2930           FT_Fixed     x_scale = glyph->x_scale;
   2931           FT_Fixed     y_scale = glyph->y_scale;
   2932 
   2933 
   2934           /* First of all, scale the points */
   2935           if ( !hinting || !decoder.builder.hints_funcs )
   2936             for ( n = cur->n_points; n > 0; n--, vec++ )
   2937             {
   2938               vec->x = FT_MulFix( vec->x, x_scale );
   2939               vec->y = FT_MulFix( vec->y, y_scale );
   2940             }
   2941 
   2942           /* Then scale the metrics */
   2943           metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
   2944           metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
   2945         }
   2946 
   2947         /* compute the other metrics */
   2948         FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
   2949 
   2950         metrics->width  = cbox.xMax - cbox.xMin;
   2951         metrics->height = cbox.yMax - cbox.yMin;
   2952 
   2953         metrics->horiBearingX = cbox.xMin;
   2954         metrics->horiBearingY = cbox.yMax;
   2955 
   2956         if ( has_vertical_info )
   2957           metrics->vertBearingX = metrics->horiBearingX -
   2958                                     metrics->horiAdvance / 2;
   2959         else
   2960         {
   2961           if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
   2962             ft_synthesize_vertical_metrics( metrics,
   2963                                             metrics->vertAdvance );
   2964         }
   2965       }
   2966     }
   2967 
   2968     return error;
   2969   }
   2970 
   2971 
   2972 /* END */
   2973