PageRenderTime 1243ms CodeModel.GetById 181ms app.highlight 461ms RepoModel.GetById 585ms app.codeStats 1ms

/src/compiler/android-ndk/jni/freetype/src/psaux/t1decode.c

http://ftk.googlecode.com/
C | 1592 lines | 1028 code | 311 blank | 253 comment | 164 complexity | cf8a939fc4e86b6b1bdea4fdb0de396c MD5 | raw file
   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    /* we don't want to touch the source code -- use macro trick */
 377#define start_point    t1_builder_start_point
 378#define check_points   t1_builder_check_points
 379#define add_point      t1_builder_add_point
 380#define add_point1     t1_builder_add_point1
 381#define add_contour    t1_builder_add_contour
 382#define close_contour  t1_builder_close_contour
 383
 384
 385    /* compute random seed from stack address of parameter */
 386    seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed              ^
 387                         (FT_PtrDist)(char*)&decoder           ^
 388                         (FT_PtrDist)(char*)&charstring_base ) &
 389                         FT_ULONG_MAX ) ;
 390    seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
 391    if ( seed == 0 )
 392      seed = 0x7384;
 393
 394    /* First of all, initialize the decoder */
 395    decoder->top  = decoder->stack;
 396    decoder->zone = decoder->zones;
 397    zone          = decoder->zones;
 398
 399    builder->parse_state = T1_Parse_Start;
 400
 401    hinter = (T1_Hints_Funcs)builder->hints_funcs;
 402
 403    /* a font that reads BuildCharArray without setting */
 404    /* its values first is buggy, but ...               */
 405    FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
 406               ( decoder->buildchar == NULL )  );
 407
 408    if ( decoder->len_buildchar > 0 )
 409      ft_memset( &decoder->buildchar[0],
 410                 0,
 411                 sizeof( decoder->buildchar[0] ) * decoder->len_buildchar );
 412
 413    FT_TRACE4(( "\n"
 414                "Start charstring\n" ));
 415
 416    zone->base           = charstring_base;
 417    limit = zone->limit  = charstring_base + charstring_len;
 418    ip    = zone->cursor = zone->base;
 419
 420    error = PSaux_Err_Ok;
 421
 422    x = orig_x = builder->pos_x;
 423    y = orig_y = builder->pos_y;
 424
 425    /* begin hints recording session, if any */
 426    if ( hinter )
 427      hinter->open( hinter->hints );
 428
 429    large_int = FALSE;
 430
 431    /* now, execute loop */
 432    while ( ip < limit )
 433    {
 434      FT_Long*     top   = decoder->top;
 435      T1_Operator  op    = op_none;
 436      FT_Int32     value = 0;
 437
 438
 439      FT_ASSERT( known_othersubr_result_cnt == 0   ||
 440                 unknown_othersubr_result_cnt == 0 );
 441
 442#ifdef FT_DEBUG_LEVEL_TRACE
 443      if ( bol )
 444      {
 445        FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
 446        bol = FALSE;
 447      }
 448#endif
 449
 450      /*********************************************************************/
 451      /*                                                                   */
 452      /* Decode operator or operand                                        */
 453      /*                                                                   */
 454      /*                                                                   */
 455
 456      /* first of all, decompress operator or value */
 457      switch ( *ip++ )
 458      {
 459      case 1:
 460        op = op_hstem;
 461        break;
 462
 463      case 3:
 464        op = op_vstem;
 465        break;
 466      case 4:
 467        op = op_vmoveto;
 468        break;
 469      case 5:
 470        op = op_rlineto;
 471        break;
 472      case 6:
 473        op = op_hlineto;
 474        break;
 475      case 7:
 476        op = op_vlineto;
 477        break;
 478      case 8:
 479        op = op_rrcurveto;
 480        break;
 481      case 9:
 482        op = op_closepath;
 483        break;
 484      case 10:
 485        op = op_callsubr;
 486        break;
 487      case 11:
 488        op = op_return;
 489        break;
 490
 491      case 13:
 492        op = op_hsbw;
 493        break;
 494      case 14:
 495        op = op_endchar;
 496        break;
 497
 498      case 15:          /* undocumented, obsolete operator */
 499        op = op_unknown15;
 500        break;
 501
 502      case 21:
 503        op = op_rmoveto;
 504        break;
 505      case 22:
 506        op = op_hmoveto;
 507        break;
 508
 509      case 30:
 510        op = op_vhcurveto;
 511        break;
 512      case 31:
 513        op = op_hvcurveto;
 514        break;
 515
 516      case 12:
 517        if ( ip > limit )
 518        {
 519          FT_ERROR(( "t1_decoder_parse_charstrings:"
 520                     " invalid escape (12+EOF)\n" ));
 521          goto Syntax_Error;
 522        }
 523
 524        switch ( *ip++ )
 525        {
 526        case 0:
 527          op = op_dotsection;
 528          break;
 529        case 1:
 530          op = op_vstem3;
 531          break;
 532        case 2:
 533          op = op_hstem3;
 534          break;
 535        case 6:
 536          op = op_seac;
 537          break;
 538        case 7:
 539          op = op_sbw;
 540          break;
 541        case 12:
 542          op = op_div;
 543          break;
 544        case 16:
 545          op = op_callothersubr;
 546          break;
 547        case 17:
 548          op = op_pop;
 549          break;
 550        case 33:
 551          op = op_setcurrentpoint;
 552          break;
 553
 554        default:
 555          FT_ERROR(( "t1_decoder_parse_charstrings:"
 556                     " invalid escape (12+%d)\n",
 557                     ip[-1] ));
 558          goto Syntax_Error;
 559        }
 560        break;
 561
 562      case 255:    /* four bytes integer */
 563        if ( ip + 4 > limit )
 564        {
 565          FT_ERROR(( "t1_decoder_parse_charstrings:"
 566                     " unexpected EOF in integer\n" ));
 567          goto Syntax_Error;
 568        }
 569
 570        value = (FT_Int32)( ( (FT_Long)ip[0] << 24 ) |
 571                            ( (FT_Long)ip[1] << 16 ) |
 572                            ( (FT_Long)ip[2] << 8  ) |
 573                                       ip[3]         );
 574        ip += 4;
 575
 576        /* According to the specification, values > 32000 or < -32000 must */
 577        /* be followed by a `div' operator to make the result be in the    */
 578        /* range [-32000;32000].  We expect that the second argument of    */
 579        /* `div' is not a large number.  Additionally, we don't handle     */
 580        /* stuff like `<large1> <large2> <num> div <num> div' or           */
 581        /* <large1> <large2> <num> div div'.  This is probably not allowed */
 582        /* anyway.                                                         */
 583        if ( value > 32000 || value < -32000 )
 584        {
 585          if ( large_int )
 586          {
 587            FT_ERROR(( "t1_decoder_parse_charstrings:"
 588                       " no `div' after large integer\n" ));
 589          }
 590          else
 591            large_int = TRUE;
 592        }
 593        else
 594        {
 595          if ( !large_int )
 596            value <<= 16;
 597        }
 598
 599        break;
 600
 601      default:
 602        if ( ip[-1] >= 32 )
 603        {
 604          if ( ip[-1] < 247 )
 605            value = (FT_Int32)ip[-1] - 139;
 606          else
 607          {
 608            if ( ++ip > limit )
 609            {
 610              FT_ERROR(( "t1_decoder_parse_charstrings:"
 611                         " unexpected EOF in integer\n" ));
 612              goto Syntax_Error;
 613            }
 614
 615            if ( ip[-2] < 251 )
 616              value =  ( ( (FT_Int32)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
 617            else
 618              value = -( ( ( (FT_Int32)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
 619          }
 620
 621          if ( !large_int )
 622            value <<= 16;
 623        }
 624        else
 625        {
 626          FT_ERROR(( "t1_decoder_parse_charstrings:"
 627                     " invalid byte (%d)\n", ip[-1] ));
 628          goto Syntax_Error;
 629        }
 630      }
 631
 632      if ( unknown_othersubr_result_cnt > 0 )
 633      {
 634        switch ( op )
 635        {
 636        case op_callsubr:
 637        case op_return:
 638        case op_none:
 639        case op_pop:
 640          break;
 641
 642        default:
 643          /* all operands have been transferred by previous pops */
 644          unknown_othersubr_result_cnt = 0;
 645          break;
 646        }
 647      }
 648
 649      if ( large_int && !( op == op_none || op == op_div ) )
 650      {
 651        FT_ERROR(( "t1_decoder_parse_charstrings:"
 652                   " no `div' after large integer\n" ));
 653
 654        large_int = FALSE;
 655      }
 656
 657      /*********************************************************************/
 658      /*                                                                   */
 659      /*  Push value on stack, or process operator                         */
 660      /*                                                                   */
 661      /*                                                                   */
 662      if ( op == op_none )
 663      {
 664        if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
 665        {
 666          FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" ));
 667          goto Syntax_Error;
 668        }
 669
 670#ifdef FT_DEBUG_LEVEL_TRACE
 671        if ( large_int )
 672          FT_TRACE4(( " %ld", value ));
 673        else
 674          FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) ));
 675#endif
 676
 677        *top++       = value;
 678        decoder->top = top;
 679      }
 680      else if ( op == op_callothersubr )  /* callothersubr */
 681      {
 682        FT_Int  subr_no;
 683        FT_Int  arg_cnt;
 684
 685
 686#ifdef FT_DEBUG_LEVEL_TRACE
 687        FT_TRACE4(( " callothersubr\n" ));
 688        bol = TRUE;
 689#endif
 690
 691        if ( top - decoder->stack < 2 )
 692          goto Stack_Underflow;
 693
 694        top -= 2;
 695
 696        subr_no = (FT_Int)( top[1] >> 16 );
 697        arg_cnt = (FT_Int)( top[0] >> 16 );
 698
 699        /***********************************************************/
 700        /*                                                         */
 701        /* remove all operands to callothersubr from the stack     */
 702        /*                                                         */
 703        /* for handled othersubrs, where we know the number of     */
 704        /* arguments, we increase the stack by the value of        */
 705        /* known_othersubr_result_cnt                              */
 706        /*                                                         */
 707        /* for unhandled othersubrs the following pops adjust the  */
 708        /* stack pointer as necessary                              */
 709
 710        if ( arg_cnt > top - decoder->stack )
 711          goto Stack_Underflow;
 712
 713        top -= arg_cnt;
 714
 715        known_othersubr_result_cnt   = 0;
 716        unknown_othersubr_result_cnt = 0;
 717
 718        /* XXX TODO: The checks to `arg_count == <whatever>'       */
 719        /* might not be correct; an othersubr expects a certain    */
 720        /* number of operands on the PostScript stack (as opposed  */
 721        /* to the T1 stack) but it doesn't have to put them there  */
 722        /* by itself; previous othersubrs might have left the      */
 723        /* operands there if they were not followed by an          */
 724        /* appropriate number of pops                              */
 725        /*                                                         */
 726        /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
 727        /* accept a font that contains charstrings like            */
 728        /*                                                         */
 729        /*     100 200 2 20 callothersubr                          */
 730        /*     300 1 20 callothersubr pop                          */
 731        /*                                                         */
 732        /* Perhaps this is the reason why BuildCharArray exists.   */
 733
 734        switch ( subr_no )
 735        {
 736        case 1:                     /* start flex feature */
 737          if ( arg_cnt != 0 )
 738            goto Unexpected_OtherSubr;
 739
 740          decoder->flex_state        = 1;
 741          decoder->num_flex_vectors  = 0;
 742          if ( start_point( builder, x, y ) ||
 743               check_points( builder, 6 )   )
 744            goto Fail;
 745          break;
 746
 747        case 2:                     /* add flex vectors */
 748          {
 749            FT_Int  idx;
 750
 751
 752            if ( arg_cnt != 0 )
 753              goto Unexpected_OtherSubr;
 754
 755            /* note that we should not add a point for index 0; */
 756            /* this will move our current position to the flex  */
 757            /* point without adding any point to the outline    */
 758            idx = decoder->num_flex_vectors++;
 759            if ( idx > 0 && idx < 7 )
 760              add_point( builder,
 761                         x,
 762                         y,
 763                         (FT_Byte)( idx == 3 || idx == 6 ) );
 764          }
 765          break;
 766
 767        case 0:                     /* end flex feature */
 768          if ( arg_cnt != 3 )
 769            goto Unexpected_OtherSubr;
 770
 771          if ( decoder->flex_state       == 0 ||
 772               decoder->num_flex_vectors != 7 )
 773          {
 774            FT_ERROR(( "t1_decoder_parse_charstrings:"
 775                       " unexpected flex end\n" ));
 776            goto Syntax_Error;
 777          }
 778
 779          /* the two `results' are popped by the following setcurrentpoint */
 780          known_othersubr_result_cnt = 2;
 781          break;
 782
 783        case 3:                     /* change hints */
 784          if ( arg_cnt != 1 )
 785            goto Unexpected_OtherSubr;
 786
 787          known_othersubr_result_cnt = 1;
 788
 789          if ( hinter )
 790            hinter->reset( hinter->hints, builder->current->n_points );
 791          break;
 792
 793        case 12:
 794        case 13:
 795          /* counter control hints, clear stack */
 796          top = decoder->stack;
 797          break;
 798
 799        case 14:
 800        case 15:
 801        case 16:
 802        case 17:
 803        case 18:                    /* multiple masters */
 804          {
 805            PS_Blend  blend = decoder->blend;
 806            FT_UInt   num_points, nn, mm;
 807            FT_Long*  delta;
 808            FT_Long*  values;
 809
 810
 811            if ( !blend )
 812            {
 813              FT_ERROR(( "t1_decoder_parse_charstrings:"
 814                         " unexpected multiple masters operator\n" ));
 815              goto Syntax_Error;
 816            }
 817
 818            num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );
 819            if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )
 820            {
 821              FT_ERROR(( "t1_decoder_parse_charstrings:"
 822                         " incorrect number of multiple masters arguments\n" ));
 823              goto Syntax_Error;
 824            }
 825
 826            /* we want to compute:                                   */
 827            /*                                                       */
 828            /*  a0*w0 + a1*w1 + ... + ak*wk                          */
 829            /*                                                       */
 830            /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
 831            /* however, given that w0 + w1 + ... + wk == 1, we can   */
 832            /* rewrite it easily as:                                 */
 833            /*                                                       */
 834            /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
 835            /*                                                       */
 836            /* where k == num_designs-1                              */
 837            /*                                                       */
 838            /* I guess that's why it's written in this `compact'     */
 839            /* form.                                                 */
 840            /*                                                       */
 841            delta  = top + num_points;
 842            values = top;
 843            for ( nn = 0; nn < num_points; nn++ )
 844            {
 845              FT_Long  tmp = values[0];
 846
 847
 848              for ( mm = 1; mm < blend->num_designs; mm++ )
 849                tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
 850
 851              *values++ = tmp;
 852            }
 853
 854            known_othersubr_result_cnt = num_points;
 855            break;
 856          }
 857
 858        case 19:
 859          /* <idx> 1 19 callothersubr                             */
 860          /* => replace elements starting from index cvi( <idx> ) */
 861          /*    of BuildCharArray with WeightVector               */
 862          {
 863            FT_Int    idx;
 864            PS_Blend  blend = decoder->blend;
 865
 866
 867            if ( arg_cnt != 1 || blend == NULL )
 868              goto Unexpected_OtherSubr;
 869
 870            idx = (FT_Int)( top[0] >> 16 );
 871
 872            if ( idx < 0                                           ||
 873                 idx + blend->num_designs > decoder->len_buildchar )
 874              goto Unexpected_OtherSubr;
 875
 876            ft_memcpy( &decoder->buildchar[idx],
 877                       blend->weight_vector,
 878                       blend->num_designs *
 879                         sizeof( blend->weight_vector[0] ) );
 880          }
 881          break;
 882
 883        case 20:
 884          /* <arg1> <arg2> 2 20 callothersubr pop   */
 885          /* ==> push <arg1> + <arg2> onto T1 stack */
 886          if ( arg_cnt != 2 )
 887            goto Unexpected_OtherSubr;
 888
 889          top[0] += top[1]; /* XXX (over|under)flow */
 890
 891          known_othersubr_result_cnt = 1;
 892          break;
 893
 894        case 21:
 895          /* <arg1> <arg2> 2 21 callothersubr pop   */
 896          /* ==> push <arg1> - <arg2> onto T1 stack */
 897          if ( arg_cnt != 2 )
 898            goto Unexpected_OtherSubr;
 899
 900          top[0] -= top[1]; /* XXX (over|under)flow */
 901
 902          known_othersubr_result_cnt = 1;
 903          break;
 904
 905        case 22:
 906          /* <arg1> <arg2> 2 22 callothersubr pop   */
 907          /* ==> push <arg1> * <arg2> onto T1 stack */
 908          if ( arg_cnt != 2 )
 909            goto Unexpected_OtherSubr;
 910
 911          top[0] = FT_MulFix( top[0], top[1] );
 912
 913          known_othersubr_result_cnt = 1;
 914          break;
 915
 916        case 23:
 917          /* <arg1> <arg2> 2 23 callothersubr pop   */
 918          /* ==> push <arg1> / <arg2> onto T1 stack */
 919          if ( arg_cnt != 2 || top[1] == 0 )
 920            goto Unexpected_OtherSubr;
 921
 922          top[0] = FT_DivFix( top[0], top[1] );
 923
 924          known_othersubr_result_cnt = 1;
 925          break;
 926
 927        case 24:
 928          /* <val> <idx> 2 24 callothersubr               */
 929          /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
 930          {
 931            FT_Int    idx;
 932            PS_Blend  blend = decoder->blend;
 933
 934
 935            if ( arg_cnt != 2 || blend == NULL )
 936              goto Unexpected_OtherSubr;
 937
 938            idx = (FT_Int)( top[1] >> 16 );
 939
 940            if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
 941              goto Unexpected_OtherSubr;
 942
 943            decoder->buildchar[idx] = top[0];
 944          }
 945          break;
 946
 947        case 25:
 948          /* <idx> 1 25 callothersubr pop        */
 949          /* ==> push BuildCharArray[cvi( idx )] */
 950          /*     onto T1 stack                   */
 951          {
 952            FT_Int    idx;
 953            PS_Blend  blend = decoder->blend;
 954
 955
 956            if ( arg_cnt != 1 || blend == NULL )
 957              goto Unexpected_OtherSubr;
 958
 959            idx = (FT_Int)( top[0] >> 16 );
 960
 961            if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
 962              goto Unexpected_OtherSubr;
 963
 964            top[0] = decoder->buildchar[idx];
 965          }
 966
 967          known_othersubr_result_cnt = 1;
 968          break;
 969
 970#if 0
 971        case 26:
 972          /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
 973          /*                      leave mark on T1 stack                    */
 974          /* <val> <idx>      ==> set BuildCharArray[cvi( <idx> )] = <val>  */
 975          XXX which routine has left its mark on the (PostScript) stack?;
 976          break;
 977#endif
 978
 979        case 27:
 980          /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
 981          /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
 982          /*     otherwise push <res2>                          */
 983          if ( arg_cnt != 4 )
 984            goto Unexpected_OtherSubr;
 985
 986          if ( top[2] > top[3] )
 987            top[0] = top[1];
 988
 989          known_othersubr_result_cnt = 1;
 990          break;
 991
 992        case 28:
 993          /* 0 28 callothersubr pop                               */
 994          /* => push random value from interval [0, 1) onto stack */
 995          if ( arg_cnt != 0 )
 996            goto Unexpected_OtherSubr;
 997
 998          {
 999            FT_Fixed  Rand;
1000
1001
1002            Rand = seed;
1003            if ( Rand >= 0x8000L )
1004              Rand++;
1005
1006            top[0] = Rand;
1007
1008            seed = FT_MulFix( seed, 0x10000L - seed );
1009            if ( seed == 0 )
1010              seed += 0x2873;
1011          }
1012
1013          known_othersubr_result_cnt = 1;
1014          break;
1015
1016        default:
1017          FT_ERROR(( "t1_decoder_parse_charstrings:"
1018                     " unknown othersubr [%d %d], wish me luck\n",
1019                     arg_cnt, subr_no ));
1020          unknown_othersubr_result_cnt = arg_cnt;
1021          break;
1022
1023        Unexpected_OtherSubr:
1024          FT_ERROR(( "t1_decoder_parse_charstrings:"
1025                     " invalid othersubr [%d %d]\n", arg_cnt, subr_no ));
1026          goto Syntax_Error;
1027        }
1028
1029        top += known_othersubr_result_cnt;
1030
1031        decoder->top = top;
1032      }
1033      else  /* general operator */
1034      {
1035        FT_Int  num_args = t1_args_count[op];
1036
1037
1038        FT_ASSERT( num_args >= 0 );
1039
1040        if ( top - decoder->stack < num_args )
1041          goto Stack_Underflow;
1042
1043        /* XXX Operators usually take their operands from the        */
1044        /*     bottom of the stack, i.e., the operands are           */
1045        /*     decoder->stack[0], ..., decoder->stack[num_args - 1]; */
1046        /*     only div, callsubr, and callothersubr are different.  */
1047        /*     In practice it doesn't matter (?).                    */
1048
1049#ifdef FT_DEBUG_LEVEL_TRACE
1050
1051        switch ( op )
1052        {
1053        case op_callsubr:
1054        case op_div:
1055        case op_callothersubr:
1056        case op_pop:
1057        case op_return:
1058          break;
1059
1060        default:
1061          if ( top - decoder->stack != num_args )
1062            FT_TRACE0(( "t1_decoder_parse_charstrings:"
1063                        " too much operands on the stack"
1064                        " (seen %d, expected %d)\n",
1065                        top - decoder->stack, num_args ));
1066            break;
1067        }
1068
1069#endif /* FT_DEBUG_LEVEL_TRACE */
1070
1071        top -= num_args;
1072
1073        switch ( op )
1074        {
1075        case op_endchar:
1076          FT_TRACE4(( " endchar\n" ));
1077
1078          close_contour( builder );
1079
1080          /* close hints recording session */
1081          if ( hinter )
1082          {
1083            if ( hinter->close( hinter->hints, builder->current->n_points ) )
1084              goto Syntax_Error;
1085
1086            /* apply hints to the loaded glyph outline now */
1087            hinter->apply( hinter->hints,
1088                           builder->current,
1089                           (PSH_Globals)builder->hints_globals,
1090                           decoder->hint_mode );
1091          }
1092
1093          /* add current outline to the glyph slot */
1094          FT_GlyphLoader_Add( builder->loader );
1095
1096          /* the compiler should optimize away this empty loop but ... */
1097
1098#ifdef FT_DEBUG_LEVEL_TRACE
1099
1100          if ( decoder->len_buildchar > 0 )
1101          {
1102            FT_UInt  i;
1103
1104
1105            FT_TRACE4(( "BuildCharArray = [ " ));
1106
1107            for ( i = 0; i < decoder->len_buildchar; ++i )
1108              FT_TRACE4(( "%d ", decoder->buildchar[ i ] ));
1109
1110            FT_TRACE4(( "]\n" ));
1111          }
1112
1113#endif /* FT_DEBUG_LEVEL_TRACE */
1114
1115          FT_TRACE4(( "\n" ));
1116
1117          /* return now! */
1118          return PSaux_Err_Ok;
1119
1120        case op_hsbw:
1121          FT_TRACE4(( " hsbw" ));
1122
1123          builder->parse_state = T1_Parse_Have_Width;
1124
1125          builder->left_bearing.x += top[0];
1126          builder->advance.x       = top[1];
1127          builder->advance.y       = 0;
1128
1129          orig_x = x = builder->pos_x + top[0];
1130          orig_y = y = builder->pos_y;
1131
1132          FT_UNUSED( orig_y );
1133
1134          /* the `metrics_only' indicates that we only want to compute */
1135          /* the glyph's metrics (lsb + advance width), not load the   */
1136          /* rest of it; so exit immediately                           */
1137          if ( builder->metrics_only )
1138            return PSaux_Err_Ok;
1139
1140          break;
1141
1142        case op_seac:
1143          return t1operator_seac( decoder,
1144                                  top[0],
1145                                  top[1],
1146                                  top[2],
1147                                  (FT_Int)( top[3] >> 16 ),
1148                                  (FT_Int)( top[4] >> 16 ) );
1149
1150        case op_sbw:
1151          FT_TRACE4(( " sbw" ));
1152
1153          builder->parse_state = T1_Parse_Have_Width;
1154
1155          builder->left_bearing.x += top[0];
1156          builder->left_bearing.y += top[1];
1157          builder->advance.x       = top[2];
1158          builder->advance.y       = top[3];
1159
1160          x = builder->pos_x + top[0];
1161          y = builder->pos_y + top[1];
1162
1163          /* the `metrics_only' indicates that we only want to compute */
1164          /* the glyph's metrics (lsb + advance width), not load the   */
1165          /* rest of it; so exit immediately                           */
1166          if ( builder->metrics_only )
1167            return PSaux_Err_Ok;
1168
1169          break;
1170
1171        case op_closepath:
1172          FT_TRACE4(( " closepath" ));
1173
1174          /* if there is no path, `closepath' is a no-op */
1175          if ( builder->parse_state == T1_Parse_Have_Path   ||
1176               builder->parse_state == T1_Parse_Have_Moveto )
1177            close_contour( builder );
1178
1179          builder->parse_state = T1_Parse_Have_Width;
1180          break;
1181
1182        case op_hlineto:
1183          FT_TRACE4(( " hlineto" ));
1184
1185          if ( start_point( builder, x, y ) )
1186            goto Fail;
1187
1188          x += top[0];
1189          goto Add_Line;
1190
1191        case op_hmoveto:
1192          FT_TRACE4(( " hmoveto" ));
1193
1194          x += top[0];
1195          if ( !decoder->flex_state )
1196          {
1197            if ( builder->parse_state == T1_Parse_Start )
1198              goto Syntax_Error;
1199            builder->parse_state = T1_Parse_Have_Moveto;
1200          }
1201          break;
1202
1203        case op_hvcurveto:
1204          FT_TRACE4(( " hvcurveto" ));
1205
1206          if ( start_point( builder, x, y ) ||
1207               check_points( builder, 3 )   )
1208            goto Fail;
1209
1210          x += top[0];
1211          add_point( builder, x, y, 0 );
1212          x += top[1];
1213          y += top[2];
1214          add_point( builder, x, y, 0 );
1215          y += top[3];
1216          add_point( builder, x, y, 1 );
1217          break;
1218
1219        case op_rlineto:
1220          FT_TRACE4(( " rlineto" ));
1221
1222          if ( start_point( builder, x, y ) )
1223            goto Fail;
1224
1225          x += top[0];
1226          y += top[1];
1227
1228        Add_Line:
1229          if ( add_point1( builder, x, y ) )
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 ( start_point( builder, x, y ) ||
1250               check_points( builder, 3 )   )
1251            goto Fail;
1252
1253          x += top[0];
1254          y += top[1];
1255          add_point( builder, x, y, 0 );
1256
1257          x += top[2];
1258          y += top[3];
1259          add_point( builder, x, y, 0 );
1260
1261          x += top[4];
1262          y += top[5];
1263          add_point( builder, x, y, 1 );
1264          break;
1265
1266        case op_vhcurveto:
1267          FT_TRACE4(( " vhcurveto" ));
1268
1269          if ( start_point( builder, x, y ) ||
1270               check_points( builder, 3 )   )
1271            goto Fail;
1272
1273          y += top[0];
1274          add_point( builder, x, y, 0 );
1275          x += top[1];
1276          y += top[2];
1277          add_point( builder, x, y, 0 );
1278          x += top[3];
1279          add_point( builder, x, y, 1 );
1280          break;
1281
1282        case op_vlineto:
1283          FT_TRACE4(( " vlineto" ));
1284
1285          if ( start_point( builder, x, y ) )
1286            goto Fail;
1287
1288          y += top[0];
1289          goto Add_Line;
1290
1291        case op_vmoveto:
1292          FT_TRACE4(( " vmoveto" ));
1293
1294          y += top[0];
1295          if ( !decoder->flex_state )
1296          {
1297            if ( builder->parse_state == T1_Parse_Start )
1298              goto Syntax_Error;
1299            builder->parse_state = T1_Parse_Have_Moveto;
1300          }
1301          break;
1302
1303        case op_div:
1304          FT_TRACE4(( " div" ));
1305
1306          /* if `large_int' is set, we divide unscaled numbers; */
1307          /* otherwise, we divide numbers in 16.16 format --    */
1308          /* in both cases, it is the same operation            */
1309          *top = FT_DivFix( top[0], top[1] );
1310          ++top;
1311
1312          large_int = FALSE;
1313          break;
1314
1315        case op_callsubr:
1316          {
1317            FT_Int  idx;
1318
1319
1320            FT_TRACE4(( " callsubr" ));
1321
1322            idx = (FT_Int)( top[0] >> 16 );
1323            if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
1324            {
1325              FT_ERROR(( "t1_decoder_parse_charstrings:"
1326                         " invalid subrs index\n" ));
1327              goto Syntax_Error;
1328            }
1329
1330            if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
1331            {
1332              FT_ERROR(( "t1_decoder_parse_charstrings:"
1333                         " too many nested subrs\n" ));
1334              goto Syntax_Error;
1335            }
1336
1337            zone->cursor = ip;  /* save current instruction pointer */
1338
1339            zone++;
1340
1341            /* The Type 1 driver stores subroutines without the seed bytes. */
1342            /* The CID driver stores subroutines with seed bytes.  This     */
1343            /* case is taken care of when decoder->subrs_len == 0.          */
1344            zone->base = decoder->subrs[idx];
1345
1346            if ( decoder->subrs_len )
1347              zone->limit = zone->base + decoder->subrs_len[idx];
1348            else
1349            {
1350              /* We are using subroutines from a CID font.  We must adjust */
1351              /* for the seed bytes.                                       */
1352              zone->base  += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
1353              zone->limit  = decoder->subrs[idx + 1];
1354            }
1355
1356            zone->cursor = zone->base;
1357
1358            if ( !zone->base )
1359            {
1360              FT_ERROR(( "t1_decoder_parse_charstrings:"
1361                         " invoking empty subrs\n" ));
1362              goto Syntax_Error;
1363            }
1364
1365            decoder->zone = zone;
1366            ip            = zone->base;
1367            limit         = zone->limit;
1368            break;
1369          }
1370
1371        case op_pop:
1372          FT_TRACE4(( " pop" ));
1373
1374          if ( known_othersubr_result_cnt > 0 )
1375          {
1376            known_othersubr_result_cnt--;
1377            /* ignore, we pushed the operands ourselves */
1378            break;
1379          }
1380
1381          if ( unknown_othersubr_result_cnt == 0 )
1382          {
1383            FT_ERROR(( "t1_decoder_parse_charstrings:"
1384                       " no more operands for othersubr\n" ));
1385            goto Syntax_Error;
1386          }
1387
1388          unknown_othersubr_result_cnt--;
1389          top++;   /* `push' the operand to callothersubr onto the stack */
1390          break;
1391
1392        case op_return:
1393          FT_TRACE4(( " return" ));
1394
1395          if ( zone <= decoder->zones )
1396          {
1397            FT_ERROR(( "t1_decoder_parse_charstrings:"
1398                       " unexpected return\n" ));
1399            goto Syntax_Error;
1400          }
1401
1402          zone--;
1403          ip            = zone->cursor;
1404          limit         = zone->limit;
1405          decoder->zone = zone;
1406          break;
1407
1408        case op_dotsection:
1409          FT_TRACE4(( " dotsection" ));
1410
1411          break;
1412
1413        case op_hstem:
1414          FT_TRACE4(( " hstem" ));
1415
1416          /* record horizontal hint */
1417          if ( hinter )
1418          {
1419            /* top[0] += builder->left_bearing.y; */
1420            hinter->stem( hinter->hints, 1, top );
1421          }
1422          break;
1423
1424        case op_hstem3:
1425          FT_TRACE4(( " hstem3" ));
1426
1427          /* record horizontal counter-controlled hints */
1428          if ( hinter )
1429            hinter->stem3( hinter->hints, 1, top );
1430          break;
1431
1432        case op_vstem:
1433          FT_TRACE4(( " vstem" ));
1434
1435          /* record vertical hint */
1436          if ( hinter )
1437          {
1438            top[0] += orig_x;
1439            hinter->stem( hinter->hints, 0, top );
1440          }
1441          break;
1442
1443        case op_vstem3:
1444          FT_TRACE4(( " vstem3" ));
1445
1446          /* record vertical counter-controlled hints */
1447          if ( hinter )
1448          {
1449            FT_Pos  dx = orig_x;
1450
1451
1452            top[0] += dx;
1453            top[2] += dx;
1454            top[4] += dx;
1455            hinter->stem3( hinter->hints, 0, top );
1456          }
1457          break;
1458
1459        case op_setcurrentpoint:
1460          FT_TRACE4(( " setcurrentpoint" ));
1461
1462          /* From the T1 specification, section 6.4:                */
1463          /*                                                        */
1464          /*   The setcurrentpoint command is used only in          */
1465          /*   conjunction with results from OtherSubrs procedures. */
1466
1467          /* known_othersubr_result_cnt != 0 is already handled     */
1468          /* above.                                                 */
1469
1470          /* Note, however, that both Ghostscript and Adobe         */
1471          /* Distiller handle this situation by silently ignoring   */
1472          /* the inappropriate `setcurrentpoint' instruction.  So   */
1473          /* we do the same.                                        */
1474#if 0
1475
1476          if ( decoder->flex_state != 1 )
1477          {
1478            FT_ERROR(( "t1_decoder_parse_charstrings:"
1479                       " unexpected `setcurrentpoint'\n" ));
1480            goto Syntax_Error;
1481          }
1482          else
1483#endif
1484            decoder->flex_state = 0;
1485          break;
1486
1487        case op_unknown15:
1488          FT_TRACE4(( " opcode_15" ));
1489          /* nothing to do except to pop the two arguments */
1490          break;
1491
1492        default:
1493          FT_ERROR(( "t1_decoder_parse_charstrings:"
1494                     " unhandled opcode %d\n", op ));
1495          goto Syntax_Error;
1496        }
1497
1498        /* XXX Operators usually clear the operand stack;  */
1499        /*     only div, callsubr, callothersubr, pop, and */
1500        /*     return are different.                       */
1501        /*     In practice it doesn't matter (?).          */
1502
1503        decoder->top = top;
1504
1505#ifdef FT_DEBUG_LEVEL_TRACE
1506        FT_TRACE4(( "\n" ));
1507        bol = TRUE;
1508#endif
1509
1510      } /* general operator processing */
1511
1512    } /* while ip < limit */
1513
1514    FT_TRACE4(( "..end..\n\n" ));
1515
1516  Fail:
1517    return error;
1518
1519  Syntax_Error:
1520    return PSaux_Err_Syntax_Error;
1521
1522  Stack_Underflow:
1523    return PSaux_Err_Stack_Underflow;
1524  }
1525
1526
1527  /* parse a single Type 1 glyph */
1528  FT_LOCAL_DEF( FT_Error )
1529  t1_decoder_parse_glyph( T1_Decoder  decoder,
1530                          FT_UInt     glyph )
1531  {
1532    return decoder->parse_callback( decoder, glyph );
1533  }
1534
1535
1536  /* initialize T1 decoder */
1537  FT_LOCAL_DEF( FT_Error )
1538  t1_decoder_init( T1_Decoder           decoder,
1539                   FT_Face              face,
1540                   FT_Size              size,
1541                   FT_GlyphSlot         slot,
1542                   FT_Byte**            glyph_names,
1543                   PS_Blend             blend,
1544                   FT_Bool              hinting,
1545                   FT_Render_Mode       hint_mode,
1546                   T1_Decoder_Callback  parse_callback )
1547  {
1548    FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
1549
1550    /* retrieve PSNames interface from list of current modules */
1551    {
1552      FT_Service_PsCMaps  psnames = 0;
1553
1554
1555      FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
1556      if ( !psnames )
1557      {
1558        FT_ERROR(( "t1_decoder_init:"
1559                   " the `psnames' module is not available\n" ));
1560        return PSaux_Err_Unimplemented_Feature;
1561      }
1562
1563      decoder->psnames = psnames;
1564    }
1565
1566    t1_builder_init( &decoder->builder, face, size, slot, hinting );
1567
1568    /* decoder->buildchar and decoder->len_buildchar have to be  */
1569    /* initialized by the caller since we cannot know the length */
1570    /* of the BuildCharArray                                     */
1571
1572    decoder->num_glyphs     = (FT_UInt)face->num_glyphs;
1573    decoder->glyph_names    = glyph_names;
1574    decoder->hint_mode      = hint_mode;
1575    decoder->blend          = blend;
1576    decoder->parse_callback = parse_callback;
1577
1578    decoder->funcs          = t1_decoder_funcs;
1579
1580    return PSaux_Err_Ok;
1581  }
1582
1583
1584  /* finalize T1 decoder */
1585  FT_LOCAL_DEF( void )
1586  t1_decoder_done( T1_Decoder  decoder )
1587  {
1588    t1_builder_done( &decoder->builder );
1589  }
1590
1591
1592/* END */