cffgload.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  cffgload.c                                                             */
00004 /*                                                                         */
00005 /*    OpenType Glyph Loader (body).                                        */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
00008 /*            2010 by                                                      */
00009 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00010 /*                                                                         */
00011 /*  This file is part of the FreeType project, and may only be used,       */
00012 /*  modified, and distributed under the terms of the FreeType project      */
00013 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00014 /*  this file you indicate that you have read the license and              */
00015 /*  understand and accept it fully.                                        */
00016 /*                                                                         */
00017 /***************************************************************************/
00018 
00019 
00020 #include <ft2build.h>
00021 #include FT_INTERNAL_DEBUG_H
00022 #include FT_INTERNAL_STREAM_H
00023 #include FT_INTERNAL_SFNT_H
00024 #include FT_OUTLINE_H
00025 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
00026 
00027 #include "cffobjs.h"
00028 #include "cffload.h"
00029 #include "cffgload.h"
00030 
00031 #include "cfferrs.h"
00032 
00033 
00034   /*************************************************************************/
00035   /*                                                                       */
00036   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00037   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00038   /* messages during execution.                                            */
00039   /*                                                                       */
00040 #undef  FT_COMPONENT
00041 #define FT_COMPONENT  trace_cffgload
00042 
00043 
00044   typedef enum  CFF_Operator_
00045   {
00046     cff_op_unknown = 0,
00047 
00048     cff_op_rmoveto,
00049     cff_op_hmoveto,
00050     cff_op_vmoveto,
00051 
00052     cff_op_rlineto,
00053     cff_op_hlineto,
00054     cff_op_vlineto,
00055 
00056     cff_op_rrcurveto,
00057     cff_op_hhcurveto,
00058     cff_op_hvcurveto,
00059     cff_op_rcurveline,
00060     cff_op_rlinecurve,
00061     cff_op_vhcurveto,
00062     cff_op_vvcurveto,
00063 
00064     cff_op_flex,
00065     cff_op_hflex,
00066     cff_op_hflex1,
00067     cff_op_flex1,
00068 
00069     cff_op_endchar,
00070 
00071     cff_op_hstem,
00072     cff_op_vstem,
00073     cff_op_hstemhm,
00074     cff_op_vstemhm,
00075 
00076     cff_op_hintmask,
00077     cff_op_cntrmask,
00078     cff_op_dotsection,  /* deprecated, acts as no-op */
00079 
00080     cff_op_abs,
00081     cff_op_add,
00082     cff_op_sub,
00083     cff_op_div,
00084     cff_op_neg,
00085     cff_op_random,
00086     cff_op_mul,
00087     cff_op_sqrt,
00088 
00089     cff_op_blend,
00090 
00091     cff_op_drop,
00092     cff_op_exch,
00093     cff_op_index,
00094     cff_op_roll,
00095     cff_op_dup,
00096 
00097     cff_op_put,
00098     cff_op_get,
00099     cff_op_store,
00100     cff_op_load,
00101 
00102     cff_op_and,
00103     cff_op_or,
00104     cff_op_not,
00105     cff_op_eq,
00106     cff_op_ifelse,
00107 
00108     cff_op_callsubr,
00109     cff_op_callgsubr,
00110     cff_op_return,
00111 
00112     /* Type 1 opcodes: invalid but seen in real life */
00113     cff_op_hsbw,
00114     cff_op_closepath,
00115     cff_op_callothersubr,
00116     cff_op_pop,
00117     cff_op_seac,
00118     cff_op_sbw,
00119     cff_op_setcurrentpoint,
00120 
00121     /* do not remove */
00122     cff_op_max
00123 
00124   } CFF_Operator;
00125 
00126 
00127 #define CFF_COUNT_CHECK_WIDTH  0x80
00128 #define CFF_COUNT_EXACT        0x40
00129 #define CFF_COUNT_CLEAR_STACK  0x20
00130 
00131   /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are  */
00132   /* used for checking the width and requested numbers of arguments    */
00133   /* only; they are set to zero afterwards                             */
00134 
00135   /* the other two flags are informative only and unused currently     */
00136 
00137   static const FT_Byte  cff_argument_counts[] =
00138   {
00139     0,  /* unknown */
00140 
00141     2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
00142     1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
00143     1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
00144 
00145     0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
00146     0 | CFF_COUNT_CLEAR_STACK,
00147     0 | CFF_COUNT_CLEAR_STACK,
00148 
00149     0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
00150     0 | CFF_COUNT_CLEAR_STACK,
00151     0 | CFF_COUNT_CLEAR_STACK,
00152     0 | CFF_COUNT_CLEAR_STACK,
00153     0 | CFF_COUNT_CLEAR_STACK,
00154     0 | CFF_COUNT_CLEAR_STACK,
00155     0 | CFF_COUNT_CLEAR_STACK,
00156 
00157     13, /* flex */
00158     7,
00159     9,
00160     11,
00161 
00162     0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
00163 
00164     2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
00165     2 | CFF_COUNT_CHECK_WIDTH,
00166     2 | CFF_COUNT_CHECK_WIDTH,
00167     2 | CFF_COUNT_CHECK_WIDTH,
00168 
00169     0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
00170     0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
00171     0, /* dotsection */
00172 
00173     1, /* abs */
00174     2,
00175     2,
00176     2,
00177     1,
00178     0,
00179     2,
00180     1,
00181 
00182     1, /* blend */
00183 
00184     1, /* drop */
00185     2,
00186     1,
00187     2,
00188     1,
00189 
00190     2, /* put */
00191     1,
00192     4,
00193     3,
00194 
00195     2, /* and */
00196     2,
00197     1,
00198     2,
00199     4,
00200 
00201     1, /* callsubr */
00202     1,
00203     0,
00204 
00205     2, /* hsbw */
00206     0,
00207     0,
00208     0,
00209     5, /* seac */
00210     4, /* sbw */
00211     2  /* setcurrentpoint */
00212   };
00213 
00214 
00215   /*************************************************************************/
00216   /*************************************************************************/
00217   /*************************************************************************/
00218   /**********                                                      *********/
00219   /**********                                                      *********/
00220   /**********             GENERIC CHARSTRING PARSING               *********/
00221   /**********                                                      *********/
00222   /**********                                                      *********/
00223   /*************************************************************************/
00224   /*************************************************************************/
00225   /*************************************************************************/
00226 
00227 
00228   /*************************************************************************/
00229   /*                                                                       */
00230   /* <Function>                                                            */
00231   /*    cff_builder_init                                                   */
00232   /*                                                                       */
00233   /* <Description>                                                         */
00234   /*    Initializes a given glyph builder.                                 */
00235   /*                                                                       */
00236   /* <InOut>                                                               */
00237   /*    builder :: A pointer to the glyph builder to initialize.           */
00238   /*                                                                       */
00239   /* <Input>                                                               */
00240   /*    face    :: The current face object.                                */
00241   /*                                                                       */
00242   /*    size    :: The current size object.                                */
00243   /*                                                                       */
00244   /*    glyph   :: The current glyph object.                               */
00245   /*                                                                       */
00246   /*    hinting :: Whether hinting is active.                              */
00247   /*                                                                       */
00248   static void
00249   cff_builder_init( CFF_Builder*   builder,
00250                     TT_Face        face,
00251                     CFF_Size       size,
00252                     CFF_GlyphSlot  glyph,
00253                     FT_Bool        hinting )
00254   {
00255     builder->path_begun  = 0;
00256     builder->load_points = 1;
00257 
00258     builder->face   = face;
00259     builder->glyph  = glyph;
00260     builder->memory = face->root.memory;
00261 
00262     if ( glyph )
00263     {
00264       FT_GlyphLoader  loader = glyph->root.internal->loader;
00265 
00266 
00267       builder->loader  = loader;
00268       builder->base    = &loader->base.outline;
00269       builder->current = &loader->current.outline;
00270       FT_GlyphLoader_Rewind( loader );
00271 
00272       builder->hints_globals = 0;
00273       builder->hints_funcs   = 0;
00274 
00275       if ( hinting && size )
00276       {
00277         CFF_Internal  internal = (CFF_Internal)size->root.internal;
00278 
00279 
00280         builder->hints_globals = (void *)internal->topfont;
00281         builder->hints_funcs   = glyph->root.internal->glyph_hints;
00282       }
00283     }
00284 
00285     builder->pos_x = 0;
00286     builder->pos_y = 0;
00287 
00288     builder->left_bearing.x = 0;
00289     builder->left_bearing.y = 0;
00290     builder->advance.x      = 0;
00291     builder->advance.y      = 0;
00292   }
00293 
00294 
00295   /*************************************************************************/
00296   /*                                                                       */
00297   /* <Function>                                                            */
00298   /*    cff_builder_done                                                   */
00299   /*                                                                       */
00300   /* <Description>                                                         */
00301   /*    Finalizes a given glyph builder.  Its contents can still be used   */
00302   /*    after the call, but the function saves important information       */
00303   /*    within the corresponding glyph slot.                               */
00304   /*                                                                       */
00305   /* <Input>                                                               */
00306   /*    builder :: A pointer to the glyph builder to finalize.             */
00307   /*                                                                       */
00308   static void
00309   cff_builder_done( CFF_Builder*  builder )
00310   {
00311     CFF_GlyphSlot  glyph = builder->glyph;
00312 
00313 
00314     if ( glyph )
00315       glyph->root.outline = *builder->base;
00316   }
00317 
00318 
00319   /*************************************************************************/
00320   /*                                                                       */
00321   /* <Function>                                                            */
00322   /*    cff_compute_bias                                                   */
00323   /*                                                                       */
00324   /* <Description>                                                         */
00325   /*    Computes the bias value in dependence of the number of glyph       */
00326   /*    subroutines.                                                       */
00327   /*                                                                       */
00328   /* <Input>                                                               */
00329   /*    in_charstring_type :: The `CharstringType' value of the top DICT   */
00330   /*                          dictionary.                                  */
00331   /*                                                                       */
00332   /*    num_subrs          :: The number of glyph subroutines.             */
00333   /*                                                                       */
00334   /* <Return>                                                              */
00335   /*    The bias value.                                                    */
00336   static FT_Int
00337   cff_compute_bias( FT_Int   in_charstring_type,
00338                     FT_UInt  num_subrs )
00339   {
00340     FT_Int  result;
00341 
00342 
00343     if ( in_charstring_type == 1 )
00344       result = 0;
00345     else if ( num_subrs < 1240 )
00346       result = 107;
00347     else if ( num_subrs < 33900U )
00348       result = 1131;
00349     else
00350       result = 32768U;
00351 
00352     return result;
00353   }
00354 
00355 
00356   /*************************************************************************/
00357   /*                                                                       */
00358   /* <Function>                                                            */
00359   /*    cff_decoder_init                                                   */
00360   /*                                                                       */
00361   /* <Description>                                                         */
00362   /*    Initializes a given glyph decoder.                                 */
00363   /*                                                                       */
00364   /* <InOut>                                                               */
00365   /*    decoder :: A pointer to the glyph builder to initialize.           */
00366   /*                                                                       */
00367   /* <Input>                                                               */
00368   /*    face      :: The current face object.                              */
00369   /*                                                                       */
00370   /*    size      :: The current size object.                              */
00371   /*                                                                       */
00372   /*    slot      :: The current glyph object.                             */
00373   /*                                                                       */
00374   /*    hinting   :: Whether hinting is active.                            */
00375   /*                                                                       */
00376   /*    hint_mode :: The hinting mode.                                     */
00377   /*                                                                       */
00378   FT_LOCAL_DEF( void )
00379   cff_decoder_init( CFF_Decoder*    decoder,
00380                     TT_Face         face,
00381                     CFF_Size        size,
00382                     CFF_GlyphSlot   slot,
00383                     FT_Bool         hinting,
00384                     FT_Render_Mode  hint_mode )
00385   {
00386     CFF_Font  cff = (CFF_Font)face->extra.data;
00387 
00388 
00389     /* clear everything */
00390     FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
00391 
00392     /* initialize builder */
00393     cff_builder_init( &decoder->builder, face, size, slot, hinting );
00394 
00395     /* initialize Type2 decoder */
00396     decoder->cff          = cff;
00397     decoder->num_globals  = cff->num_global_subrs;
00398     decoder->globals      = cff->global_subrs;
00399     decoder->globals_bias = cff_compute_bias(
00400                               cff->top_font.font_dict.charstring_type,
00401                               decoder->num_globals );
00402 
00403     decoder->hint_mode    = hint_mode;
00404   }
00405 
00406 
00407   /* this function is used to select the subfont */
00408   /* and the locals subrs array                  */
00409   FT_LOCAL_DEF( FT_Error )
00410   cff_decoder_prepare( CFF_Decoder*  decoder,
00411                        CFF_Size      size,
00412                        FT_UInt       glyph_index )
00413   {
00414     CFF_Builder  *builder = &decoder->builder;
00415     CFF_Font      cff     = (CFF_Font)builder->face->extra.data;
00416     CFF_SubFont   sub     = &cff->top_font;
00417     FT_Error      error   = CFF_Err_Ok;
00418 
00419 
00420     /* manage CID fonts */
00421     if ( cff->num_subfonts )
00422     {
00423       FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
00424 
00425 
00426       if ( fd_index >= cff->num_subfonts )
00427       {
00428         FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
00429         error = CFF_Err_Invalid_File_Format;
00430         goto Exit;
00431       }
00432 
00433       FT_TRACE4(( "glyph index %d (subfont %d):\n", glyph_index, fd_index ));
00434 
00435       sub = cff->subfonts[fd_index];
00436 
00437       if ( builder->hints_funcs && size )
00438       {
00439         CFF_Internal  internal = (CFF_Internal)size->root.internal;
00440 
00441 
00442         /* for CFFs without subfonts, this value has already been set */
00443         builder->hints_globals = (void *)internal->subfonts[fd_index];
00444       }
00445     }
00446 #ifdef FT_DEBUG_LEVEL_TRACE
00447     else
00448       FT_TRACE4(( "glyph index %d:\n", glyph_index ));
00449 #endif
00450 
00451     decoder->num_locals    = sub->num_local_subrs;
00452     decoder->locals        = sub->local_subrs;
00453     decoder->locals_bias   = cff_compute_bias(
00454                                decoder->cff->top_font.font_dict.charstring_type,
00455                                decoder->num_locals );
00456 
00457     decoder->glyph_width   = sub->private_dict.default_width;
00458     decoder->nominal_width = sub->private_dict.nominal_width;
00459 
00460   Exit:
00461     return error;
00462   }
00463 
00464 
00465   /* check that there is enough space for `count' more points */
00466   static FT_Error
00467   check_points( CFF_Builder*  builder,
00468                 FT_Int        count )
00469   {
00470     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
00471   }
00472 
00473 
00474   /* add a new point, do not check space */
00475   static void
00476   cff_builder_add_point( CFF_Builder*  builder,
00477                          FT_Pos        x,
00478                          FT_Pos        y,
00479                          FT_Byte       flag )
00480   {
00481     FT_Outline*  outline = builder->current;
00482 
00483 
00484     if ( builder->load_points )
00485     {
00486       FT_Vector*  point   = outline->points + outline->n_points;
00487       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
00488 
00489 
00490       point->x = x >> 16;
00491       point->y = y >> 16;
00492       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
00493     }
00494 
00495     outline->n_points++;
00496   }
00497 
00498 
00499   /* check space for a new on-curve point, then add it */
00500   static FT_Error
00501   cff_builder_add_point1( CFF_Builder*  builder,
00502                           FT_Pos        x,
00503                           FT_Pos        y )
00504   {
00505     FT_Error  error;
00506 
00507 
00508     error = check_points( builder, 1 );
00509     if ( !error )
00510       cff_builder_add_point( builder, x, y, 1 );
00511 
00512     return error;
00513   }
00514 
00515 
00516   /* check space for a new contour, then add it */
00517   static FT_Error
00518   cff_builder_add_contour( CFF_Builder*  builder )
00519   {
00520     FT_Outline*  outline = builder->current;
00521     FT_Error     error;
00522 
00523 
00524     if ( !builder->load_points )
00525     {
00526       outline->n_contours++;
00527       return CFF_Err_Ok;
00528     }
00529 
00530     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
00531     if ( !error )
00532     {
00533       if ( outline->n_contours > 0 )
00534         outline->contours[outline->n_contours - 1] =
00535           (short)( outline->n_points - 1 );
00536 
00537       outline->n_contours++;
00538     }
00539 
00540     return error;
00541   }
00542 
00543 
00544   /* if a path was begun, add its first on-curve point */
00545   static FT_Error
00546   cff_builder_start_point( CFF_Builder*  builder,
00547                            FT_Pos        x,
00548                            FT_Pos        y )
00549   {
00550     FT_Error  error = CFF_Err_Ok;
00551 
00552 
00553     /* test whether we are building a new contour */
00554     if ( !builder->path_begun )
00555     {
00556       builder->path_begun = 1;
00557       error = cff_builder_add_contour( builder );
00558       if ( !error )
00559         error = cff_builder_add_point1( builder, x, y );
00560     }
00561 
00562     return error;
00563   }
00564 
00565 
00566   /* close the current contour */
00567   static void
00568   cff_builder_close_contour( CFF_Builder*  builder )
00569   {
00570     FT_Outline*  outline = builder->current;
00571     FT_Int       first;
00572 
00573 
00574     if ( !outline )
00575       return;
00576 
00577     first = outline->n_contours <= 1
00578             ? 0 : outline->contours[outline->n_contours - 2] + 1;
00579 
00580     /* We must not include the last point in the path if it */
00581     /* is located on the first point.                       */
00582     if ( outline->n_points > 1 )
00583     {
00584       FT_Vector*  p1      = outline->points + first;
00585       FT_Vector*  p2      = outline->points + outline->n_points - 1;
00586       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
00587 
00588 
00589       /* `delete' last point only if it coincides with the first    */
00590       /* point and if it is not a control point (which can happen). */
00591       if ( p1->x == p2->x && p1->y == p2->y )
00592         if ( *control == FT_CURVE_TAG_ON )
00593           outline->n_points--;
00594     }
00595 
00596     if ( outline->n_contours > 0 )
00597     {
00598       /* Don't add contours only consisting of one point, i.e., */
00599       /* check whether begin point and last point are the same. */
00600       if ( first == outline->n_points - 1 )
00601       {
00602         outline->n_contours--;
00603         outline->n_points--;
00604       }
00605       else
00606         outline->contours[outline->n_contours - 1] =
00607           (short)( outline->n_points - 1 );
00608     }
00609   }
00610 
00611 
00612   static FT_Int
00613   cff_lookup_glyph_by_stdcharcode( CFF_Font  cff,
00614                                    FT_Int    charcode )
00615   {
00616     FT_UInt    n;
00617     FT_UShort  glyph_sid;
00618 
00619 
00620     /* CID-keyed fonts don't have glyph names */
00621     if ( !cff->charset.sids )
00622       return -1;
00623 
00624     /* check range of standard char code */
00625     if ( charcode < 0 || charcode > 255 )
00626       return -1;
00627 
00628     /* Get code to SID mapping from `cff_standard_encoding'. */
00629     glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
00630 
00631     for ( n = 0; n < cff->num_glyphs; n++ )
00632     {
00633       if ( cff->charset.sids[n] == glyph_sid )
00634         return n;
00635     }
00636 
00637     return -1;
00638   }
00639 
00640 
00641   static FT_Error
00642   cff_get_glyph_data( TT_Face    face,
00643                       FT_UInt    glyph_index,
00644                       FT_Byte**  pointer,
00645                       FT_ULong*  length )
00646   {
00647 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00648     /* For incremental fonts get the character data using the */
00649     /* callback function.                                     */
00650     if ( face->root.internal->incremental_interface )
00651     {
00652       FT_Data   data;
00653       FT_Error  error =
00654                   face->root.internal->incremental_interface->funcs->get_glyph_data(
00655                     face->root.internal->incremental_interface->object,
00656                     glyph_index, &data );
00657 
00658 
00659       *pointer = (FT_Byte*)data.pointer;
00660       *length = data.length;
00661 
00662       return error;
00663     }
00664     else
00665 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
00666 
00667     {
00668       CFF_Font  cff  = (CFF_Font)(face->extra.data);
00669 
00670 
00671       return cff_index_access_element( &cff->charstrings_index, glyph_index,
00672                                        pointer, length );
00673     }
00674   }
00675 
00676 
00677   static void
00678   cff_free_glyph_data( TT_Face    face,
00679                        FT_Byte**  pointer,
00680                        FT_ULong   length )
00681   {
00682 #ifndef FT_CONFIG_OPTION_INCREMENTAL
00683     FT_UNUSED( length );
00684 #endif
00685 
00686 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00687     /* For incremental fonts get the character data using the */
00688     /* callback function.                                     */
00689     if ( face->root.internal->incremental_interface )
00690     {
00691       FT_Data data;
00692 
00693 
00694       data.pointer = *pointer;
00695       data.length  = length;
00696 
00697       face->root.internal->incremental_interface->funcs->free_glyph_data(
00698         face->root.internal->incremental_interface->object, &data );
00699     }
00700     else
00701 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
00702 
00703     {
00704       CFF_Font  cff = (CFF_Font)(face->extra.data);
00705 
00706 
00707       cff_index_forget_element( &cff->charstrings_index, pointer );
00708     }
00709   }
00710 
00711 
00712   static FT_Error
00713   cff_operator_seac( CFF_Decoder*  decoder,
00714                      FT_Pos        asb,
00715                      FT_Pos        adx,
00716                      FT_Pos        ady,
00717                      FT_Int        bchar,
00718                      FT_Int        achar )
00719   {
00720     FT_Error      error;
00721     CFF_Builder*  builder = &decoder->builder;
00722     FT_Int        bchar_index, achar_index;
00723     TT_Face       face = decoder->builder.face;
00724     FT_Vector     left_bearing, advance;
00725     FT_Byte*      charstring;
00726     FT_ULong      charstring_len;
00727     FT_Pos        glyph_width;
00728 
00729 
00730     if ( decoder->seac )
00731     {
00732       FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
00733       return CFF_Err_Syntax_Error;
00734     }
00735 
00736     adx += decoder->builder.left_bearing.x;
00737     ady += decoder->builder.left_bearing.y;
00738 
00739 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00740     /* Incremental fonts don't necessarily have valid charsets.        */
00741     /* They use the character code, not the glyph index, in this case. */
00742     if ( face->root.internal->incremental_interface )
00743     {
00744       bchar_index = bchar;
00745       achar_index = achar;
00746     }
00747     else
00748 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
00749     {
00750       CFF_Font cff = (CFF_Font)(face->extra.data);
00751 
00752 
00753       bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
00754       achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
00755     }
00756 
00757     if ( bchar_index < 0 || achar_index < 0 )
00758     {
00759       FT_ERROR(( "cff_operator_seac:"
00760                  " invalid seac character code arguments\n" ));
00761       return CFF_Err_Syntax_Error;
00762     }
00763 
00764     /* If we are trying to load a composite glyph, do not load the */
00765     /* accent character and return the array of subglyphs.         */
00766     if ( builder->no_recurse )
00767     {
00768       FT_GlyphSlot    glyph  = (FT_GlyphSlot)builder->glyph;
00769       FT_GlyphLoader  loader = glyph->internal->loader;
00770       FT_SubGlyph     subg;
00771 
00772 
00773       /* reallocate subglyph array if necessary */
00774       error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
00775       if ( error )
00776         goto Exit;
00777 
00778       subg = loader->current.subglyphs;
00779 
00780       /* subglyph 0 = base character */
00781       subg->index = bchar_index;
00782       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
00783                     FT_SUBGLYPH_FLAG_USE_MY_METRICS;
00784       subg->arg1  = 0;
00785       subg->arg2  = 0;
00786       subg++;
00787 
00788       /* subglyph 1 = accent character */
00789       subg->index = achar_index;
00790       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
00791       subg->arg1  = (FT_Int)( adx >> 16 );
00792       subg->arg2  = (FT_Int)( ady >> 16 );
00793 
00794       /* set up remaining glyph fields */
00795       glyph->num_subglyphs = 2;
00796       glyph->subglyphs     = loader->base.subglyphs;
00797       glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
00798 
00799       loader->current.num_subglyphs = 2;
00800     }
00801 
00802     FT_GlyphLoader_Prepare( builder->loader );
00803 
00804     /* First load `bchar' in builder */
00805     error = cff_get_glyph_data( face, bchar_index,
00806                                 &charstring, &charstring_len );
00807     if ( !error )
00808     {
00809       /* the seac operator must not be nested */
00810       decoder->seac = TRUE;
00811       error = cff_decoder_parse_charstrings( decoder, charstring,
00812                                              charstring_len );
00813       decoder->seac = FALSE;
00814 
00815       if ( error )
00816         goto Exit;
00817 
00818       cff_free_glyph_data( face, &charstring, charstring_len );
00819     }
00820 
00821     /* Save the left bearing, advance and glyph width of the base */
00822     /* character as they will be erased by the next load.         */
00823 
00824     left_bearing = builder->left_bearing;
00825     advance      = builder->advance;
00826     glyph_width  = decoder->glyph_width;
00827 
00828     builder->left_bearing.x = 0;
00829     builder->left_bearing.y = 0;
00830 
00831     builder->pos_x = adx - asb;
00832     builder->pos_y = ady;
00833 
00834     /* Now load `achar' on top of the base outline. */
00835     error = cff_get_glyph_data( face, achar_index,
00836                                 &charstring, &charstring_len );
00837     if ( !error )
00838     {
00839       /* the seac operator must not be nested */
00840       decoder->seac = TRUE;
00841       error = cff_decoder_parse_charstrings( decoder, charstring,
00842                                              charstring_len );
00843       decoder->seac = FALSE;
00844 
00845       if ( error )
00846         goto Exit;
00847 
00848       cff_free_glyph_data( face, &charstring, charstring_len );
00849     }
00850 
00851     /* Restore the left side bearing, advance and glyph width */
00852     /* of the base character.                                 */
00853     builder->left_bearing = left_bearing;
00854     builder->advance      = advance;
00855     decoder->glyph_width  = glyph_width;
00856 
00857     builder->pos_x = 0;
00858     builder->pos_y = 0;
00859 
00860   Exit:
00861     return error;
00862   }
00863 
00864 
00865   /*************************************************************************/
00866   /*                                                                       */
00867   /* <Function>                                                            */
00868   /*    cff_decoder_parse_charstrings                                      */
00869   /*                                                                       */
00870   /* <Description>                                                         */
00871   /*    Parses a given Type 2 charstrings program.                         */
00872   /*                                                                       */
00873   /* <InOut>                                                               */
00874   /*    decoder         :: The current Type 1 decoder.                     */
00875   /*                                                                       */
00876   /* <Input>                                                               */
00877   /*    charstring_base :: The base of the charstring stream.              */
00878   /*                                                                       */
00879   /*    charstring_len  :: The length in bytes of the charstring stream.   */
00880   /*                                                                       */
00881   /* <Return>                                                              */
00882   /*    FreeType error code.  0 means success.                             */
00883   /*                                                                       */
00884   FT_LOCAL_DEF( FT_Error )
00885   cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
00886                                  FT_Byte*      charstring_base,
00887                                  FT_ULong      charstring_len )
00888   {
00889     FT_Error           error;
00890     CFF_Decoder_Zone*  zone;
00891     FT_Byte*           ip;
00892     FT_Byte*           limit;
00893     CFF_Builder*       builder = &decoder->builder;
00894     FT_Pos             x, y;
00895     FT_Fixed           seed;
00896     FT_Fixed*          stack;
00897     FT_Int             charstring_type =
00898                          decoder->cff->top_font.font_dict.charstring_type;
00899 
00900     T2_Hints_Funcs     hinter;
00901 
00902 
00903     /* set default width */
00904     decoder->num_hints  = 0;
00905     decoder->read_width = 1;
00906 
00907     /* compute random seed from stack address of parameter */
00908     seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed              ^
00909                          (FT_PtrDist)(char*)&decoder           ^
00910                          (FT_PtrDist)(char*)&charstring_base ) &
00911                          FT_ULONG_MAX ) ;
00912     seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
00913     if ( seed == 0 )
00914       seed = 0x7384;
00915 
00916     /* initialize the decoder */
00917     decoder->top  = decoder->stack;
00918     decoder->zone = decoder->zones;
00919     zone          = decoder->zones;
00920     stack         = decoder->top;
00921 
00922     hinter = (T2_Hints_Funcs)builder->hints_funcs;
00923 
00924     builder->path_begun = 0;
00925 
00926     zone->base           = charstring_base;
00927     limit = zone->limit  = charstring_base + charstring_len;
00928     ip    = zone->cursor = zone->base;
00929 
00930     error = CFF_Err_Ok;
00931 
00932     x = builder->pos_x;
00933     y = builder->pos_y;
00934 
00935     /* begin hints recording session, if any */
00936     if ( hinter )
00937       hinter->open( hinter->hints );
00938 
00939     /* now execute loop */
00940     while ( ip < limit )
00941     {
00942       CFF_Operator  op;
00943       FT_Byte       v;
00944 
00945 
00946       /********************************************************************/
00947       /*                                                                  */
00948       /* Decode operator or operand                                       */
00949       /*                                                                  */
00950       v = *ip++;
00951       if ( v >= 32 || v == 28 )
00952       {
00953         FT_Int    shift = 16;
00954         FT_Int32  val;
00955 
00956 
00957         /* this is an operand, push it on the stack */
00958         if ( v == 28 )
00959         {
00960           if ( ip + 1 >= limit )
00961             goto Syntax_Error;
00962           val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
00963           ip += 2;
00964         }
00965         else if ( v < 247 )
00966           val = (FT_Int32)v - 139;
00967         else if ( v < 251 )
00968         {
00969           if ( ip >= limit )
00970             goto Syntax_Error;
00971           val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108;
00972         }
00973         else if ( v < 255 )
00974         {
00975           if ( ip >= limit )
00976             goto Syntax_Error;
00977           val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108;
00978         }
00979         else
00980         {
00981           if ( ip + 3 >= limit )
00982             goto Syntax_Error;
00983           val = ( (FT_Int32)ip[0] << 24 ) |
00984                 ( (FT_Int32)ip[1] << 16 ) |
00985                 ( (FT_Int32)ip[2] <<  8 ) |
00986                             ip[3];
00987           ip    += 4;
00988           if ( charstring_type == 2 )
00989             shift = 0;
00990         }
00991         if ( decoder->top - stack >= CFF_MAX_OPERANDS )
00992           goto Stack_Overflow;
00993 
00994         val           <<= shift;
00995         *decoder->top++ = val;
00996 
00997 #ifdef FT_DEBUG_LEVEL_TRACE
00998         if ( !( val & 0xFFFFL ) )
00999           FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) ));
01000         else
01001           FT_TRACE4(( " %.2f", val / 65536.0 ));
01002 #endif
01003 
01004       }
01005       else
01006       {
01007         /* The specification says that normally arguments are to be taken */
01008         /* from the bottom of the stack.  However, this seems not to be   */
01009         /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
01010         /* arguments similar to a PS interpreter.                         */
01011 
01012         FT_Fixed*  args     = decoder->top;
01013         FT_Int     num_args = (FT_Int)( args - decoder->stack );
01014         FT_Int     req_args;
01015 
01016 
01017         /* find operator */
01018         op = cff_op_unknown;
01019 
01020         switch ( v )
01021         {
01022         case 1:
01023           op = cff_op_hstem;
01024           break;
01025         case 3:
01026           op = cff_op_vstem;
01027           break;
01028         case 4:
01029           op = cff_op_vmoveto;
01030           break;
01031         case 5:
01032           op = cff_op_rlineto;
01033           break;
01034         case 6:
01035           op = cff_op_hlineto;
01036           break;
01037         case 7:
01038           op = cff_op_vlineto;
01039           break;
01040         case 8:
01041           op = cff_op_rrcurveto;
01042           break;
01043         case 9:
01044           op = cff_op_closepath;
01045           break;
01046         case 10:
01047           op = cff_op_callsubr;
01048           break;
01049         case 11:
01050           op = cff_op_return;
01051           break;
01052         case 12:
01053           {
01054             if ( ip >= limit )
01055               goto Syntax_Error;
01056             v = *ip++;
01057 
01058             switch ( v )
01059             {
01060             case 0:
01061               op = cff_op_dotsection;
01062               break;
01063             case 1: /* this is actually the Type1 vstem3 operator */
01064               op = cff_op_vstem;
01065               break;
01066             case 2: /* this is actually the Type1 hstem3 operator */
01067               op = cff_op_hstem;
01068               break;
01069             case 3:
01070               op = cff_op_and;
01071               break;
01072             case 4:
01073               op = cff_op_or;
01074               break;
01075             case 5:
01076               op = cff_op_not;
01077               break;
01078             case 6:
01079               op = cff_op_seac;
01080               break;
01081             case 7:
01082               op = cff_op_sbw;
01083               break;
01084             case 8:
01085               op = cff_op_store;
01086               break;
01087             case 9:
01088               op = cff_op_abs;
01089               break;
01090             case 10:
01091               op = cff_op_add;
01092               break;
01093             case 11:
01094               op = cff_op_sub;
01095               break;
01096             case 12:
01097               op = cff_op_div;
01098               break;
01099             case 13:
01100               op = cff_op_load;
01101               break;
01102             case 14:
01103               op = cff_op_neg;
01104               break;
01105             case 15:
01106               op = cff_op_eq;
01107               break;
01108             case 16:
01109               op = cff_op_callothersubr;
01110               break;
01111             case 17:
01112               op = cff_op_pop;
01113               break;
01114             case 18:
01115               op = cff_op_drop;
01116               break;
01117             case 20:
01118               op = cff_op_put;
01119               break;
01120             case 21:
01121               op = cff_op_get;
01122               break;
01123             case 22:
01124               op = cff_op_ifelse;
01125               break;
01126             case 23:
01127               op = cff_op_random;
01128               break;
01129             case 24:
01130               op = cff_op_mul;
01131               break;
01132             case 26:
01133               op = cff_op_sqrt;
01134               break;
01135             case 27:
01136               op = cff_op_dup;
01137               break;
01138             case 28:
01139               op = cff_op_exch;
01140               break;
01141             case 29:
01142               op = cff_op_index;
01143               break;
01144             case 30:
01145               op = cff_op_roll;
01146               break;
01147             case 33:
01148               op = cff_op_setcurrentpoint;
01149               break;
01150             case 34:
01151               op = cff_op_hflex;
01152               break;
01153             case 35:
01154               op = cff_op_flex;
01155               break;
01156             case 36:
01157               op = cff_op_hflex1;
01158               break;
01159             case 37:
01160               op = cff_op_flex1;
01161               break;
01162             default:
01163               /* decrement ip for syntax error message */
01164               ip--;
01165             }
01166           }
01167           break;
01168         case 13:
01169           op = cff_op_hsbw;
01170           break;
01171         case 14:
01172           op = cff_op_endchar;
01173           break;
01174         case 16:
01175           op = cff_op_blend;
01176           break;
01177         case 18:
01178           op = cff_op_hstemhm;
01179           break;
01180         case 19:
01181           op = cff_op_hintmask;
01182           break;
01183         case 20:
01184           op = cff_op_cntrmask;
01185           break;
01186         case 21:
01187           op = cff_op_rmoveto;
01188           break;
01189         case 22:
01190           op = cff_op_hmoveto;
01191           break;
01192         case 23:
01193           op = cff_op_vstemhm;
01194           break;
01195         case 24:
01196           op = cff_op_rcurveline;
01197           break;
01198         case 25:
01199           op = cff_op_rlinecurve;
01200           break;
01201         case 26:
01202           op = cff_op_vvcurveto;
01203           break;
01204         case 27:
01205           op = cff_op_hhcurveto;
01206           break;
01207         case 29:
01208           op = cff_op_callgsubr;
01209           break;
01210         case 30:
01211           op = cff_op_vhcurveto;
01212           break;
01213         case 31:
01214           op = cff_op_hvcurveto;
01215           break;
01216         default:
01217           break;
01218         }
01219 
01220         if ( op == cff_op_unknown )
01221           goto Syntax_Error;
01222 
01223         /* check arguments */
01224         req_args = cff_argument_counts[op];
01225         if ( req_args & CFF_COUNT_CHECK_WIDTH )
01226         {
01227           if ( num_args > 0 && decoder->read_width )
01228           {
01229             /* If `nominal_width' is non-zero, the number is really a      */
01230             /* difference against `nominal_width'.  Else, the number here  */
01231             /* is truly a width, not a difference against `nominal_width'. */
01232             /* If the font does not set `nominal_width', then              */
01233             /* `nominal_width' defaults to zero, and so we can set         */
01234             /* `glyph_width' to `nominal_width' plus number on the stack   */
01235             /* -- for either case.                                         */
01236 
01237             FT_Int  set_width_ok;
01238 
01239 
01240             switch ( op )
01241             {
01242             case cff_op_hmoveto:
01243             case cff_op_vmoveto:
01244               set_width_ok = num_args & 2;
01245               break;
01246 
01247             case cff_op_hstem:
01248             case cff_op_vstem:
01249             case cff_op_hstemhm:
01250             case cff_op_vstemhm:
01251             case cff_op_rmoveto:
01252             case cff_op_hintmask:
01253             case cff_op_cntrmask:
01254               set_width_ok = num_args & 1;
01255               break;
01256 
01257             case cff_op_endchar:
01258               /* If there is a width specified for endchar, we either have */
01259               /* 1 argument or 5 arguments.  We like to argue.             */
01260               set_width_ok = ( num_args == 5 ) || ( num_args == 1 );
01261               break;
01262 
01263             default:
01264               set_width_ok = 0;
01265               break;
01266             }
01267 
01268             if ( set_width_ok )
01269             {
01270               decoder->glyph_width = decoder->nominal_width +
01271                                        ( stack[0] >> 16 );
01272 
01273               if ( decoder->width_only )
01274               {
01275                 /* we only want the advance width; stop here */
01276                 break;
01277               }
01278 
01279               /* Consumed an argument. */
01280               num_args--;
01281             }
01282           }
01283 
01284           decoder->read_width = 0;
01285           req_args            = 0;
01286         }
01287 
01288         req_args &= 0x000F;
01289         if ( num_args < req_args )
01290           goto Stack_Underflow;
01291         args     -= req_args;
01292         num_args -= req_args;
01293 
01294         /* At this point, `args' points to the first argument of the  */
01295         /* operand in case `req_args' isn't zero.  Otherwise, we have */
01296         /* to adjust `args' manually.                                 */
01297 
01298         /* Note that we only pop arguments from the stack which we    */
01299         /* really need and can digest so that we can continue in case */
01300         /* of superfluous stack elements.                             */
01301 
01302         switch ( op )
01303         {
01304         case cff_op_hstem:
01305         case cff_op_vstem:
01306         case cff_op_hstemhm:
01307         case cff_op_vstemhm:
01308           /* the number of arguments is always even here */
01309           FT_TRACE4((
01310               op == cff_op_hstem   ? " hstem\n"   :
01311             ( op == cff_op_vstem   ? " vstem\n"   :
01312             ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) ));
01313 
01314           if ( hinter )
01315             hinter->stems( hinter->hints,
01316                            ( op == cff_op_hstem || op == cff_op_hstemhm ),
01317                            num_args / 2,
01318                            args - ( num_args & ~1 ) );
01319 
01320           decoder->num_hints += num_args / 2;
01321           args = stack;
01322           break;
01323 
01324         case cff_op_hintmask:
01325         case cff_op_cntrmask:
01326           FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
01327 
01328           /* implement vstem when needed --                        */
01329           /* the specification doesn't say it, but this also works */
01330           /* with the 'cntrmask' operator                          */
01331           /*                                                       */
01332           if ( num_args > 0 )
01333           {
01334             if ( hinter )
01335               hinter->stems( hinter->hints,
01336                              0,
01337                              num_args / 2,
01338                              args - ( num_args & ~1 ) );
01339 
01340             decoder->num_hints += num_args / 2;
01341           }
01342 
01343           if ( hinter )
01344           {
01345             if ( op == cff_op_hintmask )
01346               hinter->hintmask( hinter->hints,
01347                                 builder->current->n_points,
01348                                 decoder->num_hints,
01349                                 ip );
01350             else
01351               hinter->counter( hinter->hints,
01352                                decoder->num_hints,
01353                                ip );
01354           }
01355 
01356 #ifdef FT_DEBUG_LEVEL_TRACE
01357           {
01358             FT_UInt maskbyte;
01359 
01360 
01361             FT_TRACE4(( " (maskbytes: " ));
01362 
01363             for ( maskbyte = 0;
01364                   maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3);
01365                   maskbyte++, ip++ )
01366               FT_TRACE4(( "0x%02X", *ip ));
01367 
01368             FT_TRACE4(( ")\n" ));
01369           }
01370 #else
01371           ip += ( decoder->num_hints + 7 ) >> 3;
01372 #endif
01373           if ( ip >= limit )
01374             goto Syntax_Error;
01375           args = stack;
01376           break;
01377 
01378         case cff_op_rmoveto:
01379           FT_TRACE4(( " rmoveto\n" ));
01380 
01381           cff_builder_close_contour( builder );
01382           builder->path_begun = 0;
01383           x   += args[-2];
01384           y   += args[-1];
01385           args = stack;
01386           break;
01387 
01388         case cff_op_vmoveto:
01389           FT_TRACE4(( " vmoveto\n" ));
01390 
01391           cff_builder_close_contour( builder );
01392           builder->path_begun = 0;
01393           y   += args[-1];
01394           args = stack;
01395           break;
01396 
01397         case cff_op_hmoveto:
01398           FT_TRACE4(( " hmoveto\n" ));
01399 
01400           cff_builder_close_contour( builder );
01401           builder->path_begun = 0;
01402           x   += args[-1];
01403           args = stack;
01404           break;
01405 
01406         case cff_op_rlineto:
01407           FT_TRACE4(( " rlineto\n" ));
01408 
01409           if ( cff_builder_start_point ( builder, x, y ) ||
01410                check_points( builder, num_args / 2 )     )
01411             goto Fail;
01412 
01413           if ( num_args < 2 )
01414             goto Stack_Underflow;
01415 
01416           args -= num_args & ~1;
01417           while ( args < decoder->top )
01418           {
01419             x += args[0];
01420             y += args[1];
01421             cff_builder_add_point( builder, x, y, 1 );
01422             args += 2;
01423           }
01424           args = stack;
01425           break;
01426 
01427         case cff_op_hlineto:
01428         case cff_op_vlineto:
01429           {
01430             FT_Int  phase = ( op == cff_op_hlineto );
01431 
01432 
01433             FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
01434                                              : " vlineto\n" ));
01435 
01436             if ( num_args < 1 )
01437               goto Stack_Underflow;
01438 
01439             if ( cff_builder_start_point ( builder, x, y ) ||
01440                  check_points( builder, num_args )         )
01441               goto Fail;
01442 
01443             args = stack;
01444             while ( args < decoder->top )
01445             {
01446               if ( phase )
01447                 x += args[0];
01448               else
01449                 y += args[0];
01450 
01451               if ( cff_builder_add_point1( builder, x, y ) )
01452                 goto Fail;
01453 
01454               args++;
01455               phase ^= 1;
01456             }
01457             args = stack;
01458           }
01459           break;
01460 
01461         case cff_op_rrcurveto:
01462           {
01463             FT_Int  nargs;
01464 
01465 
01466             FT_TRACE4(( " rrcurveto\n" ));
01467 
01468             if ( num_args < 6 )
01469               goto Stack_Underflow;
01470 
01471             nargs = num_args - num_args % 6;
01472 
01473             if ( cff_builder_start_point ( builder, x, y ) ||
01474                  check_points( builder, nargs / 2 )     )
01475               goto Fail;
01476 
01477             args -= nargs;
01478             while ( args < decoder->top )
01479             {
01480               x += args[0];
01481               y += args[1];
01482               cff_builder_add_point( builder, x, y, 0 );
01483               x += args[2];
01484               y += args[3];
01485               cff_builder_add_point( builder, x, y, 0 );
01486               x += args[4];
01487               y += args[5];
01488               cff_builder_add_point( builder, x, y, 1 );
01489               args += 6;
01490             }
01491             args = stack;
01492           }
01493           break;
01494 
01495         case cff_op_vvcurveto:
01496           {
01497             FT_Int  nargs;
01498 
01499 
01500             FT_TRACE4(( " vvcurveto\n" ));
01501 
01502             if ( num_args < 4 )
01503               goto Stack_Underflow;
01504 
01505             /* if num_args isn't of the form 4n or 4n+1, */
01506             /* we reduce it to 4n+1                      */
01507 
01508             nargs = num_args - num_args % 4;
01509             if ( num_args - nargs > 0 )
01510               nargs += 1;
01511 
01512             if ( cff_builder_start_point( builder, x, y ) )
01513               goto Fail;
01514 
01515             args -= nargs;
01516 
01517             if ( nargs & 1 )
01518             {
01519               x += args[0];
01520               args++;
01521               nargs--;
01522             }
01523 
01524             if ( check_points( builder, 3 * ( nargs / 4 ) ) )
01525               goto Fail;
01526 
01527             while ( args < decoder->top )
01528             {
01529               y += args[0];
01530               cff_builder_add_point( builder, x, y, 0 );
01531               x += args[1];
01532               y += args[2];
01533               cff_builder_add_point( builder, x, y, 0 );
01534               y += args[3];
01535               cff_builder_add_point( builder, x, y, 1 );
01536               args += 4;
01537             }
01538             args = stack;
01539           }
01540           break;
01541 
01542         case cff_op_hhcurveto:
01543           {
01544             FT_Int  nargs;
01545 
01546 
01547             FT_TRACE4(( " hhcurveto\n" ));
01548 
01549             if ( num_args < 4 )
01550               goto Stack_Underflow;
01551 
01552             /* if num_args isn't of the form 4n or 4n+1, */
01553             /* we reduce it to 4n+1                      */
01554 
01555             nargs = num_args - num_args % 4;
01556             if ( num_args - nargs > 0 )
01557               nargs += 1;
01558 
01559             if ( cff_builder_start_point( builder, x, y ) )
01560               goto Fail;
01561 
01562             args -= nargs;
01563             if ( nargs & 1 )
01564             {
01565               y += args[0];
01566               args++;
01567               nargs--;
01568             }
01569 
01570             if ( check_points( builder, 3 * ( nargs / 4 ) ) )
01571               goto Fail;
01572 
01573             while ( args < decoder->top )
01574             {
01575               x += args[0];
01576               cff_builder_add_point( builder, x, y, 0 );
01577               x += args[1];
01578               y += args[2];
01579               cff_builder_add_point( builder, x, y, 0 );
01580               x += args[3];
01581               cff_builder_add_point( builder, x, y, 1 );
01582               args += 4;
01583             }
01584             args = stack;
01585           }
01586           break;
01587 
01588         case cff_op_vhcurveto:
01589         case cff_op_hvcurveto:
01590           {
01591             FT_Int  phase;
01592             FT_Int  nargs;
01593 
01594 
01595             FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n"
01596                                                : " hvcurveto\n" ));
01597 
01598             if ( cff_builder_start_point( builder, x, y ) )
01599               goto Fail;
01600 
01601             if ( num_args < 4 )
01602               goto Stack_Underflow;
01603 
01604             /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
01605             /* we reduce it to the largest one which fits             */
01606 
01607             nargs = num_args - num_args % 4;
01608             if ( num_args - nargs > 0 )
01609               nargs += 1;
01610 
01611             args -= nargs;
01612             if ( check_points( builder, ( nargs / 4 ) * 3 ) )
01613               goto Stack_Underflow;
01614 
01615             phase = ( op == cff_op_hvcurveto );
01616 
01617             while ( nargs >= 4 )
01618             {
01619               nargs -= 4;
01620               if ( phase )
01621               {
01622                 x += args[0];
01623                 cff_builder_add_point( builder, x, y, 0 );
01624                 x += args[1];
01625                 y += args[2];
01626                 cff_builder_add_point( builder, x, y, 0 );
01627                 y += args[3];
01628                 if ( nargs == 1 )
01629                   x += args[4];
01630                 cff_builder_add_point( builder, x, y, 1 );
01631               }
01632               else
01633               {
01634                 y += args[0];
01635                 cff_builder_add_point( builder, x, y, 0 );
01636                 x += args[1];
01637                 y += args[2];
01638                 cff_builder_add_point( builder, x, y, 0 );
01639                 x += args[3];
01640                 if ( nargs == 1 )
01641                   y += args[4];
01642                 cff_builder_add_point( builder, x, y, 1 );
01643               }
01644               args  += 4;
01645               phase ^= 1;
01646             }
01647             args = stack;
01648           }
01649           break;
01650 
01651         case cff_op_rlinecurve:
01652           {
01653             FT_Int  num_lines;
01654             FT_Int  nargs;
01655 
01656 
01657             FT_TRACE4(( " rlinecurve\n" ));
01658 
01659             if ( num_args < 8 )
01660               goto Stack_Underflow;
01661 
01662             nargs     = num_args & ~1;
01663             num_lines = ( nargs - 6 ) / 2;
01664 
01665             if ( cff_builder_start_point( builder, x, y ) ||
01666                  check_points( builder, num_lines + 3 )   )
01667               goto Fail;
01668 
01669             args -= nargs;
01670 
01671             /* first, add the line segments */
01672             while ( num_lines > 0 )
01673             {
01674               x += args[0];
01675               y += args[1];
01676               cff_builder_add_point( builder, x, y, 1 );
01677               args += 2;
01678               num_lines--;
01679             }
01680 
01681             /* then the curve */
01682             x += args[0];
01683             y += args[1];
01684             cff_builder_add_point( builder, x, y, 0 );
01685             x += args[2];
01686             y += args[3];
01687             cff_builder_add_point( builder, x, y, 0 );
01688             x += args[4];
01689             y += args[5];
01690             cff_builder_add_point( builder, x, y, 1 );
01691             args = stack;
01692           }
01693           break;
01694 
01695         case cff_op_rcurveline:
01696           {
01697             FT_Int  num_curves;
01698             FT_Int  nargs;
01699 
01700 
01701             FT_TRACE4(( " rcurveline\n" ));
01702 
01703             if ( num_args < 8 )
01704               goto Stack_Underflow;
01705 
01706             nargs      = num_args - 2;
01707             nargs      = nargs - nargs % 6 + 2;
01708             num_curves = ( nargs - 2 ) / 6;
01709 
01710             if ( cff_builder_start_point ( builder, x, y ) ||
01711                  check_points( builder, num_curves * 3 + 2 ) )
01712               goto Fail;
01713 
01714             args -= nargs;
01715 
01716             /* first, add the curves */
01717             while ( num_curves > 0 )
01718             {
01719               x += args[0];
01720               y += args[1];
01721               cff_builder_add_point( builder, x, y, 0 );
01722               x += args[2];
01723               y += args[3];
01724               cff_builder_add_point( builder, x, y, 0 );
01725               x += args[4];
01726               y += args[5];
01727               cff_builder_add_point( builder, x, y, 1 );
01728               args += 6;
01729               num_curves--;
01730             }
01731 
01732             /* then the final line */
01733             x += args[0];
01734             y += args[1];
01735             cff_builder_add_point( builder, x, y, 1 );
01736             args = stack;
01737           }
01738           break;
01739 
01740         case cff_op_hflex1:
01741           {
01742             FT_Pos start_y;
01743 
01744 
01745             FT_TRACE4(( " hflex1\n" ));
01746 
01747             /* adding five more points: 4 control points, 1 on-curve point */
01748             /* -- make sure we have enough space for the start point if it */
01749             /* needs to be added                                           */
01750             if ( cff_builder_start_point( builder, x, y ) ||
01751                  check_points( builder, 6 )               )
01752               goto Fail;
01753 
01754             /* record the starting point's y position for later use */
01755             start_y = y;
01756 
01757             /* first control point */
01758             x += args[0];
01759             y += args[1];
01760             cff_builder_add_point( builder, x, y, 0 );
01761 
01762             /* second control point */
01763             x += args[2];
01764             y += args[3];
01765             cff_builder_add_point( builder, x, y, 0 );
01766 
01767             /* join point; on curve, with y-value the same as the last */
01768             /* control point's y-value                                 */
01769             x += args[4];
01770             cff_builder_add_point( builder, x, y, 1 );
01771 
01772             /* third control point, with y-value the same as the join */
01773             /* point's y-value                                        */
01774             x += args[5];
01775             cff_builder_add_point( builder, x, y, 0 );
01776 
01777             /* fourth control point */
01778             x += args[6];
01779             y += args[7];
01780             cff_builder_add_point( builder, x, y, 0 );
01781 
01782             /* ending point, with y-value the same as the start   */
01783             x += args[8];
01784             y  = start_y;
01785             cff_builder_add_point( builder, x, y, 1 );
01786 
01787             args = stack;
01788             break;
01789           }
01790 
01791         case cff_op_hflex:
01792           {
01793             FT_Pos start_y;
01794 
01795 
01796             FT_TRACE4(( " hflex\n" ));
01797 
01798             /* adding six more points; 4 control points, 2 on-curve points */
01799             if ( cff_builder_start_point( builder, x, y ) ||
01800                  check_points( builder, 6 )               )
01801               goto Fail;
01802 
01803             /* record the starting point's y-position for later use */
01804             start_y = y;
01805 
01806             /* first control point */
01807             x += args[0];
01808             cff_builder_add_point( builder, x, y, 0 );
01809 
01810             /* second control point */
01811             x += args[1];
01812             y += args[2];
01813             cff_builder_add_point( builder, x, y, 0 );
01814 
01815             /* join point; on curve, with y-value the same as the last */
01816             /* control point's y-value                                 */
01817             x += args[3];
01818             cff_builder_add_point( builder, x, y, 1 );
01819 
01820             /* third control point, with y-value the same as the join */
01821             /* point's y-value                                        */
01822             x += args[4];
01823             cff_builder_add_point( builder, x, y, 0 );
01824 
01825             /* fourth control point */
01826             x += args[5];
01827             y  = start_y;
01828             cff_builder_add_point( builder, x, y, 0 );
01829 
01830             /* ending point, with y-value the same as the start point's */
01831             /* y-value -- we don't add this point, though               */
01832             x += args[6];
01833             cff_builder_add_point( builder, x, y, 1 );
01834 
01835             args = stack;
01836             break;
01837           }
01838 
01839         case cff_op_flex1:
01840           {
01841             FT_Pos     start_x, start_y; /* record start x, y values for */
01842                                          /* alter use                    */
01843             FT_Fixed   dx = 0, dy = 0;   /* used in horizontal/vertical  */
01844                                          /* algorithm below              */
01845             FT_Int     horizontal, count;
01846             FT_Fixed*  temp;
01847 
01848 
01849             FT_TRACE4(( " flex1\n" ));
01850 
01851             /* adding six more points; 4 control points, 2 on-curve points */
01852             if ( cff_builder_start_point( builder, x, y ) ||
01853                  check_points( builder, 6 )               )
01854               goto Fail;
01855 
01856             /* record the starting point's x, y position for later use */
01857             start_x = x;
01858             start_y = y;
01859 
01860             /* XXX: figure out whether this is supposed to be a horizontal */
01861             /*      or vertical flex; the Type 2 specification is vague... */
01862 
01863             temp = args;
01864 
01865             /* grab up to the last argument */
01866             for ( count = 5; count > 0; count-- )
01867             {
01868               dx += temp[0];
01869               dy += temp[1];
01870               temp += 2;
01871             }
01872 
01873             if ( dx < 0 )
01874               dx = -dx;
01875             if ( dy < 0 )
01876               dy = -dy;
01877 
01878             /* strange test, but here it is... */
01879             horizontal = ( dx > dy );
01880 
01881             for ( count = 5; count > 0; count-- )
01882             {
01883               x += args[0];
01884               y += args[1];
01885               cff_builder_add_point( builder, x, y,
01886                                      (FT_Bool)( count == 3 ) );
01887               args += 2;
01888             }
01889 
01890             /* is last operand an x- or y-delta? */
01891             if ( horizontal )
01892             {
01893               x += args[0];
01894               y  = start_y;
01895             }
01896             else
01897             {
01898               x  = start_x;
01899               y += args[0];
01900             }
01901 
01902             cff_builder_add_point( builder, x, y, 1 );
01903 
01904             args = stack;
01905             break;
01906            }
01907 
01908         case cff_op_flex:
01909           {
01910             FT_UInt  count;
01911 
01912 
01913             FT_TRACE4(( " flex\n" ));
01914 
01915             if ( cff_builder_start_point( builder, x, y ) ||
01916                  check_points( builder, 6 )               )
01917               goto Fail;
01918 
01919             for ( count = 6; count > 0; count-- )
01920             {
01921               x += args[0];
01922               y += args[1];
01923               cff_builder_add_point( builder, x, y,
01924                                      (FT_Bool)( count == 4 || count == 1 ) );
01925               args += 2;
01926             }
01927 
01928             args = stack;
01929           }
01930           break;
01931 
01932         case cff_op_seac:
01933             FT_TRACE4(( " seac\n" ));
01934 
01935             error = cff_operator_seac( decoder,
01936                                        args[0], args[1], args[2],
01937                                        (FT_Int)( args[3] >> 16 ),
01938                                        (FT_Int)( args[4] >> 16 ) );
01939 
01940             /* add current outline to the glyph slot */
01941             FT_GlyphLoader_Add( builder->loader );
01942 
01943             /* return now! */
01944             FT_TRACE4(( "\n" ));
01945             return error;
01946 
01947         case cff_op_endchar:
01948           FT_TRACE4(( " endchar\n" ));
01949 
01950           /* We are going to emulate the seac operator. */
01951           if ( num_args >= 4 )
01952           {
01953             /* Save glyph width so that the subglyphs don't overwrite it. */
01954             FT_Pos  glyph_width = decoder->glyph_width;
01955 
01956             error = cff_operator_seac( decoder,
01957                                        0L, args[-4], args[-3],
01958                                        (FT_Int)( args[-2] >> 16 ),
01959                                        (FT_Int)( args[-1] >> 16 ) );
01960 
01961             decoder->glyph_width = glyph_width;
01962           }
01963           else
01964           {
01965             if ( !error )
01966               error = CFF_Err_Ok;
01967 
01968             cff_builder_close_contour( builder );
01969 
01970             /* close hints recording session */
01971             if ( hinter )
01972             {
01973               if ( hinter->close( hinter->hints,
01974                                   builder->current->n_points ) )
01975                 goto Syntax_Error;
01976 
01977               /* apply hints to the loaded glyph outline now */
01978               hinter->apply( hinter->hints,
01979                              builder->current,
01980                              (PSH_Globals)builder->hints_globals,
01981                              decoder->hint_mode );
01982             }
01983 
01984             /* add current outline to the glyph slot */
01985             FT_GlyphLoader_Add( builder->loader );
01986           }
01987 
01988           /* return now! */
01989           FT_TRACE4(( "\n" ));
01990           return error;
01991 
01992         case cff_op_abs:
01993           FT_TRACE4(( " abs\n" ));
01994 
01995           if ( args[0] < 0 )
01996             args[0] = -args[0];
01997           args++;
01998           break;
01999 
02000         case cff_op_add:
02001           FT_TRACE4(( " add\n" ));
02002 
02003           args[0] += args[1];
02004           args++;
02005           break;
02006 
02007         case cff_op_sub:
02008           FT_TRACE4(( " sub\n" ));
02009 
02010           args[0] -= args[1];
02011           args++;
02012           break;
02013 
02014         case cff_op_div:
02015           FT_TRACE4(( " div\n" ));
02016 
02017           args[0] = FT_DivFix( args[0], args[1] );
02018           args++;
02019           break;
02020 
02021         case cff_op_neg:
02022           FT_TRACE4(( " neg\n" ));
02023 
02024           args[0] = -args[0];
02025           args++;
02026           break;
02027 
02028         case cff_op_random:
02029           {
02030             FT_Fixed  Rand;
02031 
02032 
02033             FT_TRACE4(( " rand\n" ));
02034 
02035             Rand = seed;
02036             if ( Rand >= 0x8000L )
02037               Rand++;
02038 
02039             args[0] = Rand;
02040             seed    = FT_MulFix( seed, 0x10000L - seed );
02041             if ( seed == 0 )
02042               seed += 0x2873;
02043             args++;
02044           }
02045           break;
02046 
02047         case cff_op_mul:
02048           FT_TRACE4(( " mul\n" ));
02049 
02050           args[0] = FT_MulFix( args[0], args[1] );
02051           args++;
02052           break;
02053 
02054         case cff_op_sqrt:
02055           FT_TRACE4(( " sqrt\n" ));
02056 
02057           if ( args[0] > 0 )
02058           {
02059             FT_Int    count = 9;
02060             FT_Fixed  root  = args[0];
02061             FT_Fixed  new_root;
02062 
02063 
02064             for (;;)
02065             {
02066               new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
02067               if ( new_root == root || count <= 0 )
02068                 break;
02069               root = new_root;
02070             }
02071             args[0] = new_root;
02072           }
02073           else
02074             args[0] = 0;
02075           args++;
02076           break;
02077 
02078         case cff_op_drop:
02079           /* nothing */
02080           FT_TRACE4(( " drop\n" ));
02081 
02082           break;
02083 
02084         case cff_op_exch:
02085           {
02086             FT_Fixed  tmp;
02087 
02088 
02089             FT_TRACE4(( " exch\n" ));
02090 
02091             tmp     = args[0];
02092             args[0] = args[1];
02093             args[1] = tmp;
02094             args   += 2;
02095           }
02096           break;
02097 
02098         case cff_op_index:
02099           {
02100             FT_Int  idx = (FT_Int)( args[0] >> 16 );
02101 
02102 
02103             FT_TRACE4(( " index\n" ));
02104 
02105             if ( idx < 0 )
02106               idx = 0;
02107             else if ( idx > num_args - 2 )
02108               idx = num_args - 2;
02109             args[0] = args[-( idx + 1 )];
02110             args++;
02111           }
02112           break;
02113 
02114         case cff_op_roll:
02115           {
02116             FT_Int  count = (FT_Int)( args[0] >> 16 );
02117             FT_Int  idx   = (FT_Int)( args[1] >> 16 );
02118 
02119 
02120             FT_TRACE4(( " roll\n" ));
02121 
02122             if ( count <= 0 )
02123               count = 1;
02124 
02125             args -= count;
02126             if ( args < stack )
02127               goto Stack_Underflow;
02128 
02129             if ( idx >= 0 )
02130             {
02131               while ( idx > 0 )
02132               {
02133                 FT_Fixed  tmp = args[count - 1];
02134                 FT_Int    i;
02135 
02136 
02137                 for ( i = count - 2; i >= 0; i-- )
02138                   args[i + 1] = args[i];
02139                 args[0] = tmp;
02140                 idx--;
02141               }
02142             }
02143             else
02144             {
02145               while ( idx < 0 )
02146               {
02147                 FT_Fixed  tmp = args[0];
02148                 FT_Int    i;
02149 
02150 
02151                 for ( i = 0; i < count - 1; i++ )
02152                   args[i] = args[i + 1];
02153                 args[count - 1] = tmp;
02154                 idx++;
02155               }
02156             }
02157             args += count;
02158           }
02159           break;
02160 
02161         case cff_op_dup:
02162           FT_TRACE4(( " dup\n" ));
02163 
02164           args[1] = args[0];
02165           args += 2;
02166           break;
02167 
02168         case cff_op_put:
02169           {
02170             FT_Fixed  val = args[0];
02171             FT_Int    idx = (FT_Int)( args[1] >> 16 );
02172 
02173 
02174             FT_TRACE4(( " put\n" ));
02175 
02176             if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
02177               decoder->buildchar[idx] = val;
02178           }
02179           break;
02180 
02181         case cff_op_get:
02182           {
02183             FT_Int    idx = (FT_Int)( args[0] >> 16 );
02184             FT_Fixed  val = 0;
02185 
02186 
02187             FT_TRACE4(( " get\n" ));
02188 
02189             if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
02190               val = decoder->buildchar[idx];
02191 
02192             args[0] = val;
02193             args++;
02194           }
02195           break;
02196 
02197         case cff_op_store:
02198           FT_TRACE4(( " store\n"));
02199 
02200           goto Unimplemented;
02201 
02202         case cff_op_load:
02203           FT_TRACE4(( " load\n" ));
02204 
02205           goto Unimplemented;
02206 
02207         case cff_op_dotsection:
02208           /* this operator is deprecated and ignored by the parser */
02209           FT_TRACE4(( " dotsection\n" ));
02210           break;
02211 
02212         case cff_op_closepath:
02213           /* this is an invalid Type 2 operator; however, there        */
02214           /* exist fonts which are incorrectly converted from probably */
02215           /* Type 1 to CFF, and some parsers seem to accept it         */
02216 
02217           FT_TRACE4(( " closepath (invalid op)\n" ));
02218 
02219           args = stack;
02220           break;
02221 
02222         case cff_op_hsbw:
02223           /* this is an invalid Type 2 operator; however, there        */
02224           /* exist fonts which are incorrectly converted from probably */
02225           /* Type 1 to CFF, and some parsers seem to accept it         */
02226 
02227           FT_TRACE4(( " hsbw (invalid op)\n" ));
02228 
02229           decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 );
02230 
02231           decoder->builder.left_bearing.x = args[0];
02232           decoder->builder.left_bearing.y = 0;
02233 
02234           x    = decoder->builder.pos_x + args[0];
02235           y    = decoder->builder.pos_y;
02236           args = stack;
02237           break;
02238 
02239         case cff_op_sbw:
02240           /* this is an invalid Type 2 operator; however, there        */
02241           /* exist fonts which are incorrectly converted from probably */
02242           /* Type 1 to CFF, and some parsers seem to accept it         */
02243 
02244           FT_TRACE4(( " sbw (invalid op)\n" ));
02245 
02246           decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 );
02247 
02248           decoder->builder.left_bearing.x = args[0];
02249           decoder->builder.left_bearing.y = args[1];
02250 
02251           x    = decoder->builder.pos_x + args[0];
02252           y    = decoder->builder.pos_y + args[1];
02253           args = stack;
02254           break;
02255 
02256         case cff_op_setcurrentpoint:
02257           /* this is an invalid Type 2 operator; however, there        */
02258           /* exist fonts which are incorrectly converted from probably */
02259           /* Type 1 to CFF, and some parsers seem to accept it         */
02260 
02261           FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
02262 
02263           x    = decoder->builder.pos_x + args[0];
02264           y    = decoder->builder.pos_y + args[1];
02265           args = stack;
02266           break;
02267 
02268         case cff_op_callothersubr:
02269           /* this is an invalid Type 2 operator; however, there        */
02270           /* exist fonts which are incorrectly converted from probably */
02271           /* Type 1 to CFF, and some parsers seem to accept it         */
02272 
02273           FT_TRACE4(( " callothersubr (invalid op)\n" ));
02274 
02275           /* subsequent `pop' operands should add the arguments,       */
02276           /* this is the implementation described for `unknown' other  */
02277           /* subroutines in the Type1 spec.                            */
02278           args -= 2 + ( args[-2] >> 16 );
02279           break;
02280 
02281         case cff_op_pop:
02282           /* this is an invalid Type 2 operator; however, there        */
02283           /* exist fonts which are incorrectly converted from probably */
02284           /* Type 1 to CFF, and some parsers seem to accept it         */
02285 
02286           FT_TRACE4(( " pop (invalid op)\n" ));
02287 
02288           args++;
02289           break;
02290 
02291         case cff_op_and:
02292           {
02293             FT_Fixed  cond = args[0] && args[1];
02294 
02295 
02296             FT_TRACE4(( " and\n" ));
02297 
02298             args[0] = cond ? 0x10000L : 0;
02299             args++;
02300           }
02301           break;
02302 
02303         case cff_op_or:
02304           {
02305             FT_Fixed  cond = args[0] || args[1];
02306 
02307 
02308             FT_TRACE4(( " or\n" ));
02309 
02310             args[0] = cond ? 0x10000L : 0;
02311             args++;
02312           }
02313           break;
02314 
02315         case cff_op_eq:
02316           {
02317             FT_Fixed  cond = !args[0];
02318 
02319 
02320             FT_TRACE4(( " eq\n" ));
02321 
02322             args[0] = cond ? 0x10000L : 0;
02323             args++;
02324           }
02325           break;
02326 
02327         case cff_op_ifelse:
02328           {
02329             FT_Fixed  cond = ( args[2] <= args[3] );
02330 
02331 
02332             FT_TRACE4(( " ifelse\n" ));
02333 
02334             if ( !cond )
02335               args[0] = args[1];
02336             args++;
02337           }
02338           break;
02339 
02340         case cff_op_callsubr:
02341           {
02342             FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
02343                                       decoder->locals_bias );
02344 
02345 
02346             FT_TRACE4(( " callsubr(%d)\n", idx ));
02347 
02348             if ( idx >= decoder->num_locals )
02349             {
02350               FT_ERROR(( "cff_decoder_parse_charstrings:"
02351                          " invalid local subr index\n" ));
02352               goto Syntax_Error;
02353             }
02354 
02355             if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
02356             {
02357               FT_ERROR(( "cff_decoder_parse_charstrings:"
02358                          " too many nested subrs\n" ));
02359               goto Syntax_Error;
02360             }
02361 
02362             zone->cursor = ip;  /* save current instruction pointer */
02363 
02364             zone++;
02365             zone->base   = decoder->locals[idx];
02366             zone->limit  = decoder->locals[idx + 1];
02367             zone->cursor = zone->base;
02368 
02369             if ( !zone->base || zone->limit == zone->base )
02370             {
02371               FT_ERROR(( "cff_decoder_parse_charstrings:"
02372                          " invoking empty subrs\n" ));
02373               goto Syntax_Error;
02374             }
02375 
02376             decoder->zone = zone;
02377             ip            = zone->base;
02378             limit         = zone->limit;
02379           }
02380           break;
02381 
02382         case cff_op_callgsubr:
02383           {
02384             FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
02385                                       decoder->globals_bias );
02386 
02387 
02388             FT_TRACE4(( " callgsubr(%d)\n", idx ));
02389 
02390             if ( idx >= decoder->num_globals )
02391             {
02392               FT_ERROR(( "cff_decoder_parse_charstrings:"
02393                          " invalid global subr index\n" ));
02394               goto Syntax_Error;
02395             }
02396 
02397             if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
02398             {
02399               FT_ERROR(( "cff_decoder_parse_charstrings:"
02400                          " too many nested subrs\n" ));
02401               goto Syntax_Error;
02402             }
02403 
02404             zone->cursor = ip;  /* save current instruction pointer */
02405 
02406             zone++;
02407             zone->base   = decoder->globals[idx];
02408             zone->limit  = decoder->globals[idx + 1];
02409             zone->cursor = zone->base;
02410 
02411             if ( !zone->base || zone->limit == zone->base )
02412             {
02413               FT_ERROR(( "cff_decoder_parse_charstrings:"
02414                          " invoking empty subrs\n" ));
02415               goto Syntax_Error;
02416             }
02417 
02418             decoder->zone = zone;
02419             ip            = zone->base;
02420             limit         = zone->limit;
02421           }
02422           break;
02423 
02424         case cff_op_return:
02425           FT_TRACE4(( " return\n" ));
02426 
02427           if ( decoder->zone <= decoder->zones )
02428           {
02429             FT_ERROR(( "cff_decoder_parse_charstrings:"
02430                        " unexpected return\n" ));
02431             goto Syntax_Error;
02432           }
02433 
02434           decoder->zone--;
02435           zone  = decoder->zone;
02436           ip    = zone->cursor;
02437           limit = zone->limit;
02438           break;
02439 
02440         default:
02441         Unimplemented:
02442           FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
02443 
02444           if ( ip[-1] == 12 )
02445             FT_ERROR(( " %d", ip[0] ));
02446           FT_ERROR(( "\n" ));
02447 
02448           return CFF_Err_Unimplemented_Feature;
02449         }
02450 
02451       decoder->top = args;
02452 
02453       } /* general operator processing */
02454 
02455     } /* while ip < limit */
02456 
02457     FT_TRACE4(( "..end..\n\n" ));
02458 
02459   Fail:
02460     return error;
02461 
02462   Syntax_Error:
02463     FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
02464     return CFF_Err_Invalid_File_Format;
02465 
02466   Stack_Underflow:
02467     FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
02468     return CFF_Err_Too_Few_Arguments;
02469 
02470   Stack_Overflow:
02471     FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
02472     return CFF_Err_Stack_Overflow;
02473   }
02474 
02475 
02476   /*************************************************************************/
02477   /*************************************************************************/
02478   /*************************************************************************/
02479   /**********                                                      *********/
02480   /**********                                                      *********/
02481   /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
02482   /**********                                                      *********/
02483   /**********    The following code is in charge of computing      *********/
02484   /**********    the maximum advance width of the font.  It        *********/
02485   /**********    quickly processes each glyph charstring to        *********/
02486   /**********    extract the value from either a `sbw' or `seac'   *********/
02487   /**********    operator.                                         *********/
02488   /**********                                                      *********/
02489   /*************************************************************************/
02490   /*************************************************************************/
02491   /*************************************************************************/
02492 
02493 
02494 #if 0 /* unused until we support pure CFF fonts */
02495 
02496 
02497   FT_LOCAL_DEF( FT_Error )
02498   cff_compute_max_advance( TT_Face  face,
02499                            FT_Int*  max_advance )
02500   {
02501     FT_Error     error = CFF_Err_Ok;
02502     CFF_Decoder  decoder;
02503     FT_Int       glyph_index;
02504     CFF_Font     cff = (CFF_Font)face->other;
02505 
02506 
02507     *max_advance = 0;
02508 
02509     /* Initialize load decoder */
02510     cff_decoder_init( &decoder, face, 0, 0, 0, 0 );
02511 
02512     decoder.builder.metrics_only = 1;
02513     decoder.builder.load_points  = 0;
02514 
02515     /* For each glyph, parse the glyph charstring and extract */
02516     /* the advance width.                                     */
02517     for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
02518           glyph_index++ )
02519     {
02520       FT_Byte*  charstring;
02521       FT_ULong  charstring_len;
02522 
02523 
02524       /* now get load the unscaled outline */
02525       error = cff_get_glyph_data( face, glyph_index,
02526                                   &charstring, &charstring_len );
02527       if ( !error )
02528       {
02529         error = cff_decoder_prepare( &decoder, size, glyph_index );
02530         if ( !error )
02531           error = cff_decoder_parse_charstrings( &decoder,
02532                                                  charstring,
02533                                                  charstring_len );
02534 
02535         cff_free_glyph_data( face, &charstring, &charstring_len );
02536       }
02537 
02538       /* ignore the error if one has occurred -- skip to next glyph */
02539       error = CFF_Err_Ok;
02540     }
02541 
02542     *max_advance = decoder.builder.advance.x;
02543 
02544     return CFF_Err_Ok;
02545   }
02546 
02547 
02548 #endif /* 0 */
02549 
02550 
02551   FT_LOCAL_DEF( FT_Error )
02552   cff_slot_load( CFF_GlyphSlot  glyph,
02553                  CFF_Size       size,
02554                  FT_UInt        glyph_index,
02555                  FT_Int32       load_flags )
02556   {
02557     FT_Error     error;
02558     CFF_Decoder  decoder;
02559     TT_Face      face = (TT_Face)glyph->root.face;
02560     FT_Bool      hinting, force_scaling;
02561     CFF_Font     cff  = (CFF_Font)face->extra.data;
02562 
02563     FT_Matrix    font_matrix;
02564     FT_Vector    font_offset;
02565 
02566 
02567     force_scaling = FALSE;
02568 
02569     /* in a CID-keyed font, consider `glyph_index' as a CID and map */
02570     /* it immediately to the real glyph_index -- if it isn't a      */
02571     /* subsetted font, glyph_indices and CIDs are identical, though */
02572     if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
02573          cff->charset.cids                               )
02574     {
02575       /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */
02576       if ( glyph_index != 0 )
02577       {
02578         glyph_index = cff_charset_cid_to_gindex( &cff->charset,
02579                                                  glyph_index );
02580         if ( glyph_index == 0 )
02581           return CFF_Err_Invalid_Argument;
02582       }
02583     }
02584     else if ( glyph_index >= cff->num_glyphs )
02585       return CFF_Err_Invalid_Argument;
02586 
02587     if ( load_flags & FT_LOAD_NO_RECURSE )
02588       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
02589 
02590     glyph->x_scale = 0x10000L;
02591     glyph->y_scale = 0x10000L;
02592     if ( size )
02593     {
02594       glyph->x_scale = size->root.metrics.x_scale;
02595       glyph->y_scale = size->root.metrics.y_scale;
02596     }
02597 
02598 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
02599 
02600     /* try to load embedded bitmap if any              */
02601     /*                                                 */
02602     /* XXX: The convention should be emphasized in     */
02603     /*      the documents because it can be confusing. */
02604     if ( size )
02605     {
02606       CFF_Face      cff_face = (CFF_Face)size->root.face;
02607       SFNT_Service  sfnt     = (SFNT_Service)cff_face->sfnt;
02608       FT_Stream     stream   = cff_face->root.stream;
02609 
02610 
02611       if ( size->strike_index != 0xFFFFFFFFUL      &&
02612            sfnt->load_eblc                         &&
02613            ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
02614       {
02615         TT_SBit_MetricsRec  metrics;
02616 
02617 
02618         error = sfnt->load_sbit_image( face,
02619                                        size->strike_index,
02620                                        glyph_index,
02621                                        (FT_Int)load_flags,
02622                                        stream,
02623                                        &glyph->root.bitmap,
02624                                        &metrics );
02625 
02626         if ( !error )
02627         {
02628           glyph->root.outline.n_points   = 0;
02629           glyph->root.outline.n_contours = 0;
02630 
02631           glyph->root.metrics.width  = (FT_Pos)metrics.width  << 6;
02632           glyph->root.metrics.height = (FT_Pos)metrics.height << 6;
02633 
02634           glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
02635           glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
02636           glyph->root.metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
02637 
02638           glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
02639           glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
02640           glyph->root.metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
02641 
02642           glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
02643 
02644           if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
02645           {
02646             glyph->root.bitmap_left = metrics.vertBearingX;
02647             glyph->root.bitmap_top  = metrics.vertBearingY;
02648           }
02649           else
02650           {
02651             glyph->root.bitmap_left = metrics.horiBearingX;
02652             glyph->root.bitmap_top  = metrics.horiBearingY;
02653           }
02654           return error;
02655         }
02656       }
02657     }
02658 
02659 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
02660 
02661     /* return immediately if we only want the embedded bitmaps */
02662     if ( load_flags & FT_LOAD_SBITS_ONLY )
02663       return CFF_Err_Invalid_Argument;
02664 
02665     /* if we have a CID subfont, use its matrix (which has already */
02666     /* been multiplied with the root matrix)                       */
02667 
02668     /* this scaling is only relevant if the PS hinter isn't active */
02669     if ( cff->num_subfonts )
02670     {
02671       FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select,
02672                                              glyph_index );
02673 
02674       FT_ULong  top_upm = cff->top_font.font_dict.units_per_em;
02675       FT_ULong  sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em;
02676 
02677 
02678       font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
02679       font_offset = cff->subfonts[fd_index]->font_dict.font_offset;
02680 
02681       if ( top_upm != sub_upm )
02682       {
02683         glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm );
02684         glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm );
02685 
02686         force_scaling = TRUE;
02687       }
02688     }
02689     else
02690     {
02691       font_matrix = cff->top_font.font_dict.font_matrix;
02692       font_offset = cff->top_font.font_dict.font_offset;
02693     }
02694 
02695     glyph->root.outline.n_points   = 0;
02696     glyph->root.outline.n_contours = 0;
02697 
02698     hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
02699                        ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
02700 
02701     glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;  /* by default */
02702 
02703     {
02704       FT_Byte*  charstring;
02705       FT_ULong  charstring_len;
02706 
02707 
02708       cff_decoder_init( &decoder, face, size, glyph, hinting,
02709                         FT_LOAD_TARGET_MODE( load_flags ) );
02710 
02711       if ( load_flags & FT_LOAD_ADVANCE_ONLY )
02712         decoder.width_only = TRUE;
02713 
02714       decoder.builder.no_recurse =
02715         (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );
02716 
02717       /* now load the unscaled outline */
02718       error = cff_get_glyph_data( face, glyph_index,
02719                                   &charstring, &charstring_len );
02720       if ( !error )
02721       {
02722         error = cff_decoder_prepare( &decoder, size, glyph_index );
02723         if ( !error )
02724         {
02725           error = cff_decoder_parse_charstrings( &decoder,
02726                                                  charstring,
02727                                                  charstring_len );
02728 
02729           cff_free_glyph_data( face, &charstring, charstring_len );
02730 
02731 
02732 #ifdef FT_CONFIG_OPTION_INCREMENTAL
02733           /* Control data and length may not be available for incremental */
02734           /* fonts.                                                       */
02735           if ( face->root.internal->incremental_interface )
02736           {
02737             glyph->root.control_data = 0;
02738             glyph->root.control_len = 0;
02739           }
02740           else
02741 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
02742 
02743           /* We set control_data and control_len if charstrings is loaded. */
02744           /* See how charstring loads at cff_index_access_element() in     */
02745           /* cffload.c.                                                    */
02746           {
02747             CFF_Index  csindex = &cff->charstrings_index;
02748 
02749 
02750             if ( csindex->offsets )
02751             {
02752               glyph->root.control_data = csindex->bytes +
02753                                            csindex->offsets[glyph_index] - 1;
02754               glyph->root.control_len  = charstring_len;
02755             }
02756           }
02757         }
02758       }
02759 
02760       /* save new glyph tables */
02761       cff_builder_done( &decoder.builder );
02762     }
02763 
02764 #ifdef FT_CONFIG_OPTION_INCREMENTAL
02765 
02766     /* Incremental fonts can optionally override the metrics. */
02767     if ( !error                                                               &&
02768          face->root.internal->incremental_interface                           &&
02769          face->root.internal->incremental_interface->funcs->get_glyph_metrics )
02770     {
02771       FT_Incremental_MetricsRec  metrics;
02772 
02773 
02774       metrics.bearing_x = decoder.builder.left_bearing.x;
02775       metrics.bearing_y = 0;
02776       metrics.advance   = decoder.builder.advance.x;
02777       metrics.advance_v = decoder.builder.advance.y;
02778 
02779       error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
02780                 face->root.internal->incremental_interface->object,
02781                 glyph_index, FALSE, &metrics );
02782 
02783       decoder.builder.left_bearing.x = metrics.bearing_x;
02784       decoder.builder.advance.x      = metrics.advance;
02785       decoder.builder.advance.y      = metrics.advance_v;
02786     }
02787 
02788 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
02789 
02790     if ( !error )
02791     {
02792       /* Now, set the metrics -- this is rather simple, as   */
02793       /* the left side bearing is the xMin, and the top side */
02794       /* bearing the yMax.                                   */
02795 
02796       /* For composite glyphs, return only left side bearing and */
02797       /* advance width.                                          */
02798       if ( load_flags & FT_LOAD_NO_RECURSE )
02799       {
02800         FT_Slot_Internal  internal = glyph->root.internal;
02801 
02802 
02803         glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
02804         glyph->root.metrics.horiAdvance  = decoder.glyph_width;
02805         internal->glyph_matrix           = font_matrix;
02806         internal->glyph_delta            = font_offset;
02807         internal->glyph_transformed      = 1;
02808       }
02809       else
02810       {
02811         FT_BBox            cbox;
02812         FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
02813         FT_Vector          advance;
02814         FT_Bool            has_vertical_info;
02815 
02816 
02817         /* copy the _unscaled_ advance width */
02818         metrics->horiAdvance                    = decoder.glyph_width;
02819         glyph->root.linearHoriAdvance           = decoder.glyph_width;
02820         glyph->root.internal->glyph_transformed = 0;
02821 
02822 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
02823         has_vertical_info = FT_BOOL( face->vertical_info                   &&
02824                                      face->vertical.number_Of_VMetrics > 0 &&
02825                                      face->vertical.long_metrics           );
02826 #else
02827         has_vertical_info = FT_BOOL( face->vertical_info                   &&
02828                                      face->vertical.number_Of_VMetrics > 0 );
02829 #endif
02830 
02831         /* get the vertical metrics from the vtmx table if we have one */
02832         if ( has_vertical_info )
02833         {
02834           FT_Short   vertBearingY = 0;
02835           FT_UShort  vertAdvance  = 0;
02836 
02837 
02838           ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
02839                                                      glyph_index,
02840                                                      &vertBearingY,
02841                                                      &vertAdvance );
02842           metrics->vertBearingY = vertBearingY;
02843           metrics->vertAdvance  = vertAdvance;
02844         }
02845         else
02846         {
02847           /* make up vertical ones */
02848           if ( face->os2.version != 0xFFFFU )
02849             metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -
02850                                              face->os2.sTypoDescender );
02851           else
02852             metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -
02853                                              face->horizontal.Descender );
02854         }
02855 
02856         glyph->root.linearVertAdvance = metrics->vertAdvance;
02857 
02858         glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
02859 
02860         glyph->root.outline.flags = 0;
02861         if ( size && size->root.metrics.y_ppem < 24 )
02862           glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
02863 
02864         glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
02865 
02866         if ( !( font_matrix.xx == 0x10000L &&
02867                 font_matrix.yy == 0x10000L &&
02868                 font_matrix.xy == 0        &&
02869                 font_matrix.yx == 0        ) )
02870           FT_Outline_Transform( &glyph->root.outline, &font_matrix );
02871 
02872         if ( !( font_offset.x == 0 &&
02873                 font_offset.y == 0 ) )
02874           FT_Outline_Translate( &glyph->root.outline,
02875                                 font_offset.x, font_offset.y );
02876 
02877         advance.x = metrics->horiAdvance;
02878         advance.y = 0;
02879         FT_Vector_Transform( &advance, &font_matrix );
02880         metrics->horiAdvance = advance.x + font_offset.x;
02881 
02882         advance.x = 0;
02883         advance.y = metrics->vertAdvance;
02884         FT_Vector_Transform( &advance, &font_matrix );
02885         metrics->vertAdvance = advance.y + font_offset.y;
02886 
02887         if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
02888         {
02889           /* scale the outline and the metrics */
02890           FT_Int       n;
02891           FT_Outline*  cur     = &glyph->root.outline;
02892           FT_Vector*   vec     = cur->points;
02893           FT_Fixed     x_scale = glyph->x_scale;
02894           FT_Fixed     y_scale = glyph->y_scale;
02895 
02896 
02897           /* First of all, scale the points */
02898           if ( !hinting || !decoder.builder.hints_funcs )
02899             for ( n = cur->n_points; n > 0; n--, vec++ )
02900             {
02901               vec->x = FT_MulFix( vec->x, x_scale );
02902               vec->y = FT_MulFix( vec->y, y_scale );
02903             }
02904 
02905           /* Then scale the metrics */
02906           metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
02907           metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
02908         }
02909 
02910         /* compute the other metrics */
02911         FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
02912 
02913         metrics->width  = cbox.xMax - cbox.xMin;
02914         metrics->height = cbox.yMax - cbox.yMin;
02915 
02916         metrics->horiBearingX = cbox.xMin;
02917         metrics->horiBearingY = cbox.yMax;
02918 
02919         if ( has_vertical_info )
02920           metrics->vertBearingX = metrics->horiBearingX -
02921                                     metrics->horiAdvance / 2;
02922         else 
02923         {
02924           if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
02925             ft_synthesize_vertical_metrics( metrics,
02926                                             metrics->vertAdvance );
02927         }
02928       }
02929     }
02930 
02931     return error;
02932   }
02933 
02934 
02935 /* END */

Generated on Tue Jul 5 14:13:46 2011 for ROOT_528-00b_version by  doxygen 1.5.1