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