PageRenderTime 102ms CodeModel.GetById 27ms app.highlight 64ms RepoModel.GetById 1ms app.codeStats 0ms

/src/freetype/src/psaux/t1decode.c

https://bitbucket.org/cabalistic/ogredeps/
C | 1614 lines | 1049 code | 311 blank | 254 comment | 181 complexity | 0b0b4db295806b3fbad5d3f950c892d4 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file