shithub: freetype+ttf2subf

Download patch

ref: fa3d6e94229b8169b3ede1e5f3ee0f6549cd9916
parent: 389acc625edf757f2b555e5d1fd7995f192edd0e
author: Tom Kacvinsky <[email protected]>
date: Tue Jan 2 19:14:11 EST 2001

Renamed t2gload.c to cffgload.c.

git/fs: mount .git/fs: mount/attach disallowed
--- a/src/cff/t2gload.c
+++ /dev/null
@@ -1,2254 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  t2gload.c                                                              */
-/*                                                                         */
-/*    OpenType Glyph Loader (body).                                        */
-/*                                                                         */
-/*  Copyright 1996-2000 by                                                 */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
-/*                                                                         */
-/*  This file is part of the FreeType project, and may only be used,       */
-/*  modified, and distributed under the terms of the FreeType project      */
-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
-/*  this file you indicate that you have read the license and              */
-/*  understand and accept it fully.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_CALC_H
-#include FT_INTERNAL_STREAM_H
-#include FT_INTERNAL_SFNT_H
-#include FT_OUTLINE_H
-#include FT_TRUETYPE_TAGS_H
-
-#include FT_SOURCE_FILE(cff,cffload.h)
-#include FT_SOURCE_FILE(cff,t2gload.h)
-
-#include FT_INTERNAL_CFF_ERRORS_H
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_t2gload
-
-
-  typedef enum  T2_Operator_
-  {
-    t2_op_unknown = 0,
-
-    t2_op_rmoveto,
-    t2_op_hmoveto,
-    t2_op_vmoveto,
-
-    t2_op_rlineto,
-    t2_op_hlineto,
-    t2_op_vlineto,
-
-    t2_op_rrcurveto,
-    t2_op_hhcurveto,
-    t2_op_hvcurveto,
-    t2_op_rcurveline,
-    t2_op_rlinecurve,
-    t2_op_vhcurveto,
-    t2_op_vvcurveto,
-
-    t2_op_flex,
-    t2_op_hflex,
-    t2_op_hflex1,
-    t2_op_flex1,
-
-    t2_op_endchar,
-
-    t2_op_hstem,
-    t2_op_vstem,
-    t2_op_hstemhm,
-    t2_op_vstemhm,
-
-    t2_op_hintmask,
-    t2_op_cntrmask,
-
-    t2_op_abs,
-    t2_op_add,
-    t2_op_sub,
-    t2_op_div,
-    t2_op_neg,
-    t2_op_random,
-    t2_op_mul,
-    t2_op_sqrt,
-
-    t2_op_blend,
-
-    t2_op_drop,
-    t2_op_exch,
-    t2_op_index,
-    t2_op_roll,
-    t2_op_dup,
-
-    t2_op_put,
-    t2_op_get,
-    t2_op_store,
-    t2_op_load,
-
-    t2_op_and,
-    t2_op_or,
-    t2_op_not,
-    t2_op_eq,
-    t2_op_ifelse,
-
-    t2_op_callsubr,
-    t2_op_callgsubr,
-    t2_op_return,
-
-    /* do not remove */
-    t2_op_max
-
-  } T2_Operator;
-
-
-#define T2_COUNT_CHECK_WIDTH  0x80
-#define T2_COUNT_EXACT        0x40
-#define T2_COUNT_CLEAR_STACK  0x20
-
-
-  static const FT_Byte  t2_argument_counts[] =
-  {
-    0,  /* unknown */
-
-    2 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, /* rmoveto */
-    1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT,
-    1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT,
-
-    0 | T2_COUNT_CLEAR_STACK, /* rlineto */
-    0 | T2_COUNT_CLEAR_STACK,
-    0 | T2_COUNT_CLEAR_STACK,
-
-    0 | T2_COUNT_CLEAR_STACK, /* rrcurveto */
-    0 | T2_COUNT_CLEAR_STACK,
-    0 | T2_COUNT_CLEAR_STACK,
-    0 | T2_COUNT_CLEAR_STACK,
-    0 | T2_COUNT_CLEAR_STACK,
-    0 | T2_COUNT_CLEAR_STACK,
-    0 | T2_COUNT_CLEAR_STACK,
-
-    13, /* flex */
-    7,
-    9,
-    11,
-
-    0 | T2_COUNT_CHECK_WIDTH, /* endchar */
-
-    2 | T2_COUNT_CHECK_WIDTH, /* hstem */
-    2 | T2_COUNT_CHECK_WIDTH,
-    2 | T2_COUNT_CHECK_WIDTH,
-    2 | T2_COUNT_CHECK_WIDTH,
-
-    0, /* hintmask */
-    0, /* cntrmask */
-
-    1, /* abs */
-    2,
-    2,
-    2,
-    1,
-    0,
-    2,
-    1,
-
-    1, /* blend */
-
-    1, /* drop */
-    2,
-    1,
-    2,
-    1,
-
-    2, /* put */
-    1,
-    4,
-    3,
-
-    2, /* and */
-    2,
-    1,
-    2,
-    4,
-
-    1, /* callsubr */
-    1,
-    0
-  };
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /**********                                                      *********/
-  /**********                                                      *********/
-  /**********             GENERIC CHARSTRING PARSING               *********/
-  /**********                                                      *********/
-  /**********                                                      *********/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    T2_Init_Builder                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Initializes a given glyph builder.                                 */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    builder :: A pointer to the glyph builder to initialize.           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face    :: The current face object.                                */
-  /*                                                                       */
-  /*    size    :: The current size object.                                */
-  /*                                                                       */
-  /*    glyph   :: The current glyph object.                               */
-  /*                                                                       */
-  static
-  void  T2_Init_Builder( T2_Builder*   builder,
-                         TT_Face       face,
-                         T2_Size       size,
-                         T2_GlyphSlot  glyph )
-  {
-    builder->path_begun  = 0;
-    builder->load_points = 1;
-
-    builder->face   = face;
-    builder->glyph  = glyph;
-    builder->memory = face->root.memory;
-
-    if ( glyph )
-    {
-      FT_GlyphLoader*  loader = glyph->root.internal->loader;
-
-
-      builder->loader  = loader;
-      builder->base    = &loader->base.outline;
-      builder->current = &loader->current.outline;
-      FT_GlyphLoader_Rewind( loader );
-    }
-
-    if ( size )
-    {
-      builder->scale_x = size->metrics.x_scale;
-      builder->scale_y = size->metrics.y_scale;
-    }
-
-    builder->pos_x = 0;
-    builder->pos_y = 0;
-
-    builder->left_bearing.x = 0;
-    builder->left_bearing.y = 0;
-    builder->advance.x      = 0;
-    builder->advance.y      = 0;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    T2_Done_Builder                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Finalizes a given glyph builder.  Its contents can still be used   */
-  /*    after the call, but the function saves important information       */
-  /*    within the corresponding glyph slot.                               */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    builder :: A pointer to the glyph builder to finalize.             */
-  /*                                                                       */
-  static
-  void  T2_Done_Builder( T2_Builder*  builder )
-  {
-    T2_GlyphSlot  glyph = builder->glyph;
-
-
-    if ( glyph )
-      glyph->root.outline = *builder->base;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    t2_compute_bias                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Computes the bias value in dependence of the number of glyph       */
-  /*    subroutines.                                                       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    num_subrs :: The number of glyph subroutines.                      */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The bias value.                                                    */
-  static
-  FT_Int  t2_compute_bias( FT_UInt  num_subrs )
-  {
-    FT_Int  result;
-
-
-    if ( num_subrs < 1240 )
-      result = 107;
-    else if ( num_subrs < 33900 )
-      result = 1131;
-    else
-      result = 32768;
-
-    return result;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    T2_Init_Decoder                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Initializes a given glyph decoder.                                 */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    decoder :: A pointer to the glyph builder to initialize.           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face    :: The current face object.                                */
-  /*                                                                       */
-  /*    size    :: The current size object.                                */
-  /*                                                                       */
-  /*    slot    :: The current glyph object.                               */
-  /*                                                                       */
-  FT_LOCAL_DEF
-  void  T2_Init_Decoder( T2_Decoder*  decoder,
-                         TT_Face      face,
-                         T2_Size      size,
-                         T2_GlyphSlot slot )
-  {
-    CFF_Font*  cff = (CFF_Font*)face->extra.data;
-
-
-    /* clear everything */
-    MEM_Set( decoder, 0, sizeof ( *decoder ) );
-
-    /* initialize builder */
-    T2_Init_Builder( &decoder->builder, face, size, slot );
-
-    /* initialize Type2 decoder */
-    decoder->num_globals  = cff->num_global_subrs;
-    decoder->globals      = cff->global_subrs;
-    decoder->globals_bias = t2_compute_bias( decoder->num_globals );
-  }
-
-
-  /* this function is used to select the locals subrs array */
-  FT_LOCAL_DEF
-  void  T2_Prepare_Decoder( T2_Decoder*  decoder,
-                            FT_UInt      glyph_index )
-  {
-    CFF_Font*     cff = (CFF_Font*)decoder->builder.face->extra.data;
-    CFF_SubFont*  sub = &cff->top_font;
-
-
-    /* manage CID fonts */
-    if ( cff->num_subfonts >= 1 )
-    {
-      FT_Byte  fd_index = CFF_Get_FD( &cff->fd_select, glyph_index );
-
-
-      sub = cff->subfonts[fd_index];
-    }
-
-    decoder->num_locals    = sub->num_local_subrs;
-    decoder->locals        = sub->local_subrs;
-    decoder->locals_bias   = t2_compute_bias( decoder->num_locals );
-
-    decoder->glyph_width   = sub->private_dict.default_width;
-    decoder->nominal_width = sub->private_dict.nominal_width;
-  }
-
-
-  /* check that there is enough room for `count' more points */
-  static
-  FT_Error  check_points( T2_Builder*  builder,
-                          FT_Int       count )
-  {
-    return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
-  }
-
-
-  /* add a new point, do not check space */
-  static
-  void  add_point( T2_Builder*  builder,
-                   FT_Pos       x,
-                   FT_Pos       y,
-                   FT_Byte      flag )
-  {
-    FT_Outline*  outline = builder->current;
-
-
-    if ( builder->load_points )
-    {
-      FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
-
-
-      point->x = x >> 16;
-      point->y = y >> 16;
-      *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
-
-      builder->last = *point;
-    }
-    outline->n_points++;
-  }
-
-
-  /* check space for a new on-curve point, then add it */
-  static
-  FT_Error  add_point1( T2_Builder*  builder,
-                        FT_Pos       x,
-                        FT_Pos       y )
-  {
-    FT_Error  error;
-
-
-    error = check_points( builder, 1 );
-    if ( !error )
-      add_point( builder, x, y, 1 );
-
-    return error;
-  }
-
-
-  /* check room for a new contour, then add it */
-  static
-  FT_Error  add_contour( T2_Builder*  builder )
-  {
-    FT_Outline*  outline = builder->current;
-    FT_Error     error;
-
-
-    if ( !builder->load_points )
-    {
-      outline->n_contours++;
-      return T2_Err_Ok;
-    }
-
-    error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
-    if ( !error )
-    {
-      if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
-
-      outline->n_contours++;
-    }
-
-    return error;
-  }
-
-
-  /* if a path was begun, add its first on-curve point */
-  static
-  FT_Error  start_point( T2_Builder*  builder,
-                         FT_Pos       x,
-                         FT_Pos       y )
-  {
-    FT_Error  error = 0;
-
-
-    /* test whether we are building a new contour */
-    if ( !builder->path_begun )
-    {
-      builder->path_begun = 1;
-      error = add_contour( builder );
-      if ( !error )
-        error = add_point1( builder, x, y );
-    }
-    return error;
-  }
-
-
-  /* close the current contour */
-  static
-  void  close_contour( T2_Builder*  builder )
-  {
-    FT_Outline*  outline = builder->current;
-
-    /* XXXX: We must not include the last point in the path if it */
-    /*       is located on the first point.                       */
-    if ( outline->n_points > 1 )
-    {
-      FT_Int      first   = 0;
-      FT_Vector*  p1      = outline->points + first;
-      FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
-
-
-      if ( outline->n_contours > 1 )
-      {
-        first = outline->contours[outline->n_contours - 2] + 1;
-        p1    = outline->points + first;
-      }
-
-      /* `delete' last point only if it coincides with the first */
-      /* point and it is not a control point (which can happen). */
-      if ( p1->x == p2->x && p1->y == p2->y )
-        if ( *control == FT_Curve_Tag_On )
-          outline->n_points--;
-    }
-
-    if ( outline->n_contours > 0 )
-      outline->contours[outline->n_contours - 1] = outline->n_points - 1;
-  }
-
-
-  static
-  FT_Int  t2_lookup_glyph_by_stdcharcode( CFF_Font*  cff,
-                                          FT_Int     charcode )
-  {
-    FT_UInt    n;
-    FT_UShort  glyph_sid;
-
-
-    /* check range of standard char code */
-    if ( charcode < 0 || charcode > 255 )
-      return -1;
-
-
-    /* Get code to SID mapping from `cff_standard_encoding'. */
-    glyph_sid = cff_standard_encoding[charcode];
-
-    for ( n = 0; n < cff->num_glyphs; n++ )
-    {
-      if ( cff->charset.sids[n] == glyph_sid )
-        return n;
-    }
-
-    return -1;
-  }
-
-
-  static
-  FT_Error  t2_operator_seac( T2_Decoder*  decoder,
-                              FT_Pos       adx,
-                              FT_Pos       ady,
-                              FT_Int       bchar,
-                              FT_Int       achar )
-  {
-    FT_Error     error;
-    FT_Int       bchar_index, achar_index, n_base_points;
-    FT_Outline*  base = decoder->builder.base;
-    TT_Face      face = decoder->builder.face;
-    CFF_Font*    cff  = (CFF_Font*)(face->extra.data);
-    FT_Vector    left_bearing, advance;
-    FT_Byte*     charstring;
-    FT_ULong     charstring_len;
-
-
-    bchar_index = t2_lookup_glyph_by_stdcharcode( cff, bchar );
-    achar_index = t2_lookup_glyph_by_stdcharcode( cff, achar );
-
-    if ( bchar_index < 0 || achar_index < 0 )
-    {
-      FT_ERROR(( "t2_operator_seac:" ));
-      FT_ERROR(( " invalid seac character code arguments\n" ));
-      return T2_Err_Syntax_Error;
-    }
-
-    /* If we are trying to load a composite glyph, do not load the */
-    /* accent character and return the array of subglyphs.         */
-    if ( decoder->builder.no_recurse )
-    {
-      FT_GlyphSlot     glyph  = (FT_GlyphSlot)decoder->builder.glyph;
-      FT_GlyphLoader*  loader = glyph->internal->loader;
-      FT_SubGlyph*     subg;
-
-
-      /* reallocate subglyph array if necessary */
-      error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
-      if ( error )
-        goto Exit;
-
-      subg = loader->current.subglyphs;
-
-      /* subglyph 0 = base character */
-      subg->index = bchar_index;
-      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
-                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
-      subg->arg1  = 0;
-      subg->arg2  = 0;
-      subg++;
-
-      /* subglyph 1 = accent character */
-      subg->index = achar_index;
-      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
-      subg->arg1  = adx;
-      subg->arg2  = ady;
-
-      /* set up remaining glyph fields */
-      glyph->num_subglyphs = 2;
-      glyph->subglyphs     = loader->base.subglyphs;
-      glyph->format        = ft_glyph_format_composite;
-
-      loader->current.num_subglyphs = 2;
-    }
-
-    /* First load `bchar' in builder */
-    error = CFF_Access_Element( &cff->charstrings_index, bchar_index,
-                                &charstring, &charstring_len );
-    if ( !error )
-    {
-      error = T2_Parse_CharStrings( decoder, charstring, charstring_len );
-
-      if ( error )
-        goto Exit;
-
-      CFF_Forget_Element( &cff->charstrings_index, &charstring );
-    }
-
-    n_base_points = base->n_points;
-
-    /* Save the left bearing and width of the base character */
-    /* as they will be erased by the next load.              */
-
-    left_bearing = decoder->builder.left_bearing;
-    advance      = decoder->builder.advance;
-
-    decoder->builder.left_bearing.x = 0;
-    decoder->builder.left_bearing.y = 0;
-
-    /* Now load `achar' on top of the base outline. */
-    error = CFF_Access_Element( &cff->charstrings_index, achar_index,
-                                &charstring, &charstring_len );
-    if ( !error )
-    {
-      error = T2_Parse_CharStrings( decoder, charstring, charstring_len );
-
-      if ( error )
-        goto Exit;
-
-      CFF_Forget_Element( &cff->charstrings_index, &charstring );
-    }
-
-    /* Restore the left side bearing and advance width */
-    /* of the base character.                          */
-    decoder->builder.left_bearing = left_bearing;
-    decoder->builder.advance      = advance;
-
-    /* Finally, move the accent. */
-    if ( decoder->builder.load_points )
-    {
-      FT_Outline  dummy;
-
-
-      dummy.n_points = base->n_points - n_base_points;
-      dummy.points   = base->points   + n_base_points;
-
-      FT_Outline_Translate( &dummy, adx, ady );
-    }
-
-  Exit:
-    return error;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    T2_Parse_CharStrings                                               */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Parses a given Type 2 charstrings program.                         */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    decoder         :: The current Type 1 decoder.                     */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    charstring_base :: The base of the charstring stream.              */
-  /*                                                                       */
-  /*    charstring_len  :: The length in bytes of the charstring stream.   */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  FT_LOCAL_DEF
-  FT_Error  T2_Parse_CharStrings( T2_Decoder*  decoder,
-                                  FT_Byte*     charstring_base,
-                                  FT_Int       charstring_len )
-  {
-    FT_Error          error;
-    T2_Decoder_Zone*  zone;
-    FT_Byte*          ip;
-    FT_Byte*          limit;
-    T2_Builder*       builder = &decoder->builder;
-    FT_Outline*       outline;
-    FT_Pos            x, y;
-    FT_Fixed          seed;
-    FT_Fixed*         stack;
-
-
-    /* set default width */
-    decoder->num_hints  = 0;
-    decoder->read_width = 1;
-
-    /* compute random seed from stack address of parameter */
-    seed = (FT_Fixed)(char*)&seed           ^
-           (FT_Fixed)(char*)&decoder        ^
-           (FT_Fixed)(char*)&charstring_base;
-    seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFF;
-    if ( seed == 0 )
-      seed = 0x7384;
-
-    /* initialize the decoder */
-    decoder->top  = decoder->stack;
-    decoder->zone = decoder->zones;
-    zone          = decoder->zones;
-    stack         = decoder->top;
-
-    builder->path_begun = 0;
-
-    zone->base           = charstring_base;
-    limit = zone->limit  = charstring_base + charstring_len;
-    ip    = zone->cursor = zone->base;
-
-    error   = T2_Err_Ok;
-    outline = builder->current;
-
-    x = builder->pos_x;
-    y = builder->pos_y;
-
-    /* now, execute loop */
-    while ( ip < limit )
-    {
-      T2_Operator  op;
-      FT_Byte      v;
-
-
-      /********************************************************************/
-      /*                                                                  */
-      /* Decode operator or operand                                       */
-      /*                                                                  */
-      v = *ip++;
-      if ( v >= 32 || v == 28 )
-      {
-        FT_Int    shift = 16;
-        FT_Int32  val;
-
-
-        /* this is an operand, push it on the stack */
-        if ( v == 28 )
-        {
-          if ( ip + 1 >= limit )
-            goto Syntax_Error;
-          val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
-          ip += 2;
-        }
-        else if ( v < 247 )
-          val = (FT_Long)v - 139;
-        else if ( v < 251 )
-        {
-          if ( ip >= limit )
-            goto Syntax_Error;
-          val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
-        }
-        else if ( v < 255 )
-        {
-          if ( ip >= limit )
-            goto Syntax_Error;
-          val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
-        }
-        else
-        {
-          if ( ip + 3 >= limit )
-            goto Syntax_Error;
-          val = ( (FT_Int32)ip[0] << 24 ) |
-                ( (FT_Int32)ip[1] << 16 ) |
-                ( (FT_Int32)ip[2] <<  8 ) |
-                            ip[3];
-          ip    += 4;
-          shift  = 0;
-        }
-        if ( decoder->top - stack >= T2_MAX_OPERANDS )
-          goto Stack_Overflow;
-
-        val           <<= shift;
-        *decoder->top++ = val;
-
-#ifdef FT_DEBUG_LEVEL_TRACE
-        if ( !( val & 0xFFFF ) )
-          FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) ));
-        else
-          FT_TRACE4(( " %.2f", val/65536.0 ));
-#endif
-
-      }
-      else
-      {
-        FT_Fixed*  args     = decoder->top;
-        FT_Int     num_args = args - decoder->stack;
-        FT_Int     req_args;
-
-
-        /* find operator */
-        op = t2_op_unknown;
-
-        switch ( v )
-        {
-        case 1:
-          op = t2_op_hstem;
-          break;
-        case 3:
-          op = t2_op_vstem;
-          break;
-        case 4:
-          op = t2_op_vmoveto;
-          break;
-        case 5:
-          op = t2_op_rlineto;
-          break;
-        case 6:
-          op = t2_op_hlineto;
-          break;
-        case 7:
-          op = t2_op_vlineto;
-          break;
-        case 8:
-          op = t2_op_rrcurveto;
-          break;
-        case 10:
-          op = t2_op_callsubr;
-          break;
-        case 11:
-          op = t2_op_return;
-          break;
-        case 12:
-          {
-            if ( ip >= limit )
-              goto Syntax_Error;
-            v = *ip++;
-
-            switch ( v )
-            {
-            case 3:
-              op = t2_op_and;
-              break;
-            case 4:
-              op = t2_op_or;
-              break;
-            case 5:
-              op = t2_op_not;
-              break;
-            case 8:
-              op = t2_op_store;
-              break;
-            case 9:
-              op = t2_op_abs;
-              break;
-            case 10:
-              op = t2_op_add;
-              break;
-            case 11:
-              op = t2_op_sub;
-              break;
-            case 12:
-              op = t2_op_div;
-              break;
-            case 13:
-              op = t2_op_load;
-              break;
-            case 14:
-              op = t2_op_neg;
-              break;
-            case 15:
-              op = t2_op_eq;
-              break;
-            case 18:
-              op = t2_op_drop;
-              break;
-            case 20:
-              op = t2_op_put;
-              break;
-            case 21:
-              op = t2_op_get;
-              break;
-            case 22:
-              op = t2_op_ifelse;
-              break;
-            case 23:
-              op = t2_op_random;
-              break;
-            case 24:
-              op = t2_op_mul;
-              break;
-            case 26:
-              op = t2_op_sqrt;
-              break;
-            case 27:
-              op = t2_op_dup;
-              break;
-            case 28:
-              op = t2_op_exch;
-              break;
-            case 29:
-              op = t2_op_index;
-              break;
-            case 30:
-              op = t2_op_roll;
-              break;
-            case 34:
-              op = t2_op_hflex;
-              break;
-            case 35:
-              op = t2_op_flex;
-              break;
-            case 36:
-              op = t2_op_hflex1;
-              break;
-            case 37:
-              op = t2_op_flex1;
-              break;
-            default:
-              /* decrement ip for syntax error message */
-              ip--;
-            }
-          }
-          break;
-        case 14:
-          op = t2_op_endchar;
-          break;
-        case 16:
-          op = t2_op_blend;
-          break;
-        case 18:
-          op = t2_op_hstemhm;
-          break;
-        case 19:
-          op = t2_op_hintmask;
-          break;
-        case 20:
-          op = t2_op_cntrmask;
-          break;
-        case 21:
-          op = t2_op_rmoveto;
-          break;
-        case 22:
-          op = t2_op_hmoveto;
-          break;
-        case 23:
-          op = t2_op_vstemhm;
-          break;
-        case 24:
-          op = t2_op_rcurveline;
-          break;
-        case 25:
-          op = t2_op_rlinecurve;
-          break;
-        case 26:
-          op = t2_op_vvcurveto;
-          break;
-        case 27:
-          op = t2_op_hhcurveto;
-          break;
-        case 29:
-          op = t2_op_callgsubr;
-          break;
-        case 30:
-          op = t2_op_vhcurveto;
-          break;
-        case 31:
-          op = t2_op_hvcurveto;
-          break;
-        default:
-          ;
-        }
-        if ( op == t2_op_unknown )
-          goto Syntax_Error;
-
-        /* check arguments */
-        req_args = t2_argument_counts[op];
-        if ( req_args & T2_COUNT_CHECK_WIDTH )
-        {
-          args = stack;
-
-          if ( num_args > 0 && decoder->read_width )
-          {
-            /* If `nominal_width' is non-zero, the number is really a      */
-            /* difference against `nominal_width'.  Else, the number here  */
-            /* is truly a width, not a difference against `nominal_width'. */
-            /* If the font does not set `nominal_width', then              */
-            /* `nominal_width' defaults to zero, and so we can set         */
-            /* `glyph_width' to `nominal_width' plus number on the stack   */
-            /* -- for either case.                                         */
-
-            FT_Int set_width_ok;
-
-
-            switch ( op )
-            {
-            case t2_op_hmoveto:
-            case t2_op_vmoveto:
-              set_width_ok = num_args & 2;
-              break;
-
-            case t2_op_hstem:
-            case t2_op_vstem:
-            case t2_op_hstemhm:
-            case t2_op_vstemhm:
-            case t2_op_rmoveto:
-              set_width_ok = num_args & 1;
-              break;
-
-            case t2_op_endchar:
-              /* If there is a width specified for endchar, we either have */
-              /* 1 argument or 5 arguments.  We like to argue.             */
-              set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) );
-              break;
-
-            default:
-              set_width_ok = 0;
-              break;
-            }
-
-            if ( set_width_ok )
-            {
-              decoder->glyph_width = decoder->nominal_width +
-                                       ( stack[0] >> 16 );
-
-              /* Consumed an argument. */
-              num_args--;
-              args++;
-            }
-          }
-
-          decoder->read_width = 0;
-          req_args            = 0;
-        }
-
-        req_args &= 15;
-        if ( num_args < req_args )
-          goto Stack_Underflow;
-        args     -= req_args;
-        num_args -= req_args;
-
-        switch ( op )
-        {
-        case t2_op_hstem:
-        case t2_op_vstem:
-        case t2_op_hstemhm:
-        case t2_op_vstemhm:
-          /* if the number of arguments is not even, the first one */
-          /* is simply the glyph width, encoded as the difference  */
-          /* to nominalWidthX                                      */
-          FT_TRACE4(( op == t2_op_hstem   ? " hstem"   :
-                      op == t2_op_vstem   ? " vstem"   :
-                      op == t2_op_hstemhm ? " hstemhm" :
-                                            " vstemhm" ));
-          decoder->num_hints += num_args / 2;
-          args = stack;
-          break;
-
-        case t2_op_hintmask:
-        case t2_op_cntrmask:
-          FT_TRACE4(( op == t2_op_hintmask ? " hintmask"
-                                           : " cntrmask" ));
-
-          decoder->num_hints += num_args / 2;
-          ip += ( decoder->num_hints + 7 ) >> 3;
-          if ( ip >= limit )
-            goto Syntax_Error;
-          args = stack;
-          break;
-
-        case t2_op_rmoveto:
-          FT_TRACE4(( " rmoveto" ));
-
-          close_contour( builder );
-          builder->path_begun = 0;
-          x   += args[0];
-          y   += args[1];
-          args = stack;
-          break;
-
-        case t2_op_vmoveto:
-          FT_TRACE4(( " vmoveto" ));
-
-          close_contour( builder );
-          builder->path_begun = 0;
-          y   += args[0];
-          args = stack;
-          break;
-
-        case t2_op_hmoveto:
-          FT_TRACE4(( " hmoveto" ));
-
-          close_contour( builder );
-          builder->path_begun = 0;
-          x   += args[0];
-          args = stack;
-          break;
-
-        case t2_op_rlineto:
-          FT_TRACE4(( " rlineto" ));
-
-          if ( start_point ( builder, x, y )         ||
-               check_points( builder, num_args / 2 ) )
-            goto Memory_Error;
-
-          if ( num_args < 2 || num_args & 1 )
-            goto Stack_Underflow;
-
-          args = stack;
-          while ( args < decoder->top )
-          {
-            x += args[0];
-            y += args[1];
-            add_point( builder, x, y, 1 );
-            args += 2;
-          }
-          args = stack;
-          break;
-
-        case t2_op_hlineto:
-        case t2_op_vlineto:
-          {
-            FT_Int  phase = ( op == t2_op_hlineto );
-
-
-            FT_TRACE4(( op == t2_op_hlineto ? " hlineto"
-                                            : " vlineto" ));
-
-            if ( start_point ( builder, x, y )     ||
-                 check_points( builder, num_args ) )
-              goto Memory_Error;
-
-            args = stack;
-            while (args < decoder->top )
-            {
-              if ( phase )
-                x += args[0];
-              else
-                y += args[0];
-
-              if ( add_point1( builder, x, y ) )
-                goto Memory_Error;
-
-              args++;
-              phase ^= 1;
-            }
-            args = stack;
-          }
-          break;
-
-        case t2_op_rrcurveto:
-          FT_TRACE4(( " rrcurveto" ));
-
-          /* check number of arguments; must be a multiple of 6 */
-          if ( num_args % 6 != 0 )
-            goto Stack_Underflow;
-
-          if ( start_point ( builder, x, y )         ||
-               check_points( builder, num_args / 2 ) )
-            goto Memory_Error;
-
-          args = stack;
-          while ( args < decoder->top )
-          {
-            x += args[0];
-            y += args[1];
-            add_point( builder, x, y, 0 );
-            x += args[2];
-            y += args[3];
-            add_point( builder, x, y, 0 );
-            x += args[4];
-            y += args[5];
-            add_point( builder, x, y, 1 );
-            args += 6;
-          }
-          args = stack;
-          break;
-
-        case t2_op_vvcurveto:
-          FT_TRACE4(( " vvcurveto" ));
-
-          if ( start_point ( builder, x, y ) )
-            goto Memory_Error;
-
-          args = stack;
-          if ( num_args & 1 )
-          {
-            x += args[0];
-            args++;
-            num_args--;
-          }
-
-          if ( num_args % 4 != 0 )
-            goto Stack_Underflow;
-
-          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
-            goto Memory_Error;
-
-          while ( args < decoder->top )
-          {
-            y += args[0];
-            add_point( builder, x, y, 0 );
-            x += args[1];
-            y += args[2];
-            add_point( builder, x, y, 0 );
-            y += args[3];
-            add_point( builder, x, y, 1 );
-            args += 4;
-          }
-          args = stack;
-          break;
-
-        case t2_op_hhcurveto:
-          FT_TRACE4(( " hhcurveto" ));
-
-          if ( start_point ( builder, x, y ) )
-            goto Memory_Error;
-
-          args = stack;
-          if ( num_args & 1 )
-          {
-            y += args[0];
-            args++;
-            num_args--;
-          }
-
-          if ( num_args % 4 != 0 )
-            goto Stack_Underflow;
-
-          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
-            goto Memory_Error;
-
-          while ( args < decoder->top )
-          {
-            x += args[0];
-            add_point( builder, x, y, 0 );
-            x += args[1];
-            y += args[2];
-            add_point( builder, x, y, 0 );
-            x += args[3];
-            add_point( builder, x, y, 1 );
-            args += 4;
-          }
-          args = stack;
-          break;
-
-        case t2_op_vhcurveto:
-        case t2_op_hvcurveto:
-          {
-            FT_Int  phase;
-
-
-            FT_TRACE4(( op == t2_op_vhcurveto ? " vhcurveto"
-                                              : " hvcurveto" ));
-
-            if ( start_point ( builder, x, y ) )
-              goto Memory_Error;
-
-            args = stack;
-            if (num_args < 4 || ( num_args % 4 ) > 1 )
-              goto Stack_Underflow;
-
-            if ( check_points( builder, ( num_args / 4 ) * 3 ) )
-              goto Stack_Underflow;
-
-            phase = ( op == t2_op_hvcurveto );
-
-            while ( num_args >= 4 )
-            {
-              num_args -= 4;
-              if ( phase )
-              {
-                x += args[0];
-                add_point( builder, x, y, 0 );
-                x += args[1];
-                y += args[2];
-                add_point( builder, x, y, 0 );
-                y += args[3];
-                if ( num_args == 1 )
-                  x += args[4];
-                add_point( builder, x, y, 1 );
-              }
-              else
-              {
-                y += args[0];
-                add_point( builder, x, y, 0 );
-                x += args[1];
-                y += args[2];
-                add_point( builder, x, y, 0 );
-                x += args[3];
-                if ( num_args == 1 )
-                  y += args[4];
-                add_point( builder, x, y, 1 );
-              }
-              args  += 4;
-              phase ^= 1;
-            }
-            args = stack;
-          }
-          break;
-
-        case t2_op_rlinecurve:
-          {
-            FT_Int  num_lines = ( num_args - 6 ) / 2;
-
-
-            FT_TRACE4(( " rlinecurve" ));
-
-            if ( num_args < 8 || ( num_args - 6 ) & 1 )
-              goto Stack_Underflow;
-
-            if ( start_point( builder, x, y )           ||
-                 check_points( builder, num_lines + 3 ) )
-              goto Memory_Error;
-
-            args = stack;
-
-            /* first, add the line segments */
-            while ( num_lines > 0 )
-            {
-              x += args[0];
-              y += args[1];
-              add_point( builder, x, y, 1 );
-              args += 2;
-              num_lines--;
-            }
-
-            /* then the curve */
-            x += args[0];
-            y += args[1];
-            add_point( builder, x, y, 0 );
-            x += args[2];
-            y += args[3];
-            add_point( builder, x, y, 0 );
-            x += args[4];
-            y += args[5];
-            add_point( builder, x, y, 1 );
-            args = stack;
-          }
-          break;
-
-        case t2_op_rcurveline:
-          {
-            FT_Int  num_curves = ( num_args - 2 ) / 6;
-
-
-            FT_TRACE4(( " rcurveline" ));
-
-            if ( num_args < 8 || ( num_args - 2 ) % 6 )
-              goto Stack_Underflow;
-
-            if ( start_point ( builder, x, y )             ||
-                 check_points( builder, num_curves*3 + 2 ) )
-              goto Memory_Error;
-
-            args = stack;
-
-            /* first, add the curves */
-            while ( num_curves > 0 )
-            {
-              x += args[0];
-              y += args[1];
-              add_point( builder, x, y, 0 );
-              x += args[2];
-              y += args[3];
-              add_point( builder, x, y, 0 );
-              x += args[4];
-              y += args[5];
-              add_point( builder, x, y, 1 );
-              args += 6;
-              num_curves--;
-            }
-
-            /* then the final line */
-            x += args[0];
-            y += args[1];
-            add_point( builder, x, y, 1 );
-            args = stack;
-          }
-          break;
-
-        case t2_op_hflex1:
-          {
-            FT_Pos start_y;
-
-
-            FT_TRACE4(( " hflex1" ));
-
-            args = stack;
-
-            /* adding five more points; 4 control points, 1 on-curve point */
-            /* make sure we have enough space for the start point if it    */
-            /* needs to be added..                                         */
-            if ( start_point( builder, x, y ) ||
-                 check_points( builder, 6 )   )
-              goto Memory_Error;
-
-            /* Record the starting point's y postion for later use */
-            start_y = y;
-
-            /* first control point */
-            x += args[0];
-            y += args[1];
-            add_point( builder, x, y, 0 );
-
-            /* second control point */
-            x += args[2];
-            y += args[3];
-            add_point( builder, x, y, 0 );
-
-            /* join point; on curve, with y-value the same as the last */
-            /* control point's y-value                                 */
-            x += args[4];
-            add_point( builder, x, y, 1 );
-
-            /* third control point, with y-value the same as the join */
-            /* point's y-value                                        */
-            x += args[5];
-            add_point( builder, x, y, 0 );
-
-            /* fourth control point */
-            x += args[6];
-            y += args[7];
-            add_point( builder, x, y, 0 );
-
-            /* ending point, with y-value the same as the start   */
-            x += args[8];
-            y  = start_y;
-            add_point( builder, x, y, 1 );
-
-            args = stack;
-            break;
-          }
-
-        case t2_op_hflex:
-          {
-            FT_Pos start_y;
-
-
-            FT_TRACE4(( " hflex" ));
-
-            args = stack;
-
-            /* adding six more points; 4 control points, 2 on-curve points */
-            if ( start_point( builder, x, y ) ||
-                 check_points ( builder, 6 )  )
-              goto Memory_Error;
-
-            /* record the starting point's y-position for later use */
-            start_y = y;
-
-            /* first control point */
-            x += args[0];
-            add_point( builder, x, y, 0 );
-
-            /* second control point */
-            x += args[1];
-            y += args[2];
-            add_point( builder, x, y, 0 );
-
-            /* join point; on curve, with y-value the same as the last */
-            /* control point's y-value                                 */
-            x += args[3];
-            add_point( builder, x, y, 1 );
-
-            /* third control point, with y-value the same as the join */
-            /* point's y-value                                        */
-            x += args[4];
-            add_point( builder, x, y, 0 );
-
-            /* fourth control point */
-            x += args[5];
-            y  = start_y;
-            add_point( builder, x, y, 0 );
-
-            /* ending point, with y-value the same as the start point's */
-            /* y-value -- we don't add this point, though               */
-            x += args[6];
-            add_point( builder, x, y, 1 );
-
-            args = stack;
-            break;
-          }
-
-        case t2_op_flex1:
-          {
-            FT_Pos  start_x, start_y; /* record start x, y values for alter */
-                                      /* use                                */
-            FT_Int  dx = 0, dy = 0;   /* used in horizontal/vertical        */
-                                      /* algorithm below                    */
-            FT_Int  horizontal, count;
-
-
-            FT_TRACE4(( " flex1" ));
-
-            /* adding six more points; 4 control points, 2 on-curve points */
-            if ( start_point( builder, x, y ) ||
-                 check_points( builder, 6 )   )
-               goto Memory_Error;
-
-            /* record the starting point's x, y postion for later use */
-            start_x = x;
-            start_y = y;
-
-            /* XXX: figure out whether this is supposed to be a horizontal */
-            /*      or vertical flex; the Type 2 specification is vague... */
-
-            args = stack;
-
-            /* grab up to the last argument */
-            for ( count = 5; count > 0; count-- )
-            {
-              dx += args[0];
-              dy += args[1];
-              args += 2;
-            }
-
-            /* rewind */
-            args = stack;
-
-            if ( dx < 0 ) dx = -dx;
-            if ( dy < 0 ) dy = -dy;
-
-            /* strange test, but here it is... */
-            horizontal = ( dx > dy );
-
-            for ( count = 5; count > 0; count-- )
-            {
-              x += args[0];
-              y += args[1];
-              add_point( builder, x, y, (FT_Bool)( count == 3 ) );
-              args += 2;
-            }
-
-            /* is last operand an x- or y-delta? */
-            if ( horizontal )
-            {
-              x += args[0];
-              y  = start_y;
-            }
-            else
-            {
-              x  = start_x;
-              y += args[0];
-            }
-
-            add_point( builder, x, y, 1 );
-
-            args = stack;
-            break;
-           }
-
-        case t2_op_flex:
-          {
-            FT_UInt  count;
-
-
-            FT_TRACE4(( " flex" ));
-
-            if ( start_point( builder, x, y ) ||
-                 check_points( builder, 6 )   )
-              goto Memory_Error;
-
-            args = stack;
-            for ( count = 6; count > 0; count-- )
-            {
-              x += args[0];
-              y += args[1];
-              add_point( builder, x, y,
-                         (FT_Bool)( count == 3 || count == 0 ) );
-              args += 2;
-            }
-
-            args = stack;
-          }
-          break;
-
-        case t2_op_endchar:
-          FT_TRACE4(( " endchar" ));
-
-          /* We are going to emulate the seac operator. */
-          if ( num_args == 4 )
-          {
-            error = t2_operator_seac( decoder, args[0] >> 16, args[1] >> 16,
-                                               args[2] >> 16, args[3] >> 16 );
-            args += 4;
-          }
-
-          if ( !error )
-            error = T2_Err_Ok;
-
-          close_contour( builder );
-
-          /* add current outline to the glyph slot */
-          FT_GlyphLoader_Add( builder->loader );
-
-          /* return now! */
-          FT_TRACE4(( "\n\n" ));
-          return error;
-
-        case t2_op_abs:
-          FT_TRACE4(( " abs" ));
-
-          if ( args[0] < 0 )
-            args[0] = -args[0];
-          args++;
-          break;
-
-        case t2_op_add:
-          FT_TRACE4(( " add" ));
-
-          args[0] += args[1];
-          args++;
-          break;
-
-        case t2_op_sub:
-          FT_TRACE4(( " sub" ));
-
-          args[0] -= args[1];
-          args++;
-          break;
-
-        case t2_op_div:
-          FT_TRACE4(( " div" ));
-
-          args[0] = FT_DivFix( args[0], args[1] );
-          args++;
-          break;
-
-        case t2_op_neg:
-          FT_TRACE4(( " neg" ));
-
-          args[0] = -args[0];
-          args++;
-          break;
-
-        case t2_op_random:
-          {
-            FT_Fixed  rand;
-
-
-            FT_TRACE4(( " rand" ));
-
-            rand = seed;
-            if ( rand >= 0x8000 )
-              rand++;
-
-            args[0] = rand;
-            seed    = FT_MulFix( seed, 0x10000L - seed );
-            if ( seed == 0 )
-              seed += 0x2873;
-            args++;
-          }
-          break;
-
-        case t2_op_mul:
-          FT_TRACE4(( " mul" ));
-
-          args[0] = FT_MulFix( args[0], args[1] );
-          args++;
-          break;
-
-        case t2_op_sqrt:
-          FT_TRACE4(( " sqrt" ));
-
-          if ( args[0] > 0 )
-          {
-            FT_Int    count = 9;
-            FT_Fixed  root  = args[0];
-            FT_Fixed  new_root;
-
-
-            for (;;)
-            {
-              new_root = ( root + FT_DivFix(args[0],root) + 1 ) >> 1;
-              if ( new_root == root || count <= 0 )
-                break;
-              root = new_root;
-            }
-            args[0] = new_root;
-          }
-          else
-            args[0] = 0;
-          args++;
-          break;
-
-        case t2_op_drop:
-          /* nothing */
-          FT_TRACE4(( " drop" ));
-
-          break;
-
-        case t2_op_exch:
-          {
-            FT_Fixed  tmp;
-
-
-            FT_TRACE4(( " exch" ));
-
-            tmp     = args[0];
-            args[0] = args[1];
-            args[1] = tmp;
-            args   += 2;
-          }
-          break;
-
-        case t2_op_index:
-          {
-            FT_Int  index = args[0] >> 16;
-
-
-            FT_TRACE4(( " index" ));
-
-            if ( index < 0 )
-              index = 0;
-            else if ( index > num_args - 2 )
-              index = num_args - 2;
-            args[0] = args[-( index + 1 )];
-            args++;
-          }
-          break;
-
-        case t2_op_roll:
-          {
-            FT_Int  count = (FT_Int)( args[0] >> 16 );
-            FT_Int  index = (FT_Int)( args[1] >> 16 );
-
-
-            FT_TRACE4(( " roll" ));
-
-            if ( count <= 0 )
-              count = 1;
-
-            args -= count;
-            if ( args < stack )
-              goto Stack_Underflow;
-
-            if ( index >= 0 )
-            {
-              while ( index > 0 )
-              {
-                FT_Fixed  tmp = args[count - 1];
-                FT_Int    i;
-
-
-                for ( i = count - 2; i >= 0; i-- )
-                  args[i + 1] = args[i];
-                args[0] = tmp;
-                index--;
-              }
-            }
-            else
-            {
-              while ( index < 0 )
-              {
-                FT_Fixed  tmp = args[0];
-                FT_Int    i;
-
-
-                for ( i = 0; i < count - 1; i++ )
-                  args[i] = args[i + 1];
-                args[count - 1] = tmp;
-                index++;
-              }
-            }
-            args += count;
-          }
-          break;
-
-        case t2_op_dup:
-          FT_TRACE4(( " dup" ));
-
-          args[1] = args[0];
-          args++;
-          break;
-
-        case t2_op_put:
-          {
-            FT_Fixed  val   = args[0];
-            FT_Int    index = (FT_Int)( args[1] >> 16 );
-
-
-            FT_TRACE4(( " put" ));
-
-            if ( index >= 0 && index < decoder->len_buildchar )
-              decoder->buildchar[index] = val;
-          }
-          break;
-
-        case t2_op_get:
-          {
-            FT_Int   index = (FT_Int)( args[0] >> 16 );
-            FT_Fixed val   = 0;
-
-
-            FT_TRACE4(( " get" ));
-
-            if ( index >= 0 && index < decoder->len_buildchar )
-              val = decoder->buildchar[index];
-
-            args[0] = val;
-            args++;
-          }
-          break;
-
-        case t2_op_store:
-          FT_TRACE4(( " store "));
-
-          goto Unimplemented;
-
-        case t2_op_load:
-          FT_TRACE4(( " load" ));
-
-          goto Unimplemented;
-
-        case t2_op_and:
-          {
-            FT_Fixed  cond = args[0] && args[1];
-
-
-            FT_TRACE4(( " and" ));
-
-            args[0] = cond ? 0x10000L : 0;
-            args++;
-          }
-          break;
-
-        case t2_op_or:
-          {
-            FT_Fixed  cond = args[0] || args[1];
-
-
-            FT_TRACE4(( " or" ));
-
-            args[0] = cond ? 0x10000L : 0;
-            args++;
-          }
-          break;
-
-        case t2_op_eq:
-          {
-            FT_Fixed  cond = !args[0];
-
-
-            FT_TRACE4(( " eq" ));
-
-            args[0] = cond ? 0x10000L : 0;
-            args++;
-          }
-          break;
-
-        case t2_op_ifelse:
-          {
-            FT_Fixed  cond = (args[2] <= args[3]);
-
-
-            FT_TRACE4(( " ifelse" ));
-
-            if ( !cond )
-              args[0] = args[1];
-            args++;
-          }
-          break;
-
-        case t2_op_callsubr:
-          {
-            FT_UInt  index = (FT_UInt)( ( args[0] >> 16 ) +
-                                        decoder->locals_bias );
-
-
-            FT_TRACE4(( " callsubr(%d)", index ));
-
-            if ( index >= decoder->num_locals )
-            {
-              FT_ERROR(( "T2_Parse_CharStrings:" ));
-              FT_ERROR(( "  invalid local subr index\n" ));
-              goto Syntax_Error;
-            }
-
-            if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS )
-            {
-              FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" ));
-              goto Syntax_Error;
-            }
-
-            zone->cursor = ip;  /* save current instruction pointer */
-
-            zone++;
-            zone->base   = decoder->locals[index];
-            zone->limit  = decoder->locals[index+1];
-            zone->cursor = zone->base;
-
-            if ( !zone->base )
-            {
-              FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" ));
-              goto Syntax_Error;
-            }
-
-            decoder->zone = zone;
-            ip            = zone->base;
-            limit         = zone->limit;
-          }
-          break;
-
-        case t2_op_callgsubr:
-          {
-            FT_UInt  index = (FT_UInt)( ( args[0] >> 16 ) +
-                                        decoder->globals_bias );
-
-
-            FT_TRACE4(( " callgsubr(%d)", index ));
-
-            if ( index >= decoder->num_globals )
-            {
-              FT_ERROR(( "T2_Parse_CharStrings:" ));
-              FT_ERROR(( " invalid global subr index\n" ));
-              goto Syntax_Error;
-            }
-
-            if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS )
-            {
-              FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" ));
-              goto Syntax_Error;
-            }
-
-            zone->cursor = ip;  /* save current instruction pointer */
-
-            zone++;
-            zone->base   = decoder->globals[index];
-            zone->limit  = decoder->globals[index+1];
-            zone->cursor = zone->base;
-
-            if ( !zone->base )
-            {
-              FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" ));
-              goto Syntax_Error;
-            }
-
-            decoder->zone = zone;
-            ip            = zone->base;
-            limit         = zone->limit;
-          }
-          break;
-
-        case t2_op_return:
-          FT_TRACE4(( " return" ));
-
-          if ( decoder->zone <= decoder->zones )
-          {
-            FT_ERROR(( "T2_Parse_CharStrings: unexpected return\n" ));
-            goto Syntax_Error;
-          }
-
-          decoder->zone--;
-          zone  = decoder->zone;
-          ip    = zone->cursor;
-          limit = zone->limit;
-          break;
-
-        default:
-        Unimplemented:
-          FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
-
-          if ( ip[-1] == 12 )
-            FT_ERROR(( " %d", ip[0] ));
-          FT_ERROR(( "\n" ));
-
-          return T2_Err_Unimplemented_Feature;
-        }
-
-      decoder->top = args;
-
-      } /* general operator processing */
-
-    } /* while ip < limit */
-
-    FT_TRACE4(( "..end..\n\n" ));
-
-    return error;
-
-  Syntax_Error:
-    FT_TRACE4(( "T2_Parse_CharStrings: syntax error!" ));
-    return T2_Err_Invalid_File_Format;
-
-  Stack_Underflow:
-    FT_TRACE4(( "T2_Parse_CharStrings: stack underflow!" ));
-    return T2_Err_Too_Few_Arguments;
-
-  Stack_Overflow:
-    FT_TRACE4(( "T2_Parse_CharStrings: stack overflow!" ));
-    return T2_Err_Stack_Overflow;
-
-  Memory_Error:
-    return builder->error;
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /**********                                                      *********/
-  /**********                                                      *********/
-  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
-  /**********                                                      *********/
-  /**********    The following code is in charge of computing      *********/
-  /**********    the maximum advance width of the font.  It        *********/
-  /**********    quickly processes each glyph charstring to        *********/
-  /**********    extract the value from either a `sbw' or `seac'   *********/
-  /**********    operator.                                         *********/
-  /**********                                                      *********/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-#if 0 /* unused until we support pure CFF fonts */
-
-
-  FT_LOCAL_DEF
-  FT_Error  T2_Compute_Max_Advance( TT_Face  face,
-                                    FT_Int*  max_advance )
-  {
-    FT_Error    error = 0;
-    T2_Decoder  decoder;
-    FT_Int      glyph_index;
-    CFF_Font*   cff = (CFF_Font*)face->other;
-
-
-    *max_advance = 0;
-
-    /* Initialize load decoder */
-    T2_Init_Decoder( &decoder, face, 0, 0 );
-
-    decoder.builder.metrics_only = 1;
-    decoder.builder.load_points  = 0;
-
-    /* For each glyph, parse the glyph charstring and extract */
-    /* the advance width.                                     */
-    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
-          glyph_index++ )
-    {
-      FT_Byte*  charstring;
-      FT_ULong  charstring_len;
-
-
-      /* now get load the unscaled outline */
-      error = T2_Access_Element( &cff->charstrings_index, glyph_index,
-                                 &charstring, &charstring_len );
-      if ( !error )
-      {
-        T2_Prepare_Decoder( &decoder, glyph_index );
-        error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
-
-        T2_Forget_Element( &cff->charstrings_index, &charstring );
-      }
-
-      /* ignore the error if one has occurred -- skip to next glyph */
-      error = 0;
-    }
-
-    *max_advance = decoder.builder.advance.x;
-
-    return T2_Err_Ok;
-  }
-
-
-#endif /* 0 */
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /**********                                                      *********/
-  /**********                                                      *********/
-  /**********               UNHINTED GLYPH LOADER                  *********/
-  /**********                                                      *********/
-  /**********    The following code is in charge of loading a      *********/
-  /**********    single outline.  It completely ignores hinting    *********/
-  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
-  /**********                                                      *********/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-  FT_LOCAL_DEF
-  FT_Error  T2_Load_Glyph( T2_GlyphSlot  glyph,
-                           T2_Size       size,
-                           FT_Int        glyph_index,
-                           FT_Int        load_flags )
-  {
-    FT_Error    error;
-    T2_Decoder  decoder;
-    TT_Face     face = (TT_Face)glyph->root.face;
-    FT_Bool     hinting;
-    CFF_Font*   cff = (CFF_Font*)face->extra.data;
-
-    FT_Matrix   font_matrix;
-    FT_Vector   font_offset;
-
-
-    if ( load_flags & FT_LOAD_NO_RECURSE )
-      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
-
-    glyph->x_scale = 0x10000L;
-    glyph->y_scale = 0x10000L;
-    if ( size )
-    {
-      glyph->x_scale = size->metrics.x_scale;
-      glyph->y_scale = size->metrics.y_scale;
-    }
-
-    glyph->root.outline.n_points   = 0;
-    glyph->root.outline.n_contours = 0;
-
-    hinting = ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
-              ( load_flags & FT_LOAD_NO_HINTING ) == 0;
-
-    glyph->root.format = ft_glyph_format_outline;  /* by default */
-
-    {
-      FT_Byte*  charstring;
-      FT_ULong  charstring_len;
-
-
-      T2_Init_Decoder( &decoder, face, size, glyph );
-
-      decoder.builder.no_recurse =
-        (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
-
-      /* now load the unscaled outline */
-      error = CFF_Access_Element( &cff->charstrings_index, glyph_index,
-                                  &charstring, &charstring_len );
-      if ( !error )
-      {
-        T2_Prepare_Decoder( &decoder, glyph_index );
-        error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
-
-        CFF_Forget_Element( &cff->charstrings_index, &charstring );
-      }
-
-      /* save new glyph tables */
-      T2_Done_Builder( &decoder.builder );
-    }
-
-    font_matrix = cff->top_font.font_dict.font_matrix;
-    font_offset = cff->top_font.font_dict.font_offset;
-
-    /* Now, set the metrics -- this is rather simple, as   */
-    /* the left side bearing is the xMin, and the top side */
-    /* bearing the yMax.                                   */
-    if ( !error )
-    {
-      /* For composite glyphs, return only left side bearing and */
-      /* advance width.                                          */
-      if ( load_flags & FT_LOAD_NO_RECURSE )
-      {
-        FT_Slot_Internal  internal = glyph->root.internal;
-        
-
-        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
-        glyph->root.metrics.horiAdvance  = decoder.glyph_width;
-        internal->glyph_matrix           = font_matrix;
-        internal->glyph_delta            = font_offset;
-        internal->glyph_transformed      = 1;
-      }
-      else
-      {
-        FT_BBox            cbox;
-        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
-
-
-        /* copy the _unscaled_ advance width */
-        metrics->horiAdvance                    = decoder.glyph_width;
-        glyph->root.linearHoriAdvance           = decoder.glyph_width;
-        glyph->root.internal->glyph_transformed = 0;
-
-        /* make up vertical metrics */
-        metrics->vertBearingX = 0;
-        metrics->vertBearingY = 0;
-        metrics->vertAdvance  = 0;
-
-        glyph->root.linearVertAdvance = 0;
-
-        glyph->root.format = ft_glyph_format_outline;
-
-        glyph->root.outline.flags = 0;
-        if ( size && size->metrics.y_ppem < 24 )
-          glyph->root.outline.flags |= ft_outline_high_precision;
-
-        glyph->root.outline.flags |= ft_outline_reverse_fill;
-
-        /* apply the font matrix */
-        FT_Outline_Transform( &glyph->root.outline, &font_matrix );
-
-        FT_Outline_Translate( &glyph->root.outline,
-                              font_offset.x,
-                              font_offset.y );
-
-        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
-        {
-          /* scale the outline and the metrics */
-          FT_Int       n;
-          FT_Outline*  cur     = &glyph->root.outline;
-          FT_Vector*   vec     = cur->points;
-          FT_Fixed     x_scale = glyph->x_scale;
-          FT_Fixed     y_scale = glyph->y_scale;
-
-
-          /* First of all, scale the points */
-          for ( n = cur->n_points; n > 0; n--, vec++ )
-          {
-            vec->x = FT_MulFix( vec->x, x_scale );
-            vec->y = FT_MulFix( vec->y, y_scale );
-          }
-
-          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
-
-          /* Then scale the metrics */
-          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
-          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
-
-          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
-          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
-        }
-
-        /* compute the other metrics */
-        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
-
-        /* grid fit the bounding box if necessary */
-        if ( hinting )
-        {
-          cbox.xMin &= -64;
-          cbox.yMin &= -64;
-          cbox.xMax  = ( cbox.xMax + 63 ) & -64;
-          cbox.yMax  = ( cbox.yMax + 63 ) & -64;
-        }
-
-        metrics->width  = cbox.xMax - cbox.xMin;
-        metrics->height = cbox.yMax - cbox.yMin;
-
-        metrics->horiBearingX = cbox.xMin;
-        metrics->horiBearingY = cbox.yMax;
-      }
-    }
-
-    return error;
-  }
-
-
-/* END */