t1decode.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  t1decode.c                                                             */
00004 /*                                                                         */
00005 /*    PostScript Type 1 decoding routines (body).                          */
00006 /*                                                                         */
00007 /*  Copyright 2000-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_CALC_H
00022 #include FT_INTERNAL_DEBUG_H
00023 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
00024 #include FT_OUTLINE_H
00025 
00026 #include "t1decode.h"
00027 #include "psobjs.h"
00028 
00029 #include "psauxerr.h"
00030 
00031 
00032   /*************************************************************************/
00033   /*                                                                       */
00034   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00035   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00036   /* messages during execution.                                            */
00037   /*                                                                       */
00038 #undef  FT_COMPONENT
00039 #define FT_COMPONENT  trace_t1decode
00040 
00041 
00042   typedef enum  T1_Operator_
00043   {
00044     op_none = 0,
00045     op_endchar,
00046     op_hsbw,
00047     op_seac,
00048     op_sbw,
00049     op_closepath,
00050     op_hlineto,
00051     op_hmoveto,
00052     op_hvcurveto,
00053     op_rlineto,
00054     op_rmoveto,
00055     op_rrcurveto,
00056     op_vhcurveto,
00057     op_vlineto,
00058     op_vmoveto,
00059     op_dotsection,
00060     op_hstem,
00061     op_hstem3,
00062     op_vstem,
00063     op_vstem3,
00064     op_div,
00065     op_callothersubr,
00066     op_callsubr,
00067     op_pop,
00068     op_return,
00069     op_setcurrentpoint,
00070     op_unknown15,
00071 
00072     op_max    /* never remove this one */
00073 
00074   } T1_Operator;
00075 
00076 
00077   static
00078   const FT_Int  t1_args_count[op_max] =
00079   {
00080     0, /* none */
00081     0, /* endchar */
00082     2, /* hsbw */
00083     5, /* seac */
00084     4, /* sbw */
00085     0, /* closepath */
00086     1, /* hlineto */
00087     1, /* hmoveto */
00088     4, /* hvcurveto */
00089     2, /* rlineto */
00090     2, /* rmoveto */
00091     6, /* rrcurveto */
00092     4, /* vhcurveto */
00093     1, /* vlineto */
00094     1, /* vmoveto */
00095     0, /* dotsection */
00096     2, /* hstem */
00097     6, /* hstem3 */
00098     2, /* vstem */
00099     6, /* vstem3 */
00100     2, /* div */
00101    -1, /* callothersubr */
00102     1, /* callsubr */
00103     0, /* pop */
00104     0, /* return */
00105     2, /* setcurrentpoint */
00106     2  /* opcode 15 (undocumented and obsolete) */
00107   };
00108 
00109 
00110   /*************************************************************************/
00111   /*                                                                       */
00112   /* <Function>                                                            */
00113   /*    t1_lookup_glyph_by_stdcharcode                                     */
00114   /*                                                                       */
00115   /* <Description>                                                         */
00116   /*    Looks up a given glyph by its StandardEncoding charcode.  Used to  */
00117   /*    implement the SEAC Type 1 operator.                                */
00118   /*                                                                       */
00119   /* <Input>                                                               */
00120   /*    face     :: The current face object.                               */
00121   /*                                                                       */
00122   /*    charcode :: The character code to look for.                        */
00123   /*                                                                       */
00124   /* <Return>                                                              */
00125   /*    A glyph index in the font face.  Returns -1 if the corresponding   */
00126   /*    glyph wasn't found.                                                */
00127   /*                                                                       */
00128   static FT_Int
00129   t1_lookup_glyph_by_stdcharcode( T1_Decoder  decoder,
00130                                   FT_Int      charcode )
00131   {
00132     FT_UInt             n;
00133     const FT_String*    glyph_name;
00134     FT_Service_PsCMaps  psnames = decoder->psnames;
00135 
00136 
00137     /* check range of standard char code */
00138     if ( charcode < 0 || charcode > 255 )
00139       return -1;
00140 
00141     glyph_name = psnames->adobe_std_strings(
00142                    psnames->adobe_std_encoding[charcode]);
00143 
00144     for ( n = 0; n < decoder->num_glyphs; n++ )
00145     {
00146       FT_String*  name = (FT_String*)decoder->glyph_names[n];
00147 
00148 
00149       if ( name                               &&
00150            name[0] == glyph_name[0]           &&
00151            ft_strcmp( name, glyph_name ) == 0 )
00152         return n;
00153     }
00154 
00155     return -1;
00156   }
00157 
00158 
00159   /*************************************************************************/
00160   /*                                                                       */
00161   /* <Function>                                                            */
00162   /*    t1operator_seac                                                    */
00163   /*                                                                       */
00164   /* <Description>                                                         */
00165   /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
00166   /*                                                                       */
00167   /* <Input>                                                               */
00168   /*    decoder :: The current CID decoder.                                */
00169   /*                                                                       */
00170   /*    asb     :: The accent's side bearing.                              */
00171   /*                                                                       */
00172   /*    adx     :: The horizontal offset of the accent.                    */
00173   /*                                                                       */
00174   /*    ady     :: The vertical offset of the accent.                      */
00175   /*                                                                       */
00176   /*    bchar   :: The base character's StandardEncoding charcode.         */
00177   /*                                                                       */
00178   /*    achar   :: The accent character's StandardEncoding charcode.       */
00179   /*                                                                       */
00180   /* <Return>                                                              */
00181   /*    FreeType error code.  0 means success.                             */
00182   /*                                                                       */
00183   static FT_Error
00184   t1operator_seac( T1_Decoder  decoder,
00185                    FT_Pos      asb,
00186                    FT_Pos      adx,
00187                    FT_Pos      ady,
00188                    FT_Int      bchar,
00189                    FT_Int      achar )
00190   {
00191     FT_Error     error;
00192     FT_Int       bchar_index, achar_index;
00193 #if 0
00194     FT_Int       n_base_points;
00195     FT_Outline*  base = decoder->builder.base;
00196 #endif
00197     FT_Vector    left_bearing, advance;
00198 
00199 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00200     T1_Face      face  = (T1_Face)decoder->builder.face;
00201 #endif     
00202 
00203 
00204     if ( decoder->seac )
00205     {
00206       FT_ERROR(( "t1operator_seac: invalid nested seac\n" ));
00207       return PSaux_Err_Syntax_Error;
00208     }
00209 
00210     /* seac weirdness */
00211     adx += decoder->builder.left_bearing.x;
00212 
00213     /* `glyph_names' is set to 0 for CID fonts which do not */
00214     /* include an encoding.  How can we deal with these?    */
00215 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00216     if ( decoder->glyph_names == 0                   &&
00217          !face->root.internal->incremental_interface )
00218 #else
00219     if ( decoder->glyph_names == 0 )
00220 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
00221     {
00222       FT_ERROR(( "t1operator_seac:"
00223                  " glyph names table not available in this font\n" ));
00224       return PSaux_Err_Syntax_Error;
00225     }
00226 
00227 #ifdef FT_CONFIG_OPTION_INCREMENTAL
00228     if ( face->root.internal->incremental_interface )
00229     {
00230       /* the caller must handle the font encoding also */
00231       bchar_index = bchar;
00232       achar_index = achar;
00233     }
00234     else
00235 #endif
00236     {
00237       bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
00238       achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
00239     }
00240 
00241     if ( bchar_index < 0 || achar_index < 0 )
00242     {
00243       FT_ERROR(( "t1operator_seac:"
00244                  " invalid seac character code arguments\n" ));
00245       return PSaux_Err_Syntax_Error;
00246     }
00247 
00248     /* if we are trying to load a composite glyph, do not load the */
00249     /* accent character and return the array of subglyphs.         */
00250     if ( decoder->builder.no_recurse )
00251     {
00252       FT_GlyphSlot    glyph  = (FT_GlyphSlot)decoder->builder.glyph;
00253       FT_GlyphLoader  loader = glyph->internal->loader;
00254       FT_SubGlyph     subg;
00255 
00256 
00257       /* reallocate subglyph array if necessary */
00258       error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
00259       if ( error )
00260         goto Exit;
00261 
00262       subg = loader->current.subglyphs;
00263 
00264       /* subglyph 0 = base character */
00265       subg->index = bchar_index;
00266       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
00267                     FT_SUBGLYPH_FLAG_USE_MY_METRICS;
00268       subg->arg1  = 0;
00269       subg->arg2  = 0;
00270       subg++;
00271 
00272       /* subglyph 1 = accent character */
00273       subg->index = achar_index;
00274       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
00275       subg->arg1  = (FT_Int)FIXED_TO_INT( adx - asb );
00276       subg->arg2  = (FT_Int)FIXED_TO_INT( ady );
00277 
00278       /* set up remaining glyph fields */
00279       glyph->num_subglyphs = 2;
00280       glyph->subglyphs     = loader->base.subglyphs;
00281       glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
00282 
00283       loader->current.num_subglyphs = 2;
00284       goto Exit;
00285     }
00286 
00287     /* First load `bchar' in builder */
00288     /* now load the unscaled outline */
00289 
00290     FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
00291 
00292     /* the seac operator must not be nested */
00293     decoder->seac = TRUE;
00294     error = t1_decoder_parse_glyph( decoder, bchar_index );
00295     decoder->seac = FALSE;
00296     if ( error )
00297       goto Exit;
00298 
00299     /* save the left bearing and width of the base character */
00300     /* as they will be erased by the next load.              */
00301 
00302     left_bearing = decoder->builder.left_bearing;
00303     advance      = decoder->builder.advance;
00304 
00305     decoder->builder.left_bearing.x = 0;
00306     decoder->builder.left_bearing.y = 0;
00307 
00308     decoder->builder.pos_x = adx - asb;
00309     decoder->builder.pos_y = ady;
00310 
00311     /* Now load `achar' on top of */
00312     /* the base outline           */
00313 
00314     /* the seac operator must not be nested */
00315     decoder->seac = TRUE;
00316     error = t1_decoder_parse_glyph( decoder, achar_index );
00317     decoder->seac = FALSE;
00318     if ( error )
00319       goto Exit;
00320 
00321     /* restore the left side bearing and   */
00322     /* advance width of the base character */
00323 
00324     decoder->builder.left_bearing = left_bearing;
00325     decoder->builder.advance      = advance;
00326 
00327     decoder->builder.pos_x = 0;
00328     decoder->builder.pos_y = 0;
00329 
00330   Exit:
00331     return error;
00332   }
00333 
00334 
00335   /*************************************************************************/
00336   /*                                                                       */
00337   /* <Function>                                                            */
00338   /*    t1_decoder_parse_charstrings                                       */
00339   /*                                                                       */
00340   /* <Description>                                                         */
00341   /*    Parses a given Type 1 charstrings program.                         */
00342   /*                                                                       */
00343   /* <Input>                                                               */
00344   /*    decoder         :: The current Type 1 decoder.                     */
00345   /*                                                                       */
00346   /*    charstring_base :: The base address of the charstring stream.      */
00347   /*                                                                       */
00348   /*    charstring_len  :: The length in bytes of the charstring stream.   */
00349   /*                                                                       */
00350   /* <Return>                                                              */
00351   /*    FreeType error code.  0 means success.                             */
00352   /*                                                                       */
00353   FT_LOCAL_DEF( FT_Error )
00354   t1_decoder_parse_charstrings( T1_Decoder  decoder,
00355                                 FT_Byte*    charstring_base,
00356                                 FT_UInt     charstring_len )
00357   {
00358     FT_Error         error;
00359     T1_Decoder_Zone  zone;
00360     FT_Byte*         ip;
00361     FT_Byte*         limit;
00362     T1_Builder       builder = &decoder->builder;
00363     FT_Pos           x, y, orig_x, orig_y;
00364     FT_Int           known_othersubr_result_cnt   = 0;
00365     FT_Int           unknown_othersubr_result_cnt = 0;
00366     FT_Bool          large_int;
00367     FT_Fixed         seed;
00368 
00369     T1_Hints_Funcs   hinter;
00370 
00371 #ifdef FT_DEBUG_LEVEL_TRACE
00372     FT_Bool          bol = TRUE;
00373 #endif
00374 
00375 
00376     /* we don't want to touch the source code -- use macro trick */
00377 #define start_point    t1_builder_start_point
00378 #define check_points   t1_builder_check_points
00379 #define add_point      t1_builder_add_point
00380 #define add_point1     t1_builder_add_point1
00381 #define add_contour    t1_builder_add_contour
00382 #define close_contour  t1_builder_close_contour
00383 
00384 
00385     /* compute random seed from stack address of parameter */
00386     seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed              ^
00387                          (FT_PtrDist)(char*)&decoder           ^
00388                          (FT_PtrDist)(char*)&charstring_base ) &
00389                          FT_ULONG_MAX ) ;
00390     seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
00391     if ( seed == 0 )
00392       seed = 0x7384;
00393 
00394     /* First of all, initialize the decoder */
00395     decoder->top  = decoder->stack;
00396     decoder->zone = decoder->zones;
00397     zone          = decoder->zones;
00398 
00399     builder->parse_state = T1_Parse_Start;
00400 
00401     hinter = (T1_Hints_Funcs)builder->hints_funcs;
00402 
00403     /* a font that reads BuildCharArray without setting */
00404     /* its values first is buggy, but ...               */
00405     FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
00406                ( decoder->buildchar == NULL )  );
00407 
00408     if ( decoder->len_buildchar > 0 )
00409       ft_memset( &decoder->buildchar[0],
00410                  0,
00411                  sizeof( decoder->buildchar[0] ) * decoder->len_buildchar );
00412 
00413     FT_TRACE4(( "\n"
00414                 "Start charstring\n" ));
00415 
00416     zone->base           = charstring_base;
00417     limit = zone->limit  = charstring_base + charstring_len;
00418     ip    = zone->cursor = zone->base;
00419 
00420     error = PSaux_Err_Ok;
00421 
00422     x = orig_x = builder->pos_x;
00423     y = orig_y = builder->pos_y;
00424 
00425     /* begin hints recording session, if any */
00426     if ( hinter )
00427       hinter->open( hinter->hints );
00428 
00429     large_int = FALSE;
00430 
00431     /* now, execute loop */
00432     while ( ip < limit )
00433     {
00434       FT_Long*     top   = decoder->top;
00435       T1_Operator  op    = op_none;
00436       FT_Int32     value = 0;
00437 
00438 
00439       FT_ASSERT( known_othersubr_result_cnt == 0   ||
00440                  unknown_othersubr_result_cnt == 0 );
00441 
00442 #ifdef FT_DEBUG_LEVEL_TRACE
00443       if ( bol )
00444       {
00445         FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
00446         bol = FALSE;
00447       }
00448 #endif
00449 
00450       /*********************************************************************/
00451       /*                                                                   */
00452       /* Decode operator or operand                                        */
00453       /*                                                                   */
00454       /*                                                                   */
00455 
00456       /* first of all, decompress operator or value */
00457       switch ( *ip++ )
00458       {
00459       case 1:
00460         op = op_hstem;
00461         break;
00462 
00463       case 3:
00464         op = op_vstem;
00465         break;
00466       case 4:
00467         op = op_vmoveto;
00468         break;
00469       case 5:
00470         op = op_rlineto;
00471         break;
00472       case 6:
00473         op = op_hlineto;
00474         break;
00475       case 7:
00476         op = op_vlineto;
00477         break;
00478       case 8:
00479         op = op_rrcurveto;
00480         break;
00481       case 9:
00482         op = op_closepath;
00483         break;
00484       case 10:
00485         op = op_callsubr;
00486         break;
00487       case 11:
00488         op = op_return;
00489         break;
00490 
00491       case 13:
00492         op = op_hsbw;
00493         break;
00494       case 14:
00495         op = op_endchar;
00496         break;
00497 
00498       case 15:          /* undocumented, obsolete operator */
00499         op = op_unknown15;
00500         break;
00501 
00502       case 21:
00503         op = op_rmoveto;
00504         break;
00505       case 22:
00506         op = op_hmoveto;
00507         break;
00508 
00509       case 30:
00510         op = op_vhcurveto;
00511         break;
00512       case 31:
00513         op = op_hvcurveto;
00514         break;
00515 
00516       case 12:
00517         if ( ip > limit )
00518         {
00519           FT_ERROR(( "t1_decoder_parse_charstrings:"
00520                      " invalid escape (12+EOF)\n" ));
00521           goto Syntax_Error;
00522         }
00523 
00524         switch ( *ip++ )
00525         {
00526         case 0:
00527           op = op_dotsection;
00528           break;
00529         case 1:
00530           op = op_vstem3;
00531           break;
00532         case 2:
00533           op = op_hstem3;
00534           break;
00535         case 6:
00536           op = op_seac;
00537           break;
00538         case 7:
00539           op = op_sbw;
00540           break;
00541         case 12:
00542           op = op_div;
00543           break;
00544         case 16:
00545           op = op_callothersubr;
00546           break;
00547         case 17:
00548           op = op_pop;
00549           break;
00550         case 33:
00551           op = op_setcurrentpoint;
00552           break;
00553 
00554         default:
00555           FT_ERROR(( "t1_decoder_parse_charstrings:"
00556                      " invalid escape (12+%d)\n",
00557                      ip[-1] ));
00558           goto Syntax_Error;
00559         }
00560         break;
00561 
00562       case 255:    /* four bytes integer */
00563         if ( ip + 4 > limit )
00564         {
00565           FT_ERROR(( "t1_decoder_parse_charstrings:"
00566                      " unexpected EOF in integer\n" ));
00567           goto Syntax_Error;
00568         }
00569 
00570         value = (FT_Int32)( ( (FT_Long)ip[0] << 24 ) |
00571                             ( (FT_Long)ip[1] << 16 ) |
00572                             ( (FT_Long)ip[2] << 8  ) |
00573                                        ip[3]         );
00574         ip += 4;
00575 
00576         /* According to the specification, values > 32000 or < -32000 must */
00577         /* be followed by a `div' operator to make the result be in the    */
00578         /* range [-32000;32000].  We expect that the second argument of    */
00579         /* `div' is not a large number.  Additionally, we don't handle     */
00580         /* stuff like `<large1> <large2> <num> div <num> div' or           */
00581         /* <large1> <large2> <num> div div'.  This is probably not allowed */
00582         /* anyway.                                                         */
00583         if ( value > 32000 || value < -32000 )
00584         {
00585           if ( large_int )
00586           {
00587             FT_ERROR(( "t1_decoder_parse_charstrings:"
00588                        " no `div' after large integer\n" ));
00589           }
00590           else
00591             large_int = TRUE;
00592         }
00593         else
00594         {
00595           if ( !large_int )
00596             value <<= 16;
00597         }
00598 
00599         break;
00600 
00601       default:
00602         if ( ip[-1] >= 32 )
00603         {
00604           if ( ip[-1] < 247 )
00605             value = (FT_Int32)ip[-1] - 139;
00606           else
00607           {
00608             if ( ++ip > limit )
00609             {
00610               FT_ERROR(( "t1_decoder_parse_charstrings:"
00611                          " unexpected EOF in integer\n" ));
00612               goto Syntax_Error;
00613             }
00614 
00615             if ( ip[-2] < 251 )
00616               value =  ( ( (FT_Int32)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
00617             else
00618               value = -( ( ( (FT_Int32)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
00619           }
00620 
00621           if ( !large_int )
00622             value <<= 16;
00623         }
00624         else
00625         {
00626           FT_ERROR(( "t1_decoder_parse_charstrings:"
00627                      " invalid byte (%d)\n", ip[-1] ));
00628           goto Syntax_Error;
00629         }
00630       }
00631 
00632       if ( unknown_othersubr_result_cnt > 0 )
00633       {
00634         switch ( op )
00635         {
00636         case op_callsubr:
00637         case op_return:
00638         case op_none:
00639         case op_pop:
00640           break;
00641 
00642         default:
00643           /* all operands have been transferred by previous pops */
00644           unknown_othersubr_result_cnt = 0;
00645           break;
00646         }
00647       }
00648 
00649       if ( large_int && !( op == op_none || op == op_div ) )
00650       {
00651         FT_ERROR(( "t1_decoder_parse_charstrings:"
00652                    " no `div' after large integer\n" ));
00653 
00654         large_int = FALSE;
00655       }
00656 
00657       /*********************************************************************/
00658       /*                                                                   */
00659       /*  Push value on stack, or process operator                         */
00660       /*                                                                   */
00661       /*                                                                   */
00662       if ( op == op_none )
00663       {
00664         if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
00665         {
00666           FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" ));
00667           goto Syntax_Error;
00668         }
00669 
00670 #ifdef FT_DEBUG_LEVEL_TRACE
00671         if ( large_int )
00672           FT_TRACE4(( " %ld", value ));
00673         else
00674           FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) ));
00675 #endif
00676 
00677         *top++       = value;
00678         decoder->top = top;
00679       }
00680       else if ( op == op_callothersubr )  /* callothersubr */
00681       {
00682         FT_Int  subr_no;
00683         FT_Int  arg_cnt;
00684 
00685 
00686 #ifdef FT_DEBUG_LEVEL_TRACE
00687         FT_TRACE4(( " callothersubr\n" ));
00688         bol = TRUE;
00689 #endif
00690 
00691         if ( top - decoder->stack < 2 )
00692           goto Stack_Underflow;
00693 
00694         top -= 2;
00695 
00696         subr_no = (FT_Int)( top[1] >> 16 );
00697         arg_cnt = (FT_Int)( top[0] >> 16 );
00698 
00699         /***********************************************************/
00700         /*                                                         */
00701         /* remove all operands to callothersubr from the stack     */
00702         /*                                                         */
00703         /* for handled othersubrs, where we know the number of     */
00704         /* arguments, we increase the stack by the value of        */
00705         /* known_othersubr_result_cnt                              */
00706         /*                                                         */
00707         /* for unhandled othersubrs the following pops adjust the  */
00708         /* stack pointer as necessary                              */
00709 
00710         if ( arg_cnt > top - decoder->stack )
00711           goto Stack_Underflow;
00712 
00713         top -= arg_cnt;
00714 
00715         known_othersubr_result_cnt   = 0;
00716         unknown_othersubr_result_cnt = 0;
00717 
00718         /* XXX TODO: The checks to `arg_count == <whatever>'       */
00719         /* might not be correct; an othersubr expects a certain    */
00720         /* number of operands on the PostScript stack (as opposed  */
00721         /* to the T1 stack) but it doesn't have to put them there  */
00722         /* by itself; previous othersubrs might have left the      */
00723         /* operands there if they were not followed by an          */
00724         /* appropriate number of pops                              */
00725         /*                                                         */
00726         /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
00727         /* accept a font that contains charstrings like            */
00728         /*                                                         */
00729         /*     100 200 2 20 callothersubr                          */
00730         /*     300 1 20 callothersubr pop                          */
00731         /*                                                         */
00732         /* Perhaps this is the reason why BuildCharArray exists.   */
00733 
00734         switch ( subr_no )
00735         {
00736         case 1:                     /* start flex feature */
00737           if ( arg_cnt != 0 )
00738             goto Unexpected_OtherSubr;
00739 
00740           decoder->flex_state        = 1;
00741           decoder->num_flex_vectors  = 0;
00742           if ( start_point( builder, x, y ) ||
00743                check_points( builder, 6 )   )
00744             goto Fail;
00745           break;
00746 
00747         case 2:                     /* add flex vectors */
00748           {
00749             FT_Int  idx;
00750 
00751 
00752             if ( arg_cnt != 0 )
00753               goto Unexpected_OtherSubr;
00754 
00755             /* note that we should not add a point for index 0; */
00756             /* this will move our current position to the flex  */
00757             /* point without adding any point to the outline    */
00758             idx = decoder->num_flex_vectors++;
00759             if ( idx > 0 && idx < 7 )
00760               add_point( builder,
00761                          x,
00762                          y,
00763                          (FT_Byte)( idx == 3 || idx == 6 ) );
00764           }
00765           break;
00766 
00767         case 0:                     /* end flex feature */
00768           if ( arg_cnt != 3 )
00769             goto Unexpected_OtherSubr;
00770 
00771           if ( decoder->flex_state       == 0 ||
00772                decoder->num_flex_vectors != 7 )
00773           {
00774             FT_ERROR(( "t1_decoder_parse_charstrings:"
00775                        " unexpected flex end\n" ));
00776             goto Syntax_Error;
00777           }
00778 
00779           /* the two `results' are popped by the following setcurrentpoint */
00780           known_othersubr_result_cnt = 2;
00781           break;
00782 
00783         case 3:                     /* change hints */
00784           if ( arg_cnt != 1 )
00785             goto Unexpected_OtherSubr;
00786 
00787           known_othersubr_result_cnt = 1;
00788 
00789           if ( hinter )
00790             hinter->reset( hinter->hints, builder->current->n_points );
00791           break;
00792 
00793         case 12:
00794         case 13:
00795           /* counter control hints, clear stack */
00796           top = decoder->stack;
00797           break;
00798 
00799         case 14:
00800         case 15:
00801         case 16:
00802         case 17:
00803         case 18:                    /* multiple masters */
00804           {
00805             PS_Blend  blend = decoder->blend;
00806             FT_UInt   num_points, nn, mm;
00807             FT_Long*  delta;
00808             FT_Long*  values;
00809 
00810 
00811             if ( !blend )
00812             {
00813               FT_ERROR(( "t1_decoder_parse_charstrings:"
00814                          " unexpected multiple masters operator\n" ));
00815               goto Syntax_Error;
00816             }
00817 
00818             num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );
00819             if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )
00820             {
00821               FT_ERROR(( "t1_decoder_parse_charstrings:"
00822                          " incorrect number of multiple masters arguments\n" ));
00823               goto Syntax_Error;
00824             }
00825 
00826             /* we want to compute:                                   */
00827             /*                                                       */
00828             /*  a0*w0 + a1*w1 + ... + ak*wk                          */
00829             /*                                                       */
00830             /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
00831             /* however, given that w0 + w1 + ... + wk == 1, we can   */
00832             /* rewrite it easily as:                                 */
00833             /*                                                       */
00834             /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
00835             /*                                                       */
00836             /* where k == num_designs-1                              */
00837             /*                                                       */
00838             /* I guess that's why it's written in this `compact'     */
00839             /* form.                                                 */
00840             /*                                                       */
00841             delta  = top + num_points;
00842             values = top;
00843             for ( nn = 0; nn < num_points; nn++ )
00844             {
00845               FT_Long  tmp = values[0];
00846 
00847 
00848               for ( mm = 1; mm < blend->num_designs; mm++ )
00849                 tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
00850 
00851               *values++ = tmp;
00852             }
00853 
00854             known_othersubr_result_cnt = num_points;
00855             break;
00856           }
00857 
00858         case 19:
00859           /* <idx> 1 19 callothersubr                             */
00860           /* => replace elements starting from index cvi( <idx> ) */
00861           /*    of BuildCharArray with WeightVector               */
00862           {
00863             FT_Int    idx;
00864             PS_Blend  blend = decoder->blend;
00865 
00866 
00867             if ( arg_cnt != 1 || blend == NULL )
00868               goto Unexpected_OtherSubr;
00869 
00870             idx = (FT_Int)( top[0] >> 16 );
00871 
00872             if ( idx < 0                                           ||
00873                  idx + blend->num_designs > decoder->len_buildchar )
00874               goto Unexpected_OtherSubr;
00875 
00876             ft_memcpy( &decoder->buildchar[idx],
00877                        blend->weight_vector,
00878                        blend->num_designs *
00879                          sizeof( blend->weight_vector[0] ) );
00880           }
00881           break;
00882 
00883         case 20:
00884           /* <arg1> <arg2> 2 20 callothersubr pop   */
00885           /* ==> push <arg1> + <arg2> onto T1 stack */
00886           if ( arg_cnt != 2 )
00887             goto Unexpected_OtherSubr;
00888 
00889           top[0] += top[1]; /* XXX (over|under)flow */
00890 
00891           known_othersubr_result_cnt = 1;
00892           break;
00893 
00894         case 21:
00895           /* <arg1> <arg2> 2 21 callothersubr pop   */
00896           /* ==> push <arg1> - <arg2> onto T1 stack */
00897           if ( arg_cnt != 2 )
00898             goto Unexpected_OtherSubr;
00899 
00900           top[0] -= top[1]; /* XXX (over|under)flow */
00901 
00902           known_othersubr_result_cnt = 1;
00903           break;
00904 
00905         case 22:
00906           /* <arg1> <arg2> 2 22 callothersubr pop   */
00907           /* ==> push <arg1> * <arg2> onto T1 stack */
00908           if ( arg_cnt != 2 )
00909             goto Unexpected_OtherSubr;
00910 
00911           top[0] = FT_MulFix( top[0], top[1] );
00912 
00913           known_othersubr_result_cnt = 1;
00914           break;
00915 
00916         case 23:
00917           /* <arg1> <arg2> 2 23 callothersubr pop   */
00918           /* ==> push <arg1> / <arg2> onto T1 stack */
00919           if ( arg_cnt != 2 || top[1] == 0 )
00920             goto Unexpected_OtherSubr;
00921 
00922           top[0] = FT_DivFix( top[0], top[1] );
00923 
00924           known_othersubr_result_cnt = 1;
00925           break;
00926 
00927         case 24:
00928           /* <val> <idx> 2 24 callothersubr               */
00929           /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
00930           {
00931             FT_Int    idx;
00932             PS_Blend  blend = decoder->blend;
00933 
00934 
00935             if ( arg_cnt != 2 || blend == NULL )
00936               goto Unexpected_OtherSubr;
00937 
00938             idx = (FT_Int)( top[1] >> 16 );
00939 
00940             if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
00941               goto Unexpected_OtherSubr;
00942 
00943             decoder->buildchar[idx] = top[0];
00944           }
00945           break;
00946 
00947         case 25:
00948           /* <idx> 1 25 callothersubr pop        */
00949           /* ==> push BuildCharArray[cvi( idx )] */
00950           /*     onto T1 stack                   */
00951           {
00952             FT_Int    idx;
00953             PS_Blend  blend = decoder->blend;
00954 
00955 
00956             if ( arg_cnt != 1 || blend == NULL )
00957               goto Unexpected_OtherSubr;
00958 
00959             idx = (FT_Int)( top[0] >> 16 );
00960 
00961             if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
00962               goto Unexpected_OtherSubr;
00963 
00964             top[0] = decoder->buildchar[idx];
00965           }
00966 
00967           known_othersubr_result_cnt = 1;
00968           break;
00969 
00970 #if 0
00971         case 26:
00972           /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
00973           /*                      leave mark on T1 stack                    */
00974           /* <val> <idx>      ==> set BuildCharArray[cvi( <idx> )] = <val>  */
00975           XXX which routine has left its mark on the (PostScript) stack?;
00976           break;
00977 #endif
00978 
00979         case 27:
00980           /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
00981           /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
00982           /*     otherwise push <res2>                          */
00983           if ( arg_cnt != 4 )
00984             goto Unexpected_OtherSubr;
00985 
00986           if ( top[2] > top[3] )
00987             top[0] = top[1];
00988 
00989           known_othersubr_result_cnt = 1;
00990           break;
00991 
00992         case 28:
00993           /* 0 28 callothersubr pop                               */
00994           /* => push random value from interval [0, 1) onto stack */
00995           if ( arg_cnt != 0 )
00996             goto Unexpected_OtherSubr;
00997 
00998           {
00999             FT_Fixed  Rand;
01000 
01001 
01002             Rand = seed;
01003             if ( Rand >= 0x8000L )
01004               Rand++;
01005 
01006             top[0] = Rand;
01007 
01008             seed = FT_MulFix( seed, 0x10000L - seed );
01009             if ( seed == 0 )
01010               seed += 0x2873;
01011           }
01012 
01013           known_othersubr_result_cnt = 1;
01014           break;
01015 
01016         default:
01017           FT_ERROR(( "t1_decoder_parse_charstrings:"
01018                      " unknown othersubr [%d %d], wish me luck\n",
01019                      arg_cnt, subr_no ));
01020           unknown_othersubr_result_cnt = arg_cnt;
01021           break;
01022 
01023         Unexpected_OtherSubr:
01024           FT_ERROR(( "t1_decoder_parse_charstrings:"
01025                      " invalid othersubr [%d %d]\n", arg_cnt, subr_no ));
01026           goto Syntax_Error;
01027         }
01028 
01029         top += known_othersubr_result_cnt;
01030 
01031         decoder->top = top;
01032       }
01033       else  /* general operator */
01034       {
01035         FT_Int  num_args = t1_args_count[op];
01036 
01037 
01038         FT_ASSERT( num_args >= 0 );
01039 
01040         if ( top - decoder->stack < num_args )
01041           goto Stack_Underflow;
01042 
01043         /* XXX Operators usually take their operands from the        */
01044         /*     bottom of the stack, i.e., the operands are           */
01045         /*     decoder->stack[0], ..., decoder->stack[num_args - 1]; */
01046         /*     only div, callsubr, and callothersubr are different.  */
01047         /*     In practice it doesn't matter (?).                    */
01048 
01049 #ifdef FT_DEBUG_LEVEL_TRACE
01050 
01051         switch ( op )
01052         {
01053         case op_callsubr:
01054         case op_div:
01055         case op_callothersubr:
01056         case op_pop:
01057         case op_return:
01058           break;
01059 
01060         default:
01061           if ( top - decoder->stack != num_args )
01062             FT_TRACE0(( "t1_decoder_parse_charstrings:"
01063                         " too much operands on the stack"
01064                         " (seen %d, expected %d)\n",
01065                         top - decoder->stack, num_args ));
01066             break;
01067         }
01068 
01069 #endif /* FT_DEBUG_LEVEL_TRACE */
01070 
01071         top -= num_args;
01072 
01073         switch ( op )
01074         {
01075         case op_endchar:
01076           FT_TRACE4(( " endchar\n" ));
01077 
01078           close_contour( builder );
01079 
01080           /* close hints recording session */
01081           if ( hinter )
01082           {
01083             if ( hinter->close( hinter->hints, builder->current->n_points ) )
01084               goto Syntax_Error;
01085 
01086             /* apply hints to the loaded glyph outline now */
01087             hinter->apply( hinter->hints,
01088                            builder->current,
01089                            (PSH_Globals)builder->hints_globals,
01090                            decoder->hint_mode );
01091           }
01092 
01093           /* add current outline to the glyph slot */
01094           FT_GlyphLoader_Add( builder->loader );
01095 
01096           /* the compiler should optimize away this empty loop but ... */
01097 
01098 #ifdef FT_DEBUG_LEVEL_TRACE
01099 
01100           if ( decoder->len_buildchar > 0 )
01101           {
01102             FT_UInt  i;
01103 
01104 
01105             FT_TRACE4(( "BuildCharArray = [ " ));
01106 
01107             for ( i = 0; i < decoder->len_buildchar; ++i )
01108               FT_TRACE4(( "%d ", decoder->buildchar[ i ] ));
01109 
01110             FT_TRACE4(( "]\n" ));
01111           }
01112 
01113 #endif /* FT_DEBUG_LEVEL_TRACE */
01114 
01115           FT_TRACE4(( "\n" ));
01116 
01117           /* return now! */
01118           return PSaux_Err_Ok;
01119 
01120         case op_hsbw:
01121           FT_TRACE4(( " hsbw" ));
01122 
01123           builder->parse_state = T1_Parse_Have_Width;
01124 
01125           builder->left_bearing.x += top[0];
01126           builder->advance.x       = top[1];
01127           builder->advance.y       = 0;
01128 
01129           orig_x = x = builder->pos_x + top[0];
01130           orig_y = y = builder->pos_y;
01131 
01132           FT_UNUSED( orig_y );
01133 
01134           /* the `metrics_only' indicates that we only want to compute */
01135           /* the glyph's metrics (lsb + advance width), not load the   */
01136           /* rest of it; so exit immediately                           */
01137           if ( builder->metrics_only )
01138             return PSaux_Err_Ok;
01139 
01140           break;
01141 
01142         case op_seac:
01143           return t1operator_seac( decoder,
01144                                   top[0],
01145                                   top[1],
01146                                   top[2],
01147                                   (FT_Int)( top[3] >> 16 ),
01148                                   (FT_Int)( top[4] >> 16 ) );
01149 
01150         case op_sbw:
01151           FT_TRACE4(( " sbw" ));
01152 
01153           builder->parse_state = T1_Parse_Have_Width;
01154 
01155           builder->left_bearing.x += top[0];
01156           builder->left_bearing.y += top[1];
01157           builder->advance.x       = top[2];
01158           builder->advance.y       = top[3];
01159 
01160           x = builder->pos_x + top[0];
01161           y = builder->pos_y + top[1];
01162 
01163           /* the `metrics_only' indicates that we only want to compute */
01164           /* the glyph's metrics (lsb + advance width), not load the   */
01165           /* rest of it; so exit immediately                           */
01166           if ( builder->metrics_only )
01167             return PSaux_Err_Ok;
01168 
01169           break;
01170 
01171         case op_closepath:
01172           FT_TRACE4(( " closepath" ));
01173 
01174           /* if there is no path, `closepath' is a no-op */
01175           if ( builder->parse_state == T1_Parse_Have_Path   ||
01176                builder->parse_state == T1_Parse_Have_Moveto )
01177             close_contour( builder );
01178 
01179           builder->parse_state = T1_Parse_Have_Width;
01180           break;
01181 
01182         case op_hlineto:
01183           FT_TRACE4(( " hlineto" ));
01184 
01185           if ( start_point( builder, x, y ) )
01186             goto Fail;
01187 
01188           x += top[0];
01189           goto Add_Line;
01190 
01191         case op_hmoveto:
01192           FT_TRACE4(( " hmoveto" ));
01193 
01194           x += top[0];
01195           if ( !decoder->flex_state )
01196           {
01197             if ( builder->parse_state == T1_Parse_Start )
01198               goto Syntax_Error;
01199             builder->parse_state = T1_Parse_Have_Moveto;
01200           }
01201           break;
01202 
01203         case op_hvcurveto:
01204           FT_TRACE4(( " hvcurveto" ));
01205 
01206           if ( start_point( builder, x, y ) ||
01207                check_points( builder, 3 )   )
01208             goto Fail;
01209 
01210           x += top[0];
01211           add_point( builder, x, y, 0 );
01212           x += top[1];
01213           y += top[2];
01214           add_point( builder, x, y, 0 );
01215           y += top[3];
01216           add_point( builder, x, y, 1 );
01217           break;
01218 
01219         case op_rlineto:
01220           FT_TRACE4(( " rlineto" ));
01221 
01222           if ( start_point( builder, x, y ) )
01223             goto Fail;
01224 
01225           x += top[0];
01226           y += top[1];
01227 
01228         Add_Line:
01229           if ( add_point1( builder, x, y ) )
01230             goto Fail;
01231           break;
01232 
01233         case op_rmoveto:
01234           FT_TRACE4(( " rmoveto" ));
01235 
01236           x += top[0];
01237           y += top[1];
01238           if ( !decoder->flex_state )
01239           {
01240             if ( builder->parse_state == T1_Parse_Start )
01241               goto Syntax_Error;
01242             builder->parse_state = T1_Parse_Have_Moveto;
01243           }
01244           break;
01245 
01246         case op_rrcurveto:
01247           FT_TRACE4(( " rrcurveto" ));
01248 
01249           if ( start_point( builder, x, y ) ||
01250                check_points( builder, 3 )   )
01251             goto Fail;
01252 
01253           x += top[0];
01254           y += top[1];
01255           add_point( builder, x, y, 0 );
01256 
01257           x += top[2];
01258           y += top[3];
01259           add_point( builder, x, y, 0 );
01260 
01261           x += top[4];
01262           y += top[5];
01263           add_point( builder, x, y, 1 );
01264           break;
01265 
01266         case op_vhcurveto:
01267           FT_TRACE4(( " vhcurveto" ));
01268 
01269           if ( start_point( builder, x, y ) ||
01270                check_points( builder, 3 )   )
01271             goto Fail;
01272 
01273           y += top[0];
01274           add_point( builder, x, y, 0 );
01275           x += top[1];
01276           y += top[2];
01277           add_point( builder, x, y, 0 );
01278           x += top[3];
01279           add_point( builder, x, y, 1 );
01280           break;
01281 
01282         case op_vlineto:
01283           FT_TRACE4(( " vlineto" ));
01284 
01285           if ( start_point( builder, x, y ) )
01286             goto Fail;
01287 
01288           y += top[0];
01289           goto Add_Line;
01290 
01291         case op_vmoveto:
01292           FT_TRACE4(( " vmoveto" ));
01293 
01294           y += top[0];
01295           if ( !decoder->flex_state )
01296           {
01297             if ( builder->parse_state == T1_Parse_Start )
01298               goto Syntax_Error;
01299             builder->parse_state = T1_Parse_Have_Moveto;
01300           }
01301           break;
01302 
01303         case op_div:
01304           FT_TRACE4(( " div" ));
01305 
01306           /* if `large_int' is set, we divide unscaled numbers; */
01307           /* otherwise, we divide numbers in 16.16 format --    */
01308           /* in both cases, it is the same operation            */
01309           *top = FT_DivFix( top[0], top[1] );
01310           ++top;
01311 
01312           large_int = FALSE;
01313           break;
01314 
01315         case op_callsubr:
01316           {
01317             FT_Int  idx;
01318 
01319 
01320             FT_TRACE4(( " callsubr" ));
01321 
01322             idx = (FT_Int)( top[0] >> 16 );
01323             if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
01324             {
01325               FT_ERROR(( "t1_decoder_parse_charstrings:"
01326                          " invalid subrs index\n" ));
01327               goto Syntax_Error;
01328             }
01329 
01330             if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
01331             {
01332               FT_ERROR(( "t1_decoder_parse_charstrings:"
01333                          " too many nested subrs\n" ));
01334               goto Syntax_Error;
01335             }
01336 
01337             zone->cursor = ip;  /* save current instruction pointer */
01338 
01339             zone++;
01340 
01341             /* The Type 1 driver stores subroutines without the seed bytes. */
01342             /* The CID driver stores subroutines with seed bytes.  This     */
01343             /* case is taken care of when decoder->subrs_len == 0.          */
01344             zone->base = decoder->subrs[idx];
01345 
01346             if ( decoder->subrs_len )
01347               zone->limit = zone->base + decoder->subrs_len[idx];
01348             else
01349             {
01350               /* We are using subroutines from a CID font.  We must adjust */
01351               /* for the seed bytes.                                       */
01352               zone->base  += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
01353               zone->limit  = decoder->subrs[idx + 1];
01354             }
01355 
01356             zone->cursor = zone->base;
01357 
01358             if ( !zone->base )
01359             {
01360               FT_ERROR(( "t1_decoder_parse_charstrings:"
01361                          " invoking empty subrs\n" ));
01362               goto Syntax_Error;
01363             }
01364 
01365             decoder->zone = zone;
01366             ip            = zone->base;
01367             limit         = zone->limit;
01368             break;
01369           }
01370 
01371         case op_pop:
01372           FT_TRACE4(( " pop" ));
01373 
01374           if ( known_othersubr_result_cnt > 0 )
01375           {
01376             known_othersubr_result_cnt--;
01377             /* ignore, we pushed the operands ourselves */
01378             break;
01379           }
01380 
01381           if ( unknown_othersubr_result_cnt == 0 )
01382           {
01383             FT_ERROR(( "t1_decoder_parse_charstrings:"
01384                        " no more operands for othersubr\n" ));
01385             goto Syntax_Error;
01386           }
01387 
01388           unknown_othersubr_result_cnt--;
01389           top++;   /* `push' the operand to callothersubr onto the stack */
01390           break;
01391 
01392         case op_return:
01393           FT_TRACE4(( " return" ));
01394 
01395           if ( zone <= decoder->zones )
01396           {
01397             FT_ERROR(( "t1_decoder_parse_charstrings:"
01398                        " unexpected return\n" ));
01399             goto Syntax_Error;
01400           }
01401 
01402           zone--;
01403           ip            = zone->cursor;
01404           limit         = zone->limit;
01405           decoder->zone = zone;
01406           break;
01407 
01408         case op_dotsection:
01409           FT_TRACE4(( " dotsection" ));
01410 
01411           break;
01412 
01413         case op_hstem:
01414           FT_TRACE4(( " hstem" ));
01415 
01416           /* record horizontal hint */
01417           if ( hinter )
01418           {
01419             /* top[0] += builder->left_bearing.y; */
01420             hinter->stem( hinter->hints, 1, top );
01421           }
01422           break;
01423 
01424         case op_hstem3:
01425           FT_TRACE4(( " hstem3" ));
01426 
01427           /* record horizontal counter-controlled hints */
01428           if ( hinter )
01429             hinter->stem3( hinter->hints, 1, top );
01430           break;
01431 
01432         case op_vstem:
01433           FT_TRACE4(( " vstem" ));
01434 
01435           /* record vertical hint */
01436           if ( hinter )
01437           {
01438             top[0] += orig_x;
01439             hinter->stem( hinter->hints, 0, top );
01440           }
01441           break;
01442 
01443         case op_vstem3:
01444           FT_TRACE4(( " vstem3" ));
01445 
01446           /* record vertical counter-controlled hints */
01447           if ( hinter )
01448           {
01449             FT_Pos  dx = orig_x;
01450 
01451 
01452             top[0] += dx;
01453             top[2] += dx;
01454             top[4] += dx;
01455             hinter->stem3( hinter->hints, 0, top );
01456           }
01457           break;
01458 
01459         case op_setcurrentpoint:
01460           FT_TRACE4(( " setcurrentpoint" ));
01461 
01462           /* From the T1 specification, section 6.4:                */
01463           /*                                                        */
01464           /*   The setcurrentpoint command is used only in          */
01465           /*   conjunction with results from OtherSubrs procedures. */
01466 
01467           /* known_othersubr_result_cnt != 0 is already handled     */
01468           /* above.                                                 */
01469 
01470           /* Note, however, that both Ghostscript and Adobe         */
01471           /* Distiller handle this situation by silently ignoring   */
01472           /* the inappropriate `setcurrentpoint' instruction.  So   */
01473           /* we do the same.                                        */
01474 #if 0
01475 
01476           if ( decoder->flex_state != 1 )
01477           {
01478             FT_ERROR(( "t1_decoder_parse_charstrings:"
01479                        " unexpected `setcurrentpoint'\n" ));
01480             goto Syntax_Error;
01481           }
01482           else
01483 #endif
01484             decoder->flex_state = 0;
01485           break;
01486 
01487         case op_unknown15:
01488           FT_TRACE4(( " opcode_15" ));
01489           /* nothing to do except to pop the two arguments */
01490           break;
01491 
01492         default:
01493           FT_ERROR(( "t1_decoder_parse_charstrings:"
01494                      " unhandled opcode %d\n", op ));
01495           goto Syntax_Error;
01496         }
01497 
01498         /* XXX Operators usually clear the operand stack;  */
01499         /*     only div, callsubr, callothersubr, pop, and */
01500         /*     return are different.                       */
01501         /*     In practice it doesn't matter (?).          */
01502 
01503         decoder->top = top;
01504 
01505 #ifdef FT_DEBUG_LEVEL_TRACE
01506         FT_TRACE4(( "\n" ));
01507         bol = TRUE;
01508 #endif
01509 
01510       } /* general operator processing */
01511 
01512     } /* while ip < limit */
01513 
01514     FT_TRACE4(( "..end..\n\n" ));
01515 
01516   Fail:
01517     return error;
01518 
01519   Syntax_Error:
01520     return PSaux_Err_Syntax_Error;
01521 
01522   Stack_Underflow:
01523     return PSaux_Err_Stack_Underflow;
01524   }
01525 
01526 
01527   /* parse a single Type 1 glyph */
01528   FT_LOCAL_DEF( FT_Error )
01529   t1_decoder_parse_glyph( T1_Decoder  decoder,
01530                           FT_UInt     glyph )
01531   {
01532     return decoder->parse_callback( decoder, glyph );
01533   }
01534 
01535 
01536   /* initialize T1 decoder */
01537   FT_LOCAL_DEF( FT_Error )
01538   t1_decoder_init( T1_Decoder           decoder,
01539                    FT_Face              face,
01540                    FT_Size              size,
01541                    FT_GlyphSlot         slot,
01542                    FT_Byte**            glyph_names,
01543                    PS_Blend             blend,
01544                    FT_Bool              hinting,
01545                    FT_Render_Mode       hint_mode,
01546                    T1_Decoder_Callback  parse_callback )
01547   {
01548     FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
01549 
01550     /* retrieve PSNames interface from list of current modules */
01551     {
01552       FT_Service_PsCMaps  psnames = 0;
01553 
01554 
01555       FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
01556       if ( !psnames )
01557       {
01558         FT_ERROR(( "t1_decoder_init:"
01559                    " the `psnames' module is not available\n" ));
01560         return PSaux_Err_Unimplemented_Feature;
01561       }
01562 
01563       decoder->psnames = psnames;
01564     }
01565 
01566     t1_builder_init( &decoder->builder, face, size, slot, hinting );
01567 
01568     /* decoder->buildchar and decoder->len_buildchar have to be  */
01569     /* initialized by the caller since we cannot know the length */
01570     /* of the BuildCharArray                                     */
01571 
01572     decoder->num_glyphs     = (FT_UInt)face->num_glyphs;
01573     decoder->glyph_names    = glyph_names;
01574     decoder->hint_mode      = hint_mode;
01575     decoder->blend          = blend;
01576     decoder->parse_callback = parse_callback;
01577 
01578     decoder->funcs          = t1_decoder_funcs;
01579 
01580     return PSaux_Err_Ok;
01581   }
01582 
01583 
01584   /* finalize T1 decoder */
01585   FT_LOCAL_DEF( void )
01586   t1_decoder_done( T1_Decoder  decoder )
01587   {
01588     t1_builder_done( &decoder->builder );
01589   }
01590 
01591 
01592 /* END */

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