misc/libfreetype/src/psaux/t1decode.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  t1decode.c                                                             */
       
     4 /*                                                                         */
       
     5 /*    PostScript Type 1 decoding routines (body).                          */
       
     6 /*                                                                         */
       
     7 /*  Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009    */
       
     8 /*            2010 by                                                      */
       
     9 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
       
    10 /*                                                                         */
       
    11 /*  This file is part of the FreeType project, and may only be used,       */
       
    12 /*  modified, and distributed under the terms of the FreeType project      */
       
    13 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
       
    14 /*  this file you indicate that you have read the license and              */
       
    15 /*  understand and accept it fully.                                        */
       
    16 /*                                                                         */
       
    17 /***************************************************************************/
       
    18 
       
    19 
       
    20 #include <ft2build.h>
       
    21 #include FT_INTERNAL_CALC_H
       
    22 #include FT_INTERNAL_DEBUG_H
       
    23 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
       
    24 #include FT_OUTLINE_H
       
    25 
       
    26 #include "t1decode.h"
       
    27 #include "psobjs.h"
       
    28 
       
    29 #include "psauxerr.h"
       
    30 
       
    31 
       
    32   /*************************************************************************/
       
    33   /*                                                                       */
       
    34   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
    35   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
    36   /* messages during execution.                                            */
       
    37   /*                                                                       */
       
    38 #undef  FT_COMPONENT
       
    39 #define FT_COMPONENT  trace_t1decode
       
    40 
       
    41 
       
    42   typedef enum  T1_Operator_
       
    43   {
       
    44     op_none = 0,
       
    45     op_endchar,
       
    46     op_hsbw,
       
    47     op_seac,
       
    48     op_sbw,
       
    49     op_closepath,
       
    50     op_hlineto,
       
    51     op_hmoveto,
       
    52     op_hvcurveto,
       
    53     op_rlineto,
       
    54     op_rmoveto,
       
    55     op_rrcurveto,
       
    56     op_vhcurveto,
       
    57     op_vlineto,
       
    58     op_vmoveto,
       
    59     op_dotsection,
       
    60     op_hstem,
       
    61     op_hstem3,
       
    62     op_vstem,
       
    63     op_vstem3,
       
    64     op_div,
       
    65     op_callothersubr,
       
    66     op_callsubr,
       
    67     op_pop,
       
    68     op_return,
       
    69     op_setcurrentpoint,
       
    70     op_unknown15,
       
    71 
       
    72     op_max    /* never remove this one */
       
    73 
       
    74   } T1_Operator;
       
    75 
       
    76 
       
    77   static
       
    78   const FT_Int  t1_args_count[op_max] =
       
    79   {
       
    80     0, /* none */
       
    81     0, /* endchar */
       
    82     2, /* hsbw */
       
    83     5, /* seac */
       
    84     4, /* sbw */
       
    85     0, /* closepath */
       
    86     1, /* hlineto */
       
    87     1, /* hmoveto */
       
    88     4, /* hvcurveto */
       
    89     2, /* rlineto */
       
    90     2, /* rmoveto */
       
    91     6, /* rrcurveto */
       
    92     4, /* vhcurveto */
       
    93     1, /* vlineto */
       
    94     1, /* vmoveto */
       
    95     0, /* dotsection */
       
    96     2, /* hstem */
       
    97     6, /* hstem3 */
       
    98     2, /* vstem */
       
    99     6, /* vstem3 */
       
   100     2, /* div */
       
   101    -1, /* callothersubr */
       
   102     1, /* callsubr */
       
   103     0, /* pop */
       
   104     0, /* return */
       
   105     2, /* setcurrentpoint */
       
   106     2  /* opcode 15 (undocumented and obsolete) */
       
   107   };
       
   108 
       
   109 
       
   110   /*************************************************************************/
       
   111   /*                                                                       */
       
   112   /* <Function>                                                            */
       
   113   /*    t1_lookup_glyph_by_stdcharcode                                     */
       
   114   /*                                                                       */
       
   115   /* <Description>                                                         */
       
   116   /*    Looks up a given glyph by its StandardEncoding charcode.  Used to  */
       
   117   /*    implement the SEAC Type 1 operator.                                */
       
   118   /*                                                                       */
       
   119   /* <Input>                                                               */
       
   120   /*    face     :: The current face object.                               */
       
   121   /*                                                                       */
       
   122   /*    charcode :: The character code to look for.                        */
       
   123   /*                                                                       */
       
   124   /* <Return>                                                              */
       
   125   /*    A glyph index in the font face.  Returns -1 if the corresponding   */
       
   126   /*    glyph wasn't found.                                                */
       
   127   /*                                                                       */
       
   128   static FT_Int
       
   129   t1_lookup_glyph_by_stdcharcode( T1_Decoder  decoder,
       
   130                                   FT_Int      charcode )
       
   131   {
       
   132     FT_UInt             n;
       
   133     const FT_String*    glyph_name;
       
   134     FT_Service_PsCMaps  psnames = decoder->psnames;
       
   135 
       
   136 
       
   137     /* check range of standard char code */
       
   138     if ( charcode < 0 || charcode > 255 )
       
   139       return -1;
       
   140 
       
   141     glyph_name = psnames->adobe_std_strings(
       
   142                    psnames->adobe_std_encoding[charcode]);
       
   143 
       
   144     for ( n = 0; n < decoder->num_glyphs; n++ )
       
   145     {
       
   146       FT_String*  name = (FT_String*)decoder->glyph_names[n];
       
   147 
       
   148 
       
   149       if ( name                               &&
       
   150            name[0] == glyph_name[0]           &&
       
   151            ft_strcmp( name, glyph_name ) == 0 )
       
   152         return n;
       
   153     }
       
   154 
       
   155     return -1;
       
   156   }
       
   157 
       
   158 
       
   159   /*************************************************************************/
       
   160   /*                                                                       */
       
   161   /* <Function>                                                            */
       
   162   /*    t1operator_seac                                                    */
       
   163   /*                                                                       */
       
   164   /* <Description>                                                         */
       
   165   /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
       
   166   /*                                                                       */
       
   167   /* <Input>                                                               */
       
   168   /*    decoder :: The current CID decoder.                                */
       
   169   /*                                                                       */
       
   170   /*    asb     :: The accent's side bearing.                              */
       
   171   /*                                                                       */
       
   172   /*    adx     :: The horizontal offset of the accent.                    */
       
   173   /*                                                                       */
       
   174   /*    ady     :: The vertical offset of the accent.                      */
       
   175   /*                                                                       */
       
   176   /*    bchar   :: The base character's StandardEncoding charcode.         */
       
   177   /*                                                                       */
       
   178   /*    achar   :: The accent character's StandardEncoding charcode.       */
       
   179   /*                                                                       */
       
   180   /* <Return>                                                              */
       
   181   /*    FreeType error code.  0 means success.                             */
       
   182   /*                                                                       */
       
   183   static FT_Error
       
   184   t1operator_seac( T1_Decoder  decoder,
       
   185                    FT_Pos      asb,
       
   186                    FT_Pos      adx,
       
   187                    FT_Pos      ady,
       
   188                    FT_Int      bchar,
       
   189                    FT_Int      achar )
       
   190   {
       
   191     FT_Error     error;
       
   192     FT_Int       bchar_index, achar_index;
       
   193 #if 0
       
   194     FT_Int       n_base_points;
       
   195     FT_Outline*  base = decoder->builder.base;
       
   196 #endif
       
   197     FT_Vector    left_bearing, advance;
       
   198 
       
   199 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       
   200     T1_Face      face  = (T1_Face)decoder->builder.face;
       
   201 #endif     
       
   202 
       
   203 
       
   204     if ( decoder->seac )
       
   205     {
       
   206       FT_ERROR(( "t1operator_seac: invalid nested seac\n" ));
       
   207       return PSaux_Err_Syntax_Error;
       
   208     }
       
   209 
       
   210     /* seac weirdness */
       
   211     adx += decoder->builder.left_bearing.x;
       
   212 
       
   213     /* `glyph_names' is set to 0 for CID fonts which do not */
       
   214     /* include an encoding.  How can we deal with these?    */
       
   215 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       
   216     if ( decoder->glyph_names == 0                   &&
       
   217          !face->root.internal->incremental_interface )
       
   218 #else
       
   219     if ( decoder->glyph_names == 0 )
       
   220 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
       
   221     {
       
   222       FT_ERROR(( "t1operator_seac:"
       
   223                  " glyph names table not available in this font\n" ));
       
   224       return PSaux_Err_Syntax_Error;
       
   225     }
       
   226 
       
   227 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       
   228     if ( face->root.internal->incremental_interface )
       
   229     {
       
   230       /* the caller must handle the font encoding also */
       
   231       bchar_index = bchar;
       
   232       achar_index = achar;
       
   233     }
       
   234     else
       
   235 #endif
       
   236     {
       
   237       bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
       
   238       achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
       
   239     }
       
   240 
       
   241     if ( bchar_index < 0 || achar_index < 0 )
       
   242     {
       
   243       FT_ERROR(( "t1operator_seac:"
       
   244                  " invalid seac character code arguments\n" ));
       
   245       return PSaux_Err_Syntax_Error;
       
   246     }
       
   247 
       
   248     /* if we are trying to load a composite glyph, do not load the */
       
   249     /* accent character and return the array of subglyphs.         */
       
   250     if ( decoder->builder.no_recurse )
       
   251     {
       
   252       FT_GlyphSlot    glyph  = (FT_GlyphSlot)decoder->builder.glyph;
       
   253       FT_GlyphLoader  loader = glyph->internal->loader;
       
   254       FT_SubGlyph     subg;
       
   255 
       
   256 
       
   257       /* reallocate subglyph array if necessary */
       
   258       error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
       
   259       if ( error )
       
   260         goto Exit;
       
   261 
       
   262       subg = loader->current.subglyphs;
       
   263 
       
   264       /* subglyph 0 = base character */
       
   265       subg->index = bchar_index;
       
   266       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
       
   267                     FT_SUBGLYPH_FLAG_USE_MY_METRICS;
       
   268       subg->arg1  = 0;
       
   269       subg->arg2  = 0;
       
   270       subg++;
       
   271 
       
   272       /* subglyph 1 = accent character */
       
   273       subg->index = achar_index;
       
   274       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
       
   275       subg->arg1  = (FT_Int)FIXED_TO_INT( adx - asb );
       
   276       subg->arg2  = (FT_Int)FIXED_TO_INT( ady );
       
   277 
       
   278       /* set up remaining glyph fields */
       
   279       glyph->num_subglyphs = 2;
       
   280       glyph->subglyphs     = loader->base.subglyphs;
       
   281       glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
       
   282 
       
   283       loader->current.num_subglyphs = 2;
       
   284       goto Exit;
       
   285     }
       
   286 
       
   287     /* First load `bchar' in builder */
       
   288     /* now load the unscaled outline */
       
   289 
       
   290     FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
       
   291 
       
   292     /* the seac operator must not be nested */
       
   293     decoder->seac = TRUE;
       
   294     error = t1_decoder_parse_glyph( decoder, bchar_index );
       
   295     decoder->seac = FALSE;
       
   296     if ( error )
       
   297       goto Exit;
       
   298 
       
   299     /* save the left bearing and width of the base character */
       
   300     /* as they will be erased by the next load.              */
       
   301 
       
   302     left_bearing = decoder->builder.left_bearing;
       
   303     advance      = decoder->builder.advance;
       
   304 
       
   305     decoder->builder.left_bearing.x = 0;
       
   306     decoder->builder.left_bearing.y = 0;
       
   307 
       
   308     decoder->builder.pos_x = adx - asb;
       
   309     decoder->builder.pos_y = ady;
       
   310 
       
   311     /* Now load `achar' on top of */
       
   312     /* the base outline           */
       
   313 
       
   314     /* the seac operator must not be nested */
       
   315     decoder->seac = TRUE;
       
   316     error = t1_decoder_parse_glyph( decoder, achar_index );
       
   317     decoder->seac = FALSE;
       
   318     if ( error )
       
   319       goto Exit;
       
   320 
       
   321     /* restore the left side bearing and   */
       
   322     /* advance width of the base character */
       
   323 
       
   324     decoder->builder.left_bearing = left_bearing;
       
   325     decoder->builder.advance      = advance;
       
   326 
       
   327     decoder->builder.pos_x = 0;
       
   328     decoder->builder.pos_y = 0;
       
   329 
       
   330   Exit:
       
   331     return error;
       
   332   }
       
   333 
       
   334 
       
   335   /*************************************************************************/
       
   336   /*                                                                       */
       
   337   /* <Function>                                                            */
       
   338   /*    t1_decoder_parse_charstrings                                       */
       
   339   /*                                                                       */
       
   340   /* <Description>                                                         */
       
   341   /*    Parses a given Type 1 charstrings program.                         */
       
   342   /*                                                                       */
       
   343   /* <Input>                                                               */
       
   344   /*    decoder         :: The current Type 1 decoder.                     */
       
   345   /*                                                                       */
       
   346   /*    charstring_base :: The base address of the charstring stream.      */
       
   347   /*                                                                       */
       
   348   /*    charstring_len  :: The length in bytes of the charstring stream.   */
       
   349   /*                                                                       */
       
   350   /* <Return>                                                              */
       
   351   /*    FreeType error code.  0 means success.                             */
       
   352   /*                                                                       */
       
   353   FT_LOCAL_DEF( FT_Error )
       
   354   t1_decoder_parse_charstrings( T1_Decoder  decoder,
       
   355                                 FT_Byte*    charstring_base,
       
   356                                 FT_UInt     charstring_len )
       
   357   {
       
   358     FT_Error         error;
       
   359     T1_Decoder_Zone  zone;
       
   360     FT_Byte*         ip;
       
   361     FT_Byte*         limit;
       
   362     T1_Builder       builder = &decoder->builder;
       
   363     FT_Pos           x, y, orig_x, orig_y;
       
   364     FT_Int           known_othersubr_result_cnt   = 0;
       
   365     FT_Int           unknown_othersubr_result_cnt = 0;
       
   366     FT_Bool          large_int;
       
   367     FT_Fixed         seed;
       
   368 
       
   369     T1_Hints_Funcs   hinter;
       
   370 
       
   371 #ifdef FT_DEBUG_LEVEL_TRACE
       
   372     FT_Bool          bol = TRUE;
       
   373 #endif
       
   374 
       
   375 
       
   376     /* compute random seed from stack address of parameter */
       
   377     seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed              ^
       
   378                          (FT_PtrDist)(char*)&decoder           ^
       
   379                          (FT_PtrDist)(char*)&charstring_base ) &
       
   380                          FT_ULONG_MAX ) ;
       
   381     seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
       
   382     if ( seed == 0 )
       
   383       seed = 0x7384;
       
   384 
       
   385     /* First of all, initialize the decoder */
       
   386     decoder->top  = decoder->stack;
       
   387     decoder->zone = decoder->zones;
       
   388     zone          = decoder->zones;
       
   389 
       
   390     builder->parse_state = T1_Parse_Start;
       
   391 
       
   392     hinter = (T1_Hints_Funcs)builder->hints_funcs;
       
   393 
       
   394     /* a font that reads BuildCharArray without setting */
       
   395     /* its values first is buggy, but ...               */
       
   396     FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
       
   397                ( decoder->buildchar == NULL )  );
       
   398 
       
   399     if ( decoder->len_buildchar > 0 )
       
   400       ft_memset( &decoder->buildchar[0],
       
   401                  0,
       
   402                  sizeof( decoder->buildchar[0] ) * decoder->len_buildchar );
       
   403 
       
   404     FT_TRACE4(( "\n"
       
   405                 "Start charstring\n" ));
       
   406 
       
   407     zone->base           = charstring_base;
       
   408     limit = zone->limit  = charstring_base + charstring_len;
       
   409     ip    = zone->cursor = zone->base;
       
   410 
       
   411     error = PSaux_Err_Ok;
       
   412 
       
   413     x = orig_x = builder->pos_x;
       
   414     y = orig_y = builder->pos_y;
       
   415 
       
   416     /* begin hints recording session, if any */
       
   417     if ( hinter )
       
   418       hinter->open( hinter->hints );
       
   419 
       
   420     large_int = FALSE;
       
   421 
       
   422     /* now, execute loop */
       
   423     while ( ip < limit )
       
   424     {
       
   425       FT_Long*     top   = decoder->top;
       
   426       T1_Operator  op    = op_none;
       
   427       FT_Int32     value = 0;
       
   428 
       
   429 
       
   430       FT_ASSERT( known_othersubr_result_cnt == 0   ||
       
   431                  unknown_othersubr_result_cnt == 0 );
       
   432 
       
   433 #ifdef FT_DEBUG_LEVEL_TRACE
       
   434       if ( bol )
       
   435       {
       
   436         FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
       
   437         bol = FALSE;
       
   438       }
       
   439 #endif
       
   440 
       
   441       /*********************************************************************/
       
   442       /*                                                                   */
       
   443       /* Decode operator or operand                                        */
       
   444       /*                                                                   */
       
   445       /*                                                                   */
       
   446 
       
   447       /* first of all, decompress operator or value */
       
   448       switch ( *ip++ )
       
   449       {
       
   450       case 1:
       
   451         op = op_hstem;
       
   452         break;
       
   453 
       
   454       case 3:
       
   455         op = op_vstem;
       
   456         break;
       
   457       case 4:
       
   458         op = op_vmoveto;
       
   459         break;
       
   460       case 5:
       
   461         op = op_rlineto;
       
   462         break;
       
   463       case 6:
       
   464         op = op_hlineto;
       
   465         break;
       
   466       case 7:
       
   467         op = op_vlineto;
       
   468         break;
       
   469       case 8:
       
   470         op = op_rrcurveto;
       
   471         break;
       
   472       case 9:
       
   473         op = op_closepath;
       
   474         break;
       
   475       case 10:
       
   476         op = op_callsubr;
       
   477         break;
       
   478       case 11:
       
   479         op = op_return;
       
   480         break;
       
   481 
       
   482       case 13:
       
   483         op = op_hsbw;
       
   484         break;
       
   485       case 14:
       
   486         op = op_endchar;
       
   487         break;
       
   488 
       
   489       case 15:          /* undocumented, obsolete operator */
       
   490         op = op_unknown15;
       
   491         break;
       
   492 
       
   493       case 21:
       
   494         op = op_rmoveto;
       
   495         break;
       
   496       case 22:
       
   497         op = op_hmoveto;
       
   498         break;
       
   499 
       
   500       case 30:
       
   501         op = op_vhcurveto;
       
   502         break;
       
   503       case 31:
       
   504         op = op_hvcurveto;
       
   505         break;
       
   506 
       
   507       case 12:
       
   508         if ( ip > limit )
       
   509         {
       
   510           FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   511                      " invalid escape (12+EOF)\n" ));
       
   512           goto Syntax_Error;
       
   513         }
       
   514 
       
   515         switch ( *ip++ )
       
   516         {
       
   517         case 0:
       
   518           op = op_dotsection;
       
   519           break;
       
   520         case 1:
       
   521           op = op_vstem3;
       
   522           break;
       
   523         case 2:
       
   524           op = op_hstem3;
       
   525           break;
       
   526         case 6:
       
   527           op = op_seac;
       
   528           break;
       
   529         case 7:
       
   530           op = op_sbw;
       
   531           break;
       
   532         case 12:
       
   533           op = op_div;
       
   534           break;
       
   535         case 16:
       
   536           op = op_callothersubr;
       
   537           break;
       
   538         case 17:
       
   539           op = op_pop;
       
   540           break;
       
   541         case 33:
       
   542           op = op_setcurrentpoint;
       
   543           break;
       
   544 
       
   545         default:
       
   546           FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   547                      " invalid escape (12+%d)\n",
       
   548                      ip[-1] ));
       
   549           goto Syntax_Error;
       
   550         }
       
   551         break;
       
   552 
       
   553       case 255:    /* four bytes integer */
       
   554         if ( ip + 4 > limit )
       
   555         {
       
   556           FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   557                      " unexpected EOF in integer\n" ));
       
   558           goto Syntax_Error;
       
   559         }
       
   560 
       
   561         value = (FT_Int32)( ( (FT_Long)ip[0] << 24 ) |
       
   562                             ( (FT_Long)ip[1] << 16 ) |
       
   563                             ( (FT_Long)ip[2] << 8  ) |
       
   564                                        ip[3]         );
       
   565         ip += 4;
       
   566 
       
   567         /* According to the specification, values > 32000 or < -32000 must */
       
   568         /* be followed by a `div' operator to make the result be in the    */
       
   569         /* range [-32000;32000].  We expect that the second argument of    */
       
   570         /* `div' is not a large number.  Additionally, we don't handle     */
       
   571         /* stuff like `<large1> <large2> <num> div <num> div' or           */
       
   572         /* <large1> <large2> <num> div div'.  This is probably not allowed */
       
   573         /* anyway.                                                         */
       
   574         if ( value > 32000 || value < -32000 )
       
   575         {
       
   576           if ( large_int )
       
   577           {
       
   578             FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   579                        " no `div' after large integer\n" ));
       
   580           }
       
   581           else
       
   582             large_int = TRUE;
       
   583         }
       
   584         else
       
   585         {
       
   586           if ( !large_int )
       
   587             value <<= 16;
       
   588         }
       
   589 
       
   590         break;
       
   591 
       
   592       default:
       
   593         if ( ip[-1] >= 32 )
       
   594         {
       
   595           if ( ip[-1] < 247 )
       
   596             value = (FT_Int32)ip[-1] - 139;
       
   597           else
       
   598           {
       
   599             if ( ++ip > limit )
       
   600             {
       
   601               FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   602                          " unexpected EOF in integer\n" ));
       
   603               goto Syntax_Error;
       
   604             }
       
   605 
       
   606             if ( ip[-2] < 251 )
       
   607               value =  ( ( (FT_Int32)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
       
   608             else
       
   609               value = -( ( ( (FT_Int32)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
       
   610           }
       
   611 
       
   612           if ( !large_int )
       
   613             value <<= 16;
       
   614         }
       
   615         else
       
   616         {
       
   617           FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   618                      " invalid byte (%d)\n", ip[-1] ));
       
   619           goto Syntax_Error;
       
   620         }
       
   621       }
       
   622 
       
   623       if ( unknown_othersubr_result_cnt > 0 )
       
   624       {
       
   625         switch ( op )
       
   626         {
       
   627         case op_callsubr:
       
   628         case op_return:
       
   629         case op_none:
       
   630         case op_pop:
       
   631           break;
       
   632 
       
   633         default:
       
   634           /* all operands have been transferred by previous pops */
       
   635           unknown_othersubr_result_cnt = 0;
       
   636           break;
       
   637         }
       
   638       }
       
   639 
       
   640       if ( large_int && !( op == op_none || op == op_div ) )
       
   641       {
       
   642         FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   643                    " no `div' after large integer\n" ));
       
   644 
       
   645         large_int = FALSE;
       
   646       }
       
   647 
       
   648       /*********************************************************************/
       
   649       /*                                                                   */
       
   650       /*  Push value on stack, or process operator                         */
       
   651       /*                                                                   */
       
   652       /*                                                                   */
       
   653       if ( op == op_none )
       
   654       {
       
   655         if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
       
   656         {
       
   657           FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" ));
       
   658           goto Syntax_Error;
       
   659         }
       
   660 
       
   661 #ifdef FT_DEBUG_LEVEL_TRACE
       
   662         if ( large_int )
       
   663           FT_TRACE4(( " %ld", value ));
       
   664         else
       
   665           FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) ));
       
   666 #endif
       
   667 
       
   668         *top++       = value;
       
   669         decoder->top = top;
       
   670       }
       
   671       else if ( op == op_callothersubr )  /* callothersubr */
       
   672       {
       
   673         FT_Int  subr_no;
       
   674         FT_Int  arg_cnt;
       
   675 
       
   676 
       
   677 #ifdef FT_DEBUG_LEVEL_TRACE
       
   678         FT_TRACE4(( " callothersubr\n" ));
       
   679         bol = TRUE;
       
   680 #endif
       
   681 
       
   682         if ( top - decoder->stack < 2 )
       
   683           goto Stack_Underflow;
       
   684 
       
   685         top -= 2;
       
   686 
       
   687         subr_no = (FT_Int)( top[1] >> 16 );
       
   688         arg_cnt = (FT_Int)( top[0] >> 16 );
       
   689 
       
   690         /***********************************************************/
       
   691         /*                                                         */
       
   692         /* remove all operands to callothersubr from the stack     */
       
   693         /*                                                         */
       
   694         /* for handled othersubrs, where we know the number of     */
       
   695         /* arguments, we increase the stack by the value of        */
       
   696         /* known_othersubr_result_cnt                              */
       
   697         /*                                                         */
       
   698         /* for unhandled othersubrs the following pops adjust the  */
       
   699         /* stack pointer as necessary                              */
       
   700 
       
   701         if ( arg_cnt > top - decoder->stack )
       
   702           goto Stack_Underflow;
       
   703 
       
   704         top -= arg_cnt;
       
   705 
       
   706         known_othersubr_result_cnt   = 0;
       
   707         unknown_othersubr_result_cnt = 0;
       
   708 
       
   709         /* XXX TODO: The checks to `arg_count == <whatever>'       */
       
   710         /* might not be correct; an othersubr expects a certain    */
       
   711         /* number of operands on the PostScript stack (as opposed  */
       
   712         /* to the T1 stack) but it doesn't have to put them there  */
       
   713         /* by itself; previous othersubrs might have left the      */
       
   714         /* operands there if they were not followed by an          */
       
   715         /* appropriate number of pops                              */
       
   716         /*                                                         */
       
   717         /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
       
   718         /* accept a font that contains charstrings like            */
       
   719         /*                                                         */
       
   720         /*     100 200 2 20 callothersubr                          */
       
   721         /*     300 1 20 callothersubr pop                          */
       
   722         /*                                                         */
       
   723         /* Perhaps this is the reason why BuildCharArray exists.   */
       
   724 
       
   725         switch ( subr_no )
       
   726         {
       
   727         case 1:                     /* start flex feature */
       
   728           if ( arg_cnt != 0 )
       
   729             goto Unexpected_OtherSubr;
       
   730 
       
   731           decoder->flex_state        = 1;
       
   732           decoder->num_flex_vectors  = 0;
       
   733           if ( ( error = t1_builder_start_point( builder, x, y ) )
       
   734                  != PSaux_Err_Ok                                   ||
       
   735                ( error = t1_builder_check_points( builder, 6 ) )
       
   736                  != PSaux_Err_Ok                                   )
       
   737             goto Fail;
       
   738           break;
       
   739 
       
   740         case 2:                     /* add flex vectors */
       
   741           {
       
   742             FT_Int  idx;
       
   743 
       
   744 
       
   745             if ( arg_cnt != 0 )
       
   746               goto Unexpected_OtherSubr;
       
   747 
       
   748             /* note that we should not add a point for index 0; */
       
   749             /* this will move our current position to the flex  */
       
   750             /* point without adding any point to the outline    */
       
   751             idx = decoder->num_flex_vectors++;
       
   752             if ( idx > 0 && idx < 7 )
       
   753               t1_builder_add_point( builder,
       
   754                                     x,
       
   755                                     y,
       
   756                                     (FT_Byte)( idx == 3 || idx == 6 ) );
       
   757           }
       
   758           break;
       
   759 
       
   760         case 0:                     /* end flex feature */
       
   761           if ( arg_cnt != 3 )
       
   762             goto Unexpected_OtherSubr;
       
   763 
       
   764           if ( decoder->flex_state       == 0 ||
       
   765                decoder->num_flex_vectors != 7 )
       
   766           {
       
   767             FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   768                        " unexpected flex end\n" ));
       
   769             goto Syntax_Error;
       
   770           }
       
   771 
       
   772           /* the two `results' are popped by the following setcurrentpoint */
       
   773           top[0] = x;
       
   774           top[1] = y;
       
   775           known_othersubr_result_cnt = 2;
       
   776           break;
       
   777 
       
   778         case 3:                     /* change hints */
       
   779           if ( arg_cnt != 1 )
       
   780             goto Unexpected_OtherSubr;
       
   781 
       
   782           known_othersubr_result_cnt = 1;
       
   783 
       
   784           if ( hinter )
       
   785             hinter->reset( hinter->hints, builder->current->n_points );
       
   786           break;
       
   787 
       
   788         case 12:
       
   789         case 13:
       
   790           /* counter control hints, clear stack */
       
   791           top = decoder->stack;
       
   792           break;
       
   793 
       
   794         case 14:
       
   795         case 15:
       
   796         case 16:
       
   797         case 17:
       
   798         case 18:                    /* multiple masters */
       
   799           {
       
   800             PS_Blend  blend = decoder->blend;
       
   801             FT_UInt   num_points, nn, mm;
       
   802             FT_Long*  delta;
       
   803             FT_Long*  values;
       
   804 
       
   805 
       
   806             if ( !blend )
       
   807             {
       
   808               FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   809                          " unexpected multiple masters operator\n" ));
       
   810               goto Syntax_Error;
       
   811             }
       
   812 
       
   813             num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );
       
   814             if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )
       
   815             {
       
   816               FT_ERROR(( "t1_decoder_parse_charstrings:"
       
   817                          " incorrect number of multiple masters arguments\n" ));
       
   818               goto Syntax_Error;
       
   819             }
       
   820 
       
   821             /* we want to compute:                                   */
       
   822             /*                                                       */
       
   823             /*  a0*w0 + a1*w1 + ... + ak*wk                          */
       
   824             /*                                                       */
       
   825             /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
       
   826             /* however, given that w0 + w1 + ... + wk == 1, we can   */
       
   827             /* rewrite it easily as:                                 */
       
   828             /*                                                       */
       
   829             /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
       
   830             /*                                                       */
       
   831             /* where k == num_designs-1                              */
       
   832             /*                                                       */
       
   833             /* I guess that's why it's written in this `compact'     */
       
   834             /* form.                                                 */
       
   835             /*                                                       */
       
   836             delta  = top + num_points;
       
   837             values = top;
       
   838             for ( nn = 0; nn < num_points; nn++ )
       
   839             {
       
   840               FT_Long  tmp = values[0];
       
   841 
       
   842 
       
   843               for ( mm = 1; mm < blend->num_designs; mm++ )
       
   844                 tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
       
   845 
       
   846               *values++ = tmp;
       
   847             }
       
   848 
       
   849             known_othersubr_result_cnt = num_points;
       
   850             break;
       
   851           }
       
   852 
       
   853         case 19:
       
   854           /* <idx> 1 19 callothersubr                             */
       
   855           /* => replace elements starting from index cvi( <idx> ) */
       
   856           /*    of BuildCharArray with WeightVector               */
       
   857           {
       
   858             FT_Int    idx;
       
   859             PS_Blend  blend = decoder->blend;
       
   860 
       
   861 
       
   862             if ( arg_cnt != 1 || blend == NULL )
       
   863               goto Unexpected_OtherSubr;
       
   864 
       
   865             idx = (FT_Int)( top[0] >> 16 );
       
   866 
       
   867             if ( idx < 0                                           ||
       
   868                  idx + blend->num_designs > decoder->len_buildchar )
       
   869               goto Unexpected_OtherSubr;
       
   870 
       
   871             ft_memcpy( &decoder->buildchar[idx],
       
   872                        blend->weight_vector,
       
   873                        blend->num_designs *
       
   874                          sizeof( blend->weight_vector[0] ) );
       
   875           }
       
   876           break;
       
   877 
       
   878         case 20:
       
   879           /* <arg1> <arg2> 2 20 callothersubr pop   */
       
   880           /* ==> push <arg1> + <arg2> onto T1 stack */
       
   881           if ( arg_cnt != 2 )
       
   882             goto Unexpected_OtherSubr;
       
   883 
       
   884           top[0] += top[1]; /* XXX (over|under)flow */
       
   885 
       
   886           known_othersubr_result_cnt = 1;
       
   887           break;
       
   888 
       
   889         case 21:
       
   890           /* <arg1> <arg2> 2 21 callothersubr pop   */
       
   891           /* ==> push <arg1> - <arg2> onto T1 stack */
       
   892           if ( arg_cnt != 2 )
       
   893             goto Unexpected_OtherSubr;
       
   894 
       
   895           top[0] -= top[1]; /* XXX (over|under)flow */
       
   896 
       
   897           known_othersubr_result_cnt = 1;
       
   898           break;
       
   899 
       
   900         case 22:
       
   901           /* <arg1> <arg2> 2 22 callothersubr pop   */
       
   902           /* ==> push <arg1> * <arg2> onto T1 stack */
       
   903           if ( arg_cnt != 2 )
       
   904             goto Unexpected_OtherSubr;
       
   905 
       
   906           top[0] = FT_MulFix( top[0], top[1] );
       
   907 
       
   908           known_othersubr_result_cnt = 1;
       
   909           break;
       
   910 
       
   911         case 23:
       
   912           /* <arg1> <arg2> 2 23 callothersubr pop   */
       
   913           /* ==> push <arg1> / <arg2> onto T1 stack */
       
   914           if ( arg_cnt != 2 || top[1] == 0 )
       
   915             goto Unexpected_OtherSubr;
       
   916 
       
   917           top[0] = FT_DivFix( top[0], top[1] );
       
   918 
       
   919           known_othersubr_result_cnt = 1;
       
   920           break;
       
   921 
       
   922         case 24:
       
   923           /* <val> <idx> 2 24 callothersubr               */
       
   924           /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
       
   925           {
       
   926             FT_Int    idx;
       
   927             PS_Blend  blend = decoder->blend;
       
   928 
       
   929 
       
   930             if ( arg_cnt != 2 || blend == NULL )
       
   931               goto Unexpected_OtherSubr;
       
   932 
       
   933             idx = (FT_Int)( top[1] >> 16 );
       
   934 
       
   935             if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
       
   936               goto Unexpected_OtherSubr;
       
   937 
       
   938             decoder->buildchar[idx] = top[0];
       
   939           }
       
   940           break;
       
   941 
       
   942         case 25:
       
   943           /* <idx> 1 25 callothersubr pop        */
       
   944           /* ==> push BuildCharArray[cvi( idx )] */
       
   945           /*     onto T1 stack                   */
       
   946           {
       
   947             FT_Int    idx;
       
   948             PS_Blend  blend = decoder->blend;
       
   949 
       
   950 
       
   951             if ( arg_cnt != 1 || blend == NULL )
       
   952               goto Unexpected_OtherSubr;
       
   953 
       
   954             idx = (FT_Int)( top[0] >> 16 );
       
   955 
       
   956             if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
       
   957               goto Unexpected_OtherSubr;
       
   958 
       
   959             top[0] = decoder->buildchar[idx];
       
   960           }
       
   961 
       
   962           known_othersubr_result_cnt = 1;
       
   963           break;
       
   964 
       
   965 #if 0
       
   966         case 26:
       
   967           /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
       
   968           /*                      leave mark on T1 stack                    */
       
   969           /* <val> <idx>      ==> set BuildCharArray[cvi( <idx> )] = <val>  */
       
   970           XXX which routine has left its mark on the (PostScript) stack?;
       
   971           break;
       
   972 #endif
       
   973 
       
   974         case 27:
       
   975           /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
       
   976           /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
       
   977           /*     otherwise push <res2>                          */
       
   978           if ( arg_cnt != 4 )
       
   979             goto Unexpected_OtherSubr;
       
   980 
       
   981           if ( top[2] > top[3] )
       
   982             top[0] = top[1];
       
   983 
       
   984           known_othersubr_result_cnt = 1;
       
   985           break;
       
   986 
       
   987         case 28:
       
   988           /* 0 28 callothersubr pop                               */
       
   989           /* => push random value from interval [0, 1) onto stack */
       
   990           if ( arg_cnt != 0 )
       
   991             goto Unexpected_OtherSubr;
       
   992 
       
   993           {
       
   994             FT_Fixed  Rand;
       
   995 
       
   996 
       
   997             Rand = seed;
       
   998             if ( Rand >= 0x8000L )
       
   999               Rand++;
       
  1000 
       
  1001             top[0] = Rand;
       
  1002 
       
  1003             seed = FT_MulFix( seed, 0x10000L - seed );
       
  1004             if ( seed == 0 )
       
  1005               seed += 0x2873;
       
  1006           }
       
  1007 
       
  1008           known_othersubr_result_cnt = 1;
       
  1009           break;
       
  1010 
       
  1011         default:
       
  1012           FT_ERROR(( "t1_decoder_parse_charstrings:"
       
  1013                      " unknown othersubr [%d %d], wish me luck\n",
       
  1014                      arg_cnt, subr_no ));
       
  1015           unknown_othersubr_result_cnt = arg_cnt;
       
  1016           break;
       
  1017 
       
  1018         Unexpected_OtherSubr:
       
  1019           FT_ERROR(( "t1_decoder_parse_charstrings:"
       
  1020                      " invalid othersubr [%d %d]\n", arg_cnt, subr_no ));
       
  1021           goto Syntax_Error;
       
  1022         }
       
  1023 
       
  1024         top += known_othersubr_result_cnt;
       
  1025 
       
  1026         decoder->top = top;
       
  1027       }
       
  1028       else  /* general operator */
       
  1029       {
       
  1030         FT_Int  num_args = t1_args_count[op];
       
  1031 
       
  1032 
       
  1033         FT_ASSERT( num_args >= 0 );
       
  1034 
       
  1035         if ( top - decoder->stack < num_args )
       
  1036           goto Stack_Underflow;
       
  1037 
       
  1038         /* XXX Operators usually take their operands from the        */
       
  1039         /*     bottom of the stack, i.e., the operands are           */
       
  1040         /*     decoder->stack[0], ..., decoder->stack[num_args - 1]; */
       
  1041         /*     only div, callsubr, and callothersubr are different.  */
       
  1042         /*     In practice it doesn't matter (?).                    */
       
  1043 
       
  1044 #ifdef FT_DEBUG_LEVEL_TRACE
       
  1045 
       
  1046         switch ( op )
       
  1047         {
       
  1048         case op_callsubr:
       
  1049         case op_div:
       
  1050         case op_callothersubr:
       
  1051         case op_pop:
       
  1052         case op_return:
       
  1053           break;
       
  1054 
       
  1055         default:
       
  1056           if ( top - decoder->stack != num_args )
       
  1057             FT_TRACE0(( "t1_decoder_parse_charstrings:"
       
  1058                         " too much operands on the stack"
       
  1059                         " (seen %d, expected %d)\n",
       
  1060                         top - decoder->stack, num_args ));
       
  1061             break;
       
  1062         }
       
  1063 
       
  1064 #endif /* FT_DEBUG_LEVEL_TRACE */
       
  1065 
       
  1066         top -= num_args;
       
  1067 
       
  1068         switch ( op )
       
  1069         {
       
  1070         case op_endchar:
       
  1071           FT_TRACE4(( " endchar\n" ));
       
  1072 
       
  1073           t1_builder_close_contour( builder );
       
  1074 
       
  1075           /* close hints recording session */
       
  1076           if ( hinter )
       
  1077           {
       
  1078             if ( hinter->close( hinter->hints, builder->current->n_points ) )
       
  1079               goto Syntax_Error;
       
  1080 
       
  1081             /* apply hints to the loaded glyph outline now */
       
  1082             hinter->apply( hinter->hints,
       
  1083                            builder->current,
       
  1084                            (PSH_Globals)builder->hints_globals,
       
  1085                            decoder->hint_mode );
       
  1086           }
       
  1087 
       
  1088           /* add current outline to the glyph slot */
       
  1089           FT_GlyphLoader_Add( builder->loader );
       
  1090 
       
  1091           /* the compiler should optimize away this empty loop but ... */
       
  1092 
       
  1093 #ifdef FT_DEBUG_LEVEL_TRACE
       
  1094 
       
  1095           if ( decoder->len_buildchar > 0 )
       
  1096           {
       
  1097             FT_UInt  i;
       
  1098 
       
  1099 
       
  1100             FT_TRACE4(( "BuildCharArray = [ " ));
       
  1101 
       
  1102             for ( i = 0; i < decoder->len_buildchar; ++i )
       
  1103               FT_TRACE4(( "%d ", decoder->buildchar[ i ] ));
       
  1104 
       
  1105             FT_TRACE4(( "]\n" ));
       
  1106           }
       
  1107 
       
  1108 #endif /* FT_DEBUG_LEVEL_TRACE */
       
  1109 
       
  1110           FT_TRACE4(( "\n" ));
       
  1111 
       
  1112           /* return now! */
       
  1113           return PSaux_Err_Ok;
       
  1114 
       
  1115         case op_hsbw:
       
  1116           FT_TRACE4(( " hsbw" ));
       
  1117 
       
  1118           builder->parse_state = T1_Parse_Have_Width;
       
  1119 
       
  1120           builder->left_bearing.x += top[0];
       
  1121           builder->advance.x       = top[1];
       
  1122           builder->advance.y       = 0;
       
  1123 
       
  1124           orig_x = x = builder->pos_x + top[0];
       
  1125           orig_y = y = builder->pos_y;
       
  1126 
       
  1127           FT_UNUSED( orig_y );
       
  1128 
       
  1129           /* the `metrics_only' indicates that we only want to compute */
       
  1130           /* the glyph's metrics (lsb + advance width), not load the   */
       
  1131           /* rest of it; so exit immediately                           */
       
  1132           if ( builder->metrics_only )
       
  1133             return PSaux_Err_Ok;
       
  1134 
       
  1135           break;
       
  1136 
       
  1137         case op_seac:
       
  1138           return t1operator_seac( decoder,
       
  1139                                   top[0],
       
  1140                                   top[1],
       
  1141                                   top[2],
       
  1142                                   (FT_Int)( top[3] >> 16 ),
       
  1143                                   (FT_Int)( top[4] >> 16 ) );
       
  1144 
       
  1145         case op_sbw:
       
  1146           FT_TRACE4(( " sbw" ));
       
  1147 
       
  1148           builder->parse_state = T1_Parse_Have_Width;
       
  1149 
       
  1150           builder->left_bearing.x += top[0];
       
  1151           builder->left_bearing.y += top[1];
       
  1152           builder->advance.x       = top[2];
       
  1153           builder->advance.y       = top[3];
       
  1154 
       
  1155           x = builder->pos_x + top[0];
       
  1156           y = builder->pos_y + top[1];
       
  1157 
       
  1158           /* the `metrics_only' indicates that we only want to compute */
       
  1159           /* the glyph's metrics (lsb + advance width), not load the   */
       
  1160           /* rest of it; so exit immediately                           */
       
  1161           if ( builder->metrics_only )
       
  1162             return PSaux_Err_Ok;
       
  1163 
       
  1164           break;
       
  1165 
       
  1166         case op_closepath:
       
  1167           FT_TRACE4(( " closepath" ));
       
  1168 
       
  1169           /* if there is no path, `closepath' is a no-op */
       
  1170           if ( builder->parse_state == T1_Parse_Have_Path   ||
       
  1171                builder->parse_state == T1_Parse_Have_Moveto )
       
  1172             t1_builder_close_contour( builder );
       
  1173 
       
  1174           builder->parse_state = T1_Parse_Have_Width;
       
  1175           break;
       
  1176 
       
  1177         case op_hlineto:
       
  1178           FT_TRACE4(( " hlineto" ));
       
  1179 
       
  1180           if ( ( error = t1_builder_start_point( builder, x, y ) )
       
  1181                  != PSaux_Err_Ok )
       
  1182             goto Fail;
       
  1183 
       
  1184           x += top[0];
       
  1185           goto Add_Line;
       
  1186 
       
  1187         case op_hmoveto:
       
  1188           FT_TRACE4(( " hmoveto" ));
       
  1189 
       
  1190           x += top[0];
       
  1191           if ( !decoder->flex_state )
       
  1192           {
       
  1193             if ( builder->parse_state == T1_Parse_Start )
       
  1194               goto Syntax_Error;
       
  1195             builder->parse_state = T1_Parse_Have_Moveto;
       
  1196           }
       
  1197           break;
       
  1198 
       
  1199         case op_hvcurveto:
       
  1200           FT_TRACE4(( " hvcurveto" ));
       
  1201 
       
  1202           if ( ( error = t1_builder_start_point( builder, x, y ) )
       
  1203                  != PSaux_Err_Ok                                   ||
       
  1204                ( error = t1_builder_check_points( builder, 3 ) )
       
  1205                  != PSaux_Err_Ok                                   )
       
  1206             goto Fail;
       
  1207 
       
  1208           x += top[0];
       
  1209           t1_builder_add_point( builder, x, y, 0 );
       
  1210           x += top[1];
       
  1211           y += top[2];
       
  1212           t1_builder_add_point( builder, x, y, 0 );
       
  1213           y += top[3];
       
  1214           t1_builder_add_point( builder, x, y, 1 );
       
  1215           break;
       
  1216 
       
  1217         case op_rlineto:
       
  1218           FT_TRACE4(( " rlineto" ));
       
  1219 
       
  1220           if ( ( error = t1_builder_start_point( builder, x, y ) )
       
  1221                  != PSaux_Err_Ok )
       
  1222             goto Fail;
       
  1223 
       
  1224           x += top[0];
       
  1225           y += top[1];
       
  1226 
       
  1227         Add_Line:
       
  1228           if ( ( error = t1_builder_add_point1( builder, x, y ) )
       
  1229                  != PSaux_Err_Ok )
       
  1230             goto Fail;
       
  1231           break;
       
  1232 
       
  1233         case op_rmoveto:
       
  1234           FT_TRACE4(( " rmoveto" ));
       
  1235 
       
  1236           x += top[0];
       
  1237           y += top[1];
       
  1238           if ( !decoder->flex_state )
       
  1239           {
       
  1240             if ( builder->parse_state == T1_Parse_Start )
       
  1241               goto Syntax_Error;
       
  1242             builder->parse_state = T1_Parse_Have_Moveto;
       
  1243           }
       
  1244           break;
       
  1245 
       
  1246         case op_rrcurveto:
       
  1247           FT_TRACE4(( " rrcurveto" ));
       
  1248 
       
  1249           if ( ( error = t1_builder_start_point( builder, x, y ) )
       
  1250                  != PSaux_Err_Ok                                   ||
       
  1251                ( error = t1_builder_check_points( builder, 3 ) )
       
  1252                  != PSaux_Err_Ok                                   )
       
  1253             goto Fail;
       
  1254 
       
  1255           x += top[0];
       
  1256           y += top[1];
       
  1257           t1_builder_add_point( builder, x, y, 0 );
       
  1258 
       
  1259           x += top[2];
       
  1260           y += top[3];
       
  1261           t1_builder_add_point( builder, x, y, 0 );
       
  1262 
       
  1263           x += top[4];
       
  1264           y += top[5];
       
  1265           t1_builder_add_point( builder, x, y, 1 );
       
  1266           break;
       
  1267 
       
  1268         case op_vhcurveto:
       
  1269           FT_TRACE4(( " vhcurveto" ));
       
  1270 
       
  1271           if ( ( error = t1_builder_start_point( builder, x, y ) )
       
  1272                  != PSaux_Err_Ok                                   ||
       
  1273                ( error = t1_builder_check_points( builder, 3 ) )
       
  1274                  != PSaux_Err_Ok                                   )
       
  1275             goto Fail;
       
  1276 
       
  1277           y += top[0];
       
  1278           t1_builder_add_point( builder, x, y, 0 );
       
  1279           x += top[1];
       
  1280           y += top[2];
       
  1281           t1_builder_add_point( builder, x, y, 0 );
       
  1282           x += top[3];
       
  1283           t1_builder_add_point( builder, x, y, 1 );
       
  1284           break;
       
  1285 
       
  1286         case op_vlineto:
       
  1287           FT_TRACE4(( " vlineto" ));
       
  1288 
       
  1289           if ( ( error = t1_builder_start_point( builder, x, y ) )
       
  1290                  != PSaux_Err_Ok )
       
  1291             goto Fail;
       
  1292 
       
  1293           y += top[0];
       
  1294           goto Add_Line;
       
  1295 
       
  1296         case op_vmoveto:
       
  1297           FT_TRACE4(( " vmoveto" ));
       
  1298 
       
  1299           y += top[0];
       
  1300           if ( !decoder->flex_state )
       
  1301           {
       
  1302             if ( builder->parse_state == T1_Parse_Start )
       
  1303               goto Syntax_Error;
       
  1304             builder->parse_state = T1_Parse_Have_Moveto;
       
  1305           }
       
  1306           break;
       
  1307 
       
  1308         case op_div:
       
  1309           FT_TRACE4(( " div" ));
       
  1310 
       
  1311           /* if `large_int' is set, we divide unscaled numbers; */
       
  1312           /* otherwise, we divide numbers in 16.16 format --    */
       
  1313           /* in both cases, it is the same operation            */
       
  1314           *top = FT_DivFix( top[0], top[1] );
       
  1315           ++top;
       
  1316 
       
  1317           large_int = FALSE;
       
  1318           break;
       
  1319 
       
  1320         case op_callsubr:
       
  1321           {
       
  1322             FT_Int  idx;
       
  1323 
       
  1324 
       
  1325             FT_TRACE4(( " callsubr" ));
       
  1326 
       
  1327             idx = (FT_Int)( top[0] >> 16 );
       
  1328             if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
       
  1329             {
       
  1330               FT_ERROR(( "t1_decoder_parse_charstrings:"
       
  1331                          " invalid subrs index\n" ));
       
  1332               goto Syntax_Error;
       
  1333             }
       
  1334 
       
  1335             if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
       
  1336             {
       
  1337               FT_ERROR(( "t1_decoder_parse_charstrings:"
       
  1338                          " too many nested subrs\n" ));
       
  1339               goto Syntax_Error;
       
  1340             }
       
  1341 
       
  1342             zone->cursor = ip;  /* save current instruction pointer */
       
  1343 
       
  1344             zone++;
       
  1345 
       
  1346             /* The Type 1 driver stores subroutines without the seed bytes. */
       
  1347             /* The CID driver stores subroutines with seed bytes.  This     */
       
  1348             /* case is taken care of when decoder->subrs_len == 0.          */
       
  1349             zone->base = decoder->subrs[idx];
       
  1350 
       
  1351             if ( decoder->subrs_len )
       
  1352               zone->limit = zone->base + decoder->subrs_len[idx];
       
  1353             else
       
  1354             {
       
  1355               /* We are using subroutines from a CID font.  We must adjust */
       
  1356               /* for the seed bytes.                                       */
       
  1357               zone->base  += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
       
  1358               zone->limit  = decoder->subrs[idx + 1];
       
  1359             }
       
  1360 
       
  1361             zone->cursor = zone->base;
       
  1362 
       
  1363             if ( !zone->base )
       
  1364             {
       
  1365               FT_ERROR(( "t1_decoder_parse_charstrings:"
       
  1366                          " invoking empty subrs\n" ));
       
  1367               goto Syntax_Error;
       
  1368             }
       
  1369 
       
  1370             decoder->zone = zone;
       
  1371             ip            = zone->base;
       
  1372             limit         = zone->limit;
       
  1373             break;
       
  1374           }
       
  1375 
       
  1376         case op_pop:
       
  1377           FT_TRACE4(( " pop" ));
       
  1378 
       
  1379           if ( known_othersubr_result_cnt > 0 )
       
  1380           {
       
  1381             known_othersubr_result_cnt--;
       
  1382             /* ignore, we pushed the operands ourselves */
       
  1383             break;
       
  1384           }
       
  1385 
       
  1386           if ( unknown_othersubr_result_cnt == 0 )
       
  1387           {
       
  1388             FT_ERROR(( "t1_decoder_parse_charstrings:"
       
  1389                        " no more operands for othersubr\n" ));
       
  1390             goto Syntax_Error;
       
  1391           }
       
  1392 
       
  1393           unknown_othersubr_result_cnt--;
       
  1394           top++;   /* `push' the operand to callothersubr onto the stack */
       
  1395           break;
       
  1396 
       
  1397         case op_return:
       
  1398           FT_TRACE4(( " return" ));
       
  1399 
       
  1400           if ( zone <= decoder->zones )
       
  1401           {
       
  1402             FT_ERROR(( "t1_decoder_parse_charstrings:"
       
  1403                        " unexpected return\n" ));
       
  1404             goto Syntax_Error;
       
  1405           }
       
  1406 
       
  1407           zone--;
       
  1408           ip            = zone->cursor;
       
  1409           limit         = zone->limit;
       
  1410           decoder->zone = zone;
       
  1411           break;
       
  1412 
       
  1413         case op_dotsection:
       
  1414           FT_TRACE4(( " dotsection" ));
       
  1415 
       
  1416           break;
       
  1417 
       
  1418         case op_hstem:
       
  1419           FT_TRACE4(( " hstem" ));
       
  1420 
       
  1421           /* record horizontal hint */
       
  1422           if ( hinter )
       
  1423           {
       
  1424             /* top[0] += builder->left_bearing.y; */
       
  1425             hinter->stem( hinter->hints, 1, top );
       
  1426           }
       
  1427           break;
       
  1428 
       
  1429         case op_hstem3:
       
  1430           FT_TRACE4(( " hstem3" ));
       
  1431 
       
  1432           /* record horizontal counter-controlled hints */
       
  1433           if ( hinter )
       
  1434             hinter->stem3( hinter->hints, 1, top );
       
  1435           break;
       
  1436 
       
  1437         case op_vstem:
       
  1438           FT_TRACE4(( " vstem" ));
       
  1439 
       
  1440           /* record vertical hint */
       
  1441           if ( hinter )
       
  1442           {
       
  1443             top[0] += orig_x;
       
  1444             hinter->stem( hinter->hints, 0, top );
       
  1445           }
       
  1446           break;
       
  1447 
       
  1448         case op_vstem3:
       
  1449           FT_TRACE4(( " vstem3" ));
       
  1450 
       
  1451           /* record vertical counter-controlled hints */
       
  1452           if ( hinter )
       
  1453           {
       
  1454             FT_Pos  dx = orig_x;
       
  1455 
       
  1456 
       
  1457             top[0] += dx;
       
  1458             top[2] += dx;
       
  1459             top[4] += dx;
       
  1460             hinter->stem3( hinter->hints, 0, top );
       
  1461           }
       
  1462           break;
       
  1463 
       
  1464         case op_setcurrentpoint:
       
  1465           FT_TRACE4(( " setcurrentpoint" ));
       
  1466 
       
  1467           /* From the T1 specification, section 6.4:                */
       
  1468           /*                                                        */
       
  1469           /*   The setcurrentpoint command is used only in          */
       
  1470           /*   conjunction with results from OtherSubrs procedures. */
       
  1471 
       
  1472           /* known_othersubr_result_cnt != 0 is already handled     */
       
  1473           /* above.                                                 */
       
  1474 
       
  1475           /* Note, however, that both Ghostscript and Adobe         */
       
  1476           /* Distiller handle this situation by silently ignoring   */
       
  1477           /* the inappropriate `setcurrentpoint' instruction.  So   */
       
  1478           /* we do the same.                                        */
       
  1479 #if 0
       
  1480 
       
  1481           if ( decoder->flex_state != 1 )
       
  1482           {
       
  1483             FT_ERROR(( "t1_decoder_parse_charstrings:"
       
  1484                        " unexpected `setcurrentpoint'\n" ));
       
  1485             goto Syntax_Error;
       
  1486           }
       
  1487           else
       
  1488             ...
       
  1489 #endif
       
  1490 
       
  1491           x = top[0];
       
  1492           y = top[1];
       
  1493           decoder->flex_state = 0;
       
  1494           break;
       
  1495 
       
  1496         case op_unknown15:
       
  1497           FT_TRACE4(( " opcode_15" ));
       
  1498           /* nothing to do except to pop the two arguments */
       
  1499           break;
       
  1500 
       
  1501         default:
       
  1502           FT_ERROR(( "t1_decoder_parse_charstrings:"
       
  1503                      " unhandled opcode %d\n", op ));
       
  1504           goto Syntax_Error;
       
  1505         }
       
  1506 
       
  1507         /* XXX Operators usually clear the operand stack;  */
       
  1508         /*     only div, callsubr, callothersubr, pop, and */
       
  1509         /*     return are different.                       */
       
  1510         /*     In practice it doesn't matter (?).          */
       
  1511 
       
  1512         decoder->top = top;
       
  1513 
       
  1514 #ifdef FT_DEBUG_LEVEL_TRACE
       
  1515         FT_TRACE4(( "\n" ));
       
  1516         bol = TRUE;
       
  1517 #endif
       
  1518 
       
  1519       } /* general operator processing */
       
  1520 
       
  1521     } /* while ip < limit */
       
  1522 
       
  1523     FT_TRACE4(( "..end..\n\n" ));
       
  1524 
       
  1525   Fail:
       
  1526     return error;
       
  1527 
       
  1528   Syntax_Error:
       
  1529     return PSaux_Err_Syntax_Error;
       
  1530 
       
  1531   Stack_Underflow:
       
  1532     return PSaux_Err_Stack_Underflow;
       
  1533   }
       
  1534 
       
  1535 
       
  1536   /* parse a single Type 1 glyph */
       
  1537   FT_LOCAL_DEF( FT_Error )
       
  1538   t1_decoder_parse_glyph( T1_Decoder  decoder,
       
  1539                           FT_UInt     glyph )
       
  1540   {
       
  1541     return decoder->parse_callback( decoder, glyph );
       
  1542   }
       
  1543 
       
  1544 
       
  1545   /* initialize T1 decoder */
       
  1546   FT_LOCAL_DEF( FT_Error )
       
  1547   t1_decoder_init( T1_Decoder           decoder,
       
  1548                    FT_Face              face,
       
  1549                    FT_Size              size,
       
  1550                    FT_GlyphSlot         slot,
       
  1551                    FT_Byte**            glyph_names,
       
  1552                    PS_Blend             blend,
       
  1553                    FT_Bool              hinting,
       
  1554                    FT_Render_Mode       hint_mode,
       
  1555                    T1_Decoder_Callback  parse_callback )
       
  1556   {
       
  1557     FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
       
  1558 
       
  1559     /* retrieve PSNames interface from list of current modules */
       
  1560     {
       
  1561       FT_Service_PsCMaps  psnames = 0;
       
  1562 
       
  1563 
       
  1564       FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
       
  1565       if ( !psnames )
       
  1566       {
       
  1567         FT_ERROR(( "t1_decoder_init:"
       
  1568                    " the `psnames' module is not available\n" ));
       
  1569         return PSaux_Err_Unimplemented_Feature;
       
  1570       }
       
  1571 
       
  1572       decoder->psnames = psnames;
       
  1573     }
       
  1574 
       
  1575     t1_builder_init( &decoder->builder, face, size, slot, hinting );
       
  1576 
       
  1577     /* decoder->buildchar and decoder->len_buildchar have to be  */
       
  1578     /* initialized by the caller since we cannot know the length */
       
  1579     /* of the BuildCharArray                                     */
       
  1580 
       
  1581     decoder->num_glyphs     = (FT_UInt)face->num_glyphs;
       
  1582     decoder->glyph_names    = glyph_names;
       
  1583     decoder->hint_mode      = hint_mode;
       
  1584     decoder->blend          = blend;
       
  1585     decoder->parse_callback = parse_callback;
       
  1586 
       
  1587     decoder->funcs          = t1_decoder_funcs;
       
  1588 
       
  1589     return PSaux_Err_Ok;
       
  1590   }
       
  1591 
       
  1592 
       
  1593   /* finalize T1 decoder */
       
  1594   FT_LOCAL_DEF( void )
       
  1595   t1_decoder_done( T1_Decoder  decoder )
       
  1596   {
       
  1597     t1_builder_done( &decoder->builder );
       
  1598   }
       
  1599 
       
  1600 
       
  1601 /* END */