ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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

Generated on Sat May 26 2012 04:32:40 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.