text:
/****************************************************************************
 *
 * pfrgload.c
 *
 *   FreeType PFR glyph loader (body).
 *
 * Copyright (C) 2002-2020 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 "pfrgload.h"
#include "pfrsbit.h"
#include "pfrload.h"            /* for macro definitions */
#include FT_INTERNAL_DEBUG_H

#include "pfrerror.h"

#undef  FT_COMPONENT
#define FT_COMPONENT  pfr

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                      PFR GLYPH BUILDER                        *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  FT_LOCAL_DEF( void )
  pfr_glyph_init( PFR_Glyph       glyph,
                  FT_GlyphLoader  loader )
  {
    FT_ZERO( glyph );

    glyph->loader     = loader;
    glyph->path_begun = 0;

    FT_GlyphLoader_Rewind( loader );
  }

  FT_LOCAL_DEF( void )
  pfr_glyph_done( PFR_Glyph  glyph )
  {
    FT_Memory  memory = glyph->loader->memory;

    FT_FREE( glyph->x_control );
    glyph->y_control = NULL;

    glyph->max_xy_control = 0;
#if 0
    glyph->num_x_control  = 0;
    glyph->num_y_control  = 0;
#endif

    FT_FREE( glyph->subs );

    glyph->max_subs = 0;
    glyph->num_subs = 0;

    glyph->loader     = NULL;
    glyph->path_begun = 0;
  }

  /* close current contour, if any */
  static void
  pfr_glyph_close_contour( PFR_Glyph  glyph )
  {
    FT_GlyphLoader  loader  = glyph->loader;
    FT_Outline*     outline = &loader->current.outline;
    FT_Int          last, first;

    if ( !glyph->path_begun )
      return;

    /* compute first and last point indices in current glyph outline */
    last  = outline->n_points - 1;
    first = 0;
    if ( outline->n_contours > 0 )
      first = outline->contours[outline->n_contours - 1];

    /* if the last point falls on the same location as the first one */
    /* we need to delete it                                          */
    if ( last > first )
    {
      FT_Vector*  p1 = outline->points + first;
      FT_Vector*  p2 = outline->points + last;

      if ( p1->x == p2->x && p1->y == p2->y )
      {
        outline->n_points--;
        last--;
      }
    }

    /* don't add empty contours */
    if ( last >= first )
      outline->contours[outline->n_contours++] = (short)last;

    glyph->path_begun = 0;
  }

  /* reset glyph to start the loading of a new glyph */
  static void
  pfr_glyph_start( PFR_Glyph  glyph )
  {
    glyph->path_begun = 0;
  }

  static FT_Error
  pfr_glyph_line_to( PFR_Glyph   glyph,
                     FT_Vector*  to )
  {
    FT_GlyphLoader  loader  = glyph->loader;
    FT_Outline*     outline = &loader->current.outline;
    FT_Error        error;

    /* check that we have begun a new path */
    if ( !glyph->path_begun )
    {
      error = FT_THROW( Invalid_Table );
      FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
      goto Exit;
    }

    error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 );
    if ( !error )
    {
      FT_Int  n = outline->n_points;

      outline->points[n] = *to;
      outline->tags  [n] = FT_CURVE_TAG_ON;

      outline->n_points++;
    }

  Exit:
    return error;
  }

  static FT_Error
  pfr_glyph_curve_to( PFR_Glyph   glyph,
                      FT_Vector*  control1,
                      FT_Vector*  control2,
                      FT_Vector*  to )
  {
    FT_GlyphLoader  loader  = glyph->loader;
    FT_Outline*     outline = &loader->current.outline;
    FT_Error        error;

    /* check that we have begun a new path */
    if ( !glyph->path_begun )
    {
      error = FT_THROW( Invalid_Table );
      FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
      goto Exit;
    }

    error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
    if ( !error )
    {
      FT_Vector*  vec = outline->points         + outline->n_points;
      FT_Byte*    tag = (FT_Byte*)outline->tags + outline->n_points;

      vec[0] = *control1;
      vec[1] = *control2;
      vec[2] = *to;
      tag[0] = FT_CURVE_TAG_CUBIC;
      tag[1] = FT_CURVE_TAG_CUBIC;
      tag[2] = FT_CURVE_TAG_ON;

      outline->n_points = (FT_Short)( outline->n_points + 3 );
    }

  Exit:
    return error;
  }

  static FT_Error
  pfr_glyph_move_to( PFR_Glyph   glyph,
                     FT_Vector*  to )
  {
    FT_GlyphLoader  loader  = glyph->loader;
    FT_Error        error;

    /* close current contour if any */
    pfr_glyph_close_contour( glyph );

    /* indicate that a new contour has started */
    glyph->path_begun = 1;

    /* check that there is space for a new contour and a new point */
    error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 1 );
    if ( !error )
    {
      /* add new start point */
      error = pfr_glyph_line_to( glyph, to );
    }

    return error;
  }

  static void
  pfr_glyph_end( PFR_Glyph  glyph )
  {
    /* close current contour if any */
    pfr_glyph_close_contour( glyph );

    /* merge the current glyph into the stack */
    FT_GlyphLoader_Add( glyph->loader );
  }

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                      PFR GLYPH LOADER                         *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /* load a simple glyph */
  static FT_Error
  pfr_glyph_load_simple( PFR_Glyph  glyph,
                         FT_Byte*   p,
                         FT_Byte*   limit )
  {
    FT_Error   error  = FT_Err_Ok;
    FT_Memory  memory = glyph->loader->memory;
    FT_UInt    flags, x_count, y_count, i, count, mask;
    FT_Int     x;

    PFR_CHECK( 1 );
    flags = PFR_NEXT_BYTE( p );

    /* test for composite glyphs */
    if ( flags & PFR_GLYPH_IS_COMPOUND )
      goto Failure;

    x_count = 0;
    y_count = 0;

    if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )
    {
      PFR_CHECK( 1 );
      count   = PFR_NEXT_BYTE( p );
      x_count = count & 15;
      y_count = count >> 4;
    }
    else
    {
      if ( flags & PFR_GLYPH_XCOUNT )
      {
        PFR_CHECK( 1 );
        x_count = PFR_NEXT_BYTE( p );
      }

      if ( flags & PFR_GLYPH_YCOUNT )
      {
        PFR_CHECK( 1 );
        y_count = PFR_NEXT_BYTE( p );
      }
    }

    count = x_count + y_count;

    /* re-allocate array when necessary */
    if ( count > glyph->max_xy_control )
    {
      FT_UInt  new_max = FT_PAD_CEIL( count, 8 );

      if ( FT_RENEW_ARRAY( glyph->x_control,
                           glyph->max_xy_control,
                           new_max ) )
        goto Exit;

      glyph->max_xy_control = new_max;
    }

    glyph->y_control = glyph->x_control + x_count;

    mask = 0;
    x    = 0;

    for ( i = 0; i < count; i++ )
    {
      if ( ( i & 7 ) == 0 )
      {
        PFR_CHECK( 1 );
        mask = PFR_NEXT_BYTE( p );
      }

      if ( mask & 1 )
      {
        PFR_CHECK( 2 );
        x = PFR_NEXT_SHORT( p );
      }
      else
      {
        PFR_CHECK( 1 );
        x += PFR_NEXT_BYTE( p );
      }

      glyph->x_control[i] = x;

      mask >>= 1;
    }

    /* XXX: we ignore the secondary stroke and edge definitions */
    /*      since we don't support native PFR hinting           */
    /*                                                          */
    if ( flags & PFR_GLYPH_SINGLE_EXTRA_ITEMS )
    {
      error = pfr_extra_items_skip( &p, limit );
      if ( error )
        goto Exit;
    }

    pfr_glyph_start( glyph );

    /* now load a simple glyph */
    {
      FT_Vector   pos[4];
      FT_Vector*  cur;

      pos[0].x = pos[0].y = 0;
      pos[3]   = pos[0];

      for (;;)
      {
        FT_UInt  format, format_low, args_format = 0, args_count, n;

        /****************************************************************
         * read instruction
         */
        PFR_CHECK( 1 );
        format     = PFR_NEXT_BYTE( p );
        format_low = format & 15;

        switch ( format >> 4 )
        {
        case 0:                                               /* end glyph */
          FT_TRACE6(( "- end glyph" ));
          args_count = 0;
          break;

        case 1:                                  /* general line operation */
          FT_TRACE6(( "- general line" ));
          goto Line1;

        case 4:                                 /* move to inside contour  */
          FT_TRACE6(( "- move to inside" ));
          goto Line1;

        case 5:                                 /* move to outside contour */
          FT_TRACE6(( "- move to outside" ));
        Line1:
          args_format = format_low;
          args_count  = 1;
          break;

        case 2:                                      /* horizontal line to */
          FT_TRACE6(( "- horizontal line to cx.%d", format_low ));
          if ( format_low >= x_count )
            goto Failure;
          pos[0].x   = glyph->x_control[format_low];
          pos[0].y   = pos[3].y;
          pos[3]     = pos[0];
          args_count = 0;
          break;

        case 3:                                        /* vertical line to */
          FT_TRACE6(( "- vertical line to cy.%d", format_low ));
          if ( format_low >= y_count )
            goto Failure;
          pos[0].x   = pos[3].x;
          pos[0].y   = glyph->y_control[format_low];
          pos[3]     = pos[0];
          args_count = 0;
          break;

        case 6:                            /* horizontal to vertical curve */
          FT_TRACE6(( "- hv curve " ));
          args_format = 0xB8E;
          args_count  = 3;
          break;

        case 7:                            /* vertical to horizontal curve */
          FT_TRACE6(( "- vh curve" ));
          args_format = 0xE2B;
          args_count  = 3;
          break;

        default:                                       /* general curve to */
          FT_TRACE6(( "- general curve" ));
          args_count  = 4;
          args_format = format_low;
        }

        /************************************************************
         * now read arguments
         */
        cur = pos;
        for ( n = 0; n < args_count; n++ )
        {
          FT_UInt  idx;
          FT_Int   delta;

          /* read the X argument */
          switch ( args_format & 3 )
          {
          case 0:                           /* 8-bit index */
            PFR_CHECK( 1 );
            idx = PFR_NEXT_BYTE( p );
            if ( idx >= x_count )
              goto Failure;
            cur->x = glyph->x_control[idx];
            FT_TRACE7(( " cx#%d", idx ));
            break;

          case 1:                           /* 16-bit absolute value */
            PFR_CHECK( 2 );
            cur->x = PFR_NEXT_SHORT( p );
            FT_TRACE7(( " x.%d", cur->x ));
            break;

          case 2:                           /* 8-bit delta */
            PFR_CHECK( 1 );
            delta  = PFR_NEXT_INT8( p );
            cur->x = pos[3].x + delta;
            FT_TRACE7(( " dx.%d", delta ));
            break;

          default:
            FT_TRACE7(( " |" ));
            cur->x = pos[3].x;
          }

          /* read the Y argument */
          switch ( ( args_format >> 2 ) & 3 )
          {
          case 0:                           /* 8-bit index */
            PFR_CHECK( 1 );
            idx  = PFR_NEXT_BYTE( p );
            if ( idx >= y_count )
              goto Failure;
            cur->y = glyph->y_control[idx];
            FT_TRACE7(( " cy#%d", idx ));
            break;

          case 1:                           /* 16-bit absolute value */
            PFR_CHECK( 2 );
            cur->y = PFR_NEXT_SHORT( p );
            FT_TRACE7(( " y.%d", cur->y ));
            break;

          case 2:                           /* 8-bit delta */
            PFR_CHECK( 1 );
            delta  = PFR_NEXT_INT8( p );
            cur->y = pos[3].y + delta;
            FT_TRACE7(( " dy.%d", delta ));
            break;

          default:
            FT_TRACE7(( " -" ));
            cur->y = pos[3].y;
          }

          /* read the additional format flag for the general curve */
          if ( n == 0 && args_count == 4 )
          {
            PFR_CHECK( 1 );
            args_format = PFR_NEXT_BYTE( p );
            args_count--;
          }
          else
            args_format >>= 4;

          /* save the previous point */
          pos[3] = cur[0];
          cur++;
        }

        FT_TRACE7(( "\n" ));

        /************************************************************
         * finally, execute instruction
         */
        switch ( format >> 4 )
        {
        case 0:                                       /* end glyph => EXIT */
          pfr_glyph_end( glyph );
          goto Exit;

        case 1:                                         /* line operations */
        case 2:
        case 3:
          error = pfr_glyph_line_to( glyph, pos );
          goto Test_Error;

        case 4:                                 /* move to inside contour  */
        case 5:                                 /* move to outside contour */
          error = pfr_glyph_move_to( glyph, pos );
          goto Test_Error;

        default:                                       /* curve operations */
          error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 );

        Test_Error:  /* test error condition */
          if ( error )
            goto Exit;
        }
      } /* for (;;) */
    }

  Exit:
    return error;

  Failure:
  Too_Short:
    error = FT_THROW( Invalid_Table );
    FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" ));
    goto Exit;
  }

  /* load a composite/compound glyph */
  static FT_Error
  pfr_glyph_load_compound( PFR_Glyph  glyph,
                           FT_Byte*   p,
                           FT_Byte*   limit )
  {
    FT_Error        error  = FT_Err_Ok;
    FT_GlyphLoader  loader = glyph->loader;
    FT_Memory       memory = loader->memory;
    PFR_SubGlyph    subglyph;
    FT_UInt         flags, i, count, org_count;
    FT_Int          x_pos, y_pos;

    PFR_CHECK( 1 );
    flags = PFR_NEXT_BYTE( p );

    /* test for composite glyphs */
    if ( !( flags & PFR_GLYPH_IS_COMPOUND ) )
      goto Failure;

    count = flags & 0x3F;

    /* ignore extra items when present */
    /*                                 */
    if ( flags & PFR_GLYPH_COMPOUND_EXTRA_ITEMS )
    {
      error = pfr_extra_items_skip( &p, limit );
      if ( error )
        goto Exit;
    }

    /* we can't rely on the FT_GlyphLoader to load sub-glyphs, because   */
    /* the PFR format is dumb, using direct file offsets to point to the */
    /* sub-glyphs (instead of glyph indices).  Sigh.                     */
    /*                                                                   */
    /* For now, we load the list of sub-glyphs into a different array    */
    /* but this will prevent us from using the auto-hinter at its best   */
    /* quality.                                                          */
    /*                                                                   */
    org_count = glyph->num_subs;

    if ( org_count + count > glyph->max_subs )
    {
      FT_UInt  new_max = ( org_count + count + 3 ) & (FT_UInt)-4;

      /* we arbitrarily limit the number of subglyphs */
      /* to avoid endless recursion                   */
      if ( new_max > 64 )
      {
        error = FT_THROW( Invalid_Table );
        FT_ERROR(( "pfr_glyph_load_compound:"
                   " too many compound glyphs components\n" ));
        goto Exit;
      }

      if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )
        goto Exit;

      glyph->max_subs = new_max;
    }

    subglyph = glyph->subs + org_count;

    for ( i = 0; i < count; i++, subglyph++ )
    {
      FT_UInt  format;

      x_pos = 0;
      y_pos = 0;

      PFR_CHECK( 1 );
      format = PFR_NEXT_BYTE( p );

      /* read scale when available */
      subglyph->x_scale = 0x10000L;
      if ( format & PFR_SUBGLYPH_XSCALE )
      {
        PFR_CHECK( 2 );
        subglyph->x_scale = PFR_NEXT_SHORT( p ) * 16;
      }

      subglyph->y_scale = 0x10000L;
      if ( format & PFR_SUBGLYPH_YSCALE )
      {
        PFR_CHECK( 2 );
        subglyph->y_scale = PFR_NEXT_SHORT( p ) * 16;
      }

      /* read offset */
      switch ( format & 3 )
      {
      case 1:
        PFR_CHECK( 2 );
        x_pos = PFR_NEXT_SHORT( p );
        break;

      case 2:
        PFR_CHECK( 1 );
        x_pos += PFR_NEXT_INT8( p );
        break;

      default:
        ;
      }

      switch ( ( format >> 2 ) & 3 )
      {
      case 1:
        PFR_CHECK( 2 );
        y_pos = PFR_NEXT_SHORT( p );
        break;

      case 2:
        PFR_CHECK( 1 );
        y_pos += PFR_NEXT_INT8( p );
        break;

      default:
        ;
      }

      subglyph->x_delta = x_pos;
      subglyph->y_delta = y_pos;

      /* read glyph position and size now */
      if ( format & PFR_SUBGLYPH_2BYTE_SIZE )
      {
        PFR_CHECK( 2 );
        subglyph->gps_size = PFR_NEXT_USHORT( p );
      }
      else
      {
        PFR_CHECK( 1 );
        subglyph->gps_size = PFR_NEXT_BYTE( p );
      }

      if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )
      {
        PFR_CHECK( 3 );
        subglyph->gps_offset = PFR_NEXT_ULONG( p );
      }
      else
      {
        PFR_CHECK( 2 );
        subglyph->gps_offset = PFR_NEXT_USHORT( p );
      }

      glyph->num_subs++;
    }

  Exit:
    return error;

  Failure:
  Too_Short:
    error = FT_THROW( Invalid_Table );
    FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" ));
    goto Exit;
  }

  static FT_Error
  pfr_glyph_load_rec( PFR_Glyph  glyph,
                      FT_Stream  stream,
                      FT_ULong   gps_offset,
                      FT_ULong   offset,
                      FT_ULong   size )
  {
    FT_Error  error;
    FT_Byte*  p;
    FT_Byte*  limit;

    if ( FT_STREAM_SEEK( gps_offset + offset ) ||
         FT_FRAME_ENTER( size )                )
      goto Exit;

    p     = (FT_Byte*)stream->cursor;
    limit = p + size;

    if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )
    {
      FT_UInt         n, old_count, count;
      FT_GlyphLoader  loader = glyph->loader;
      FT_Outline*     base   = &loader->base.outline;

      old_count = glyph->num_subs;

      /* this is a compound glyph - load it */
      error = pfr_glyph_load_compound( glyph, p, limit );

      FT_FRAME_EXIT();

      if ( error )
        goto Exit;

      count = glyph->num_subs - old_count;

      FT_TRACE4(( "compound glyph with %d element%s (offset %lu):\n",
                  count,
                  count == 1 ? "" : "s",
                  offset ));

      /* now, load each individual glyph */
      for ( n = 0; n < count; n++ )
      {
        FT_Int        i, old_points, num_points;
        PFR_SubGlyph  subglyph;

        FT_TRACE4(( "  subglyph %d:\n", n ));

        subglyph   = glyph->subs + old_count + n;
        old_points = base->n_points;

        error = pfr_glyph_load_rec( glyph, stream, gps_offset,
                                    subglyph->gps_offset,
                                    subglyph->gps_size );
        if ( error )
          break;

        /* note that `glyph->subs' might have been re-allocated */
        subglyph   = glyph->subs + old_count + n;
        num_points = base->n_points - old_points;

        /* translate and eventually scale the new glyph points */
        if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )
        {
          FT_Vector*  vec = base->points + old_points;

          for ( i = 0; i < num_points; i++, vec++ )
          {
            vec->x = FT_MulFix( vec->x, subglyph->x_scale ) +
                       subglyph->x_delta;
            vec->y = FT_MulFix( vec->y, subglyph->y_scale ) +
                       subglyph->y_delta;
          }
        }
        else
        {
          FT_Vector*  vec = loader->base.outline.points + old_points;

          for ( i = 0; i < num_points; i++, vec++ )
          {
            vec->x += subglyph->x_delta;
            vec->y += subglyph->y_delta;
          }
        }

        /* proceed to next sub-glyph */
      }

      FT_TRACE4(( "end compound glyph with %d element%s\n",
                  count,
                  count == 1 ? "" : "s" ));
    }
    else
    {
      FT_TRACE4(( "simple glyph (offset %lu)\n", offset ));

      /* load a simple glyph */
      error = pfr_glyph_load_simple( glyph, p, limit );

      FT_FRAME_EXIT();
    }

  Exit:
    return error;
  }

  FT_LOCAL_DEF( FT_Error )
  pfr_glyph_load( PFR_Glyph  glyph,
                  FT_Stream  stream,
                  FT_ULong   gps_offset,
                  FT_ULong   offset,
                  FT_ULong   size )
  {
    /* initialize glyph loader */
    FT_GlyphLoader_Rewind( glyph->loader );

    glyph->num_subs = 0;

    /* load the glyph, recursively when needed */
    return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );
  }

/* END */


text:
/****************************************************************************
 *
 * pshints.h
 *
 *   Adobe's code for handling CFF hints (body).
 *
 * Copyright 2007-2013 Adobe Systems Incorporated.
 *
 * This software, and all works of authorship, whether in source or
 * object code form as indicated by the copyright notice(s) included
 * herein (collectively, the "Work") is made available, and may only be
 * used, modified, and distributed under the FreeType Project License,
 * LICENSE.TXT.  Additionally, subject to the terms and conditions of the
 * FreeType Project License, each contributor to the Work hereby grants
 * to any individual or legal entity exercising permissions granted by
 * the FreeType Project License and this section (hereafter, "You" or
 * "Your") a perpetual, worldwide, non-exclusive, no-charge,
 * royalty-free, irrevocable (except as stated in this section) patent
 * license to make, have made, use, offer to sell, sell, import, and
 * otherwise transfer the Work, where such license applies only to those
 * patent claims licensable by such contributor that are necessarily
 * infringed by their contribution(s) alone or by combination of their
 * contribution(s) with the Work to which such contribution(s) was
 * submitted.  If You institute patent litigation against any entity
 * (including a cross-claim or counterclaim in a lawsuit) alleging that
 * the Work or a contribution incorporated within the Work constitutes
 * direct or contributory patent infringement, then any patent licenses
 * granted to You under this License for that Work shall terminate as of
 * the date such litigation is filed.
 *
 * By using, modifying, or distributing the Work you indicate that you
 * have read and understood the terms and conditions of the
 * FreeType Project License as well as those provided in this section,
 * and you accept them fully.
 *
 */

#ifndef PSHINT_H_
#define PSHINT_H_

FT_BEGIN_HEADER

  enum
  {
    CF2_MAX_HINTS = 96    /* maximum # of hints */
  };

  /*
   * A HintMask object stores a bit mask that specifies which hints in the
   * charstring are active at a given time.  Hints in CFF must be declared
   * at the start, before any drawing operators, with horizontal hints
   * preceding vertical hints.  The HintMask is ordered the same way, with
   * horizontal hints immediately followed by vertical hints.  Clients are
   * responsible for knowing how many of each type are present.
   *
   * The maximum total number of hints is 96, as specified by the CFF
   * specification.
   *
   * A HintMask is built 0 or more times while interpreting a charstring, by
   * the HintMask operator.  There is only one HintMask, but it is built or
   * rebuilt each time there is a hint substitution (HintMask operator) in
   * the charstring.  A default HintMask with all bits set is built if there
   * has been no HintMask operator prior to the first drawing operator.
   *
   */

  typedef struct  CF2_HintMaskRec_
  {
    FT_Error*  error;

    FT_Bool  isValid;
    FT_Bool  isNew;

    size_t  bitCount;
    size_t  byteCount;

    FT_Byte  mask[( CF2_MAX_HINTS + 7 ) / 8];

  } CF2_HintMaskRec, *CF2_HintMask;

  typedef struct  CF2_StemHintRec_
  {
    FT_Bool  used;     /* DS positions are valid         */

    CF2_Fixed  min;    /* original character space value */
    CF2_Fixed  max;

    CF2_Fixed  minDS;  /* DS position after first use    */
    CF2_Fixed  maxDS;

  } CF2_StemHintRec, *CF2_StemHint;

  /*
   * A HintMap object stores a piecewise linear function for mapping
   * y-coordinates from character space to device space, providing
   * appropriate pixel alignment to stem edges.
   *
   * The map is implemented as an array of `CF2_Hint' elements, each
   * representing an edge.  When edges are paired, as from stem hints, the
   * bottom edge must immediately precede the top edge in the array.
   * Element character space AND device space positions must both increase
   * monotonically in the array.  `CF2_Hint' elements are also used as
   * parameters to `cf2_blues_capture'.
   *
   * The `cf2_hintmap_build' method must be called before any drawing
   * operation (beginning with a Move operator) and at each hint
   * substitution (HintMask operator).
   *
   * The `cf2_hintmap_map' method is called to transform y-coordinates at
   * each drawing operation (move, line, curve).
   *
   */

  /* TODO: make this a CF2_ArrStack and add a deep copy method */
  enum
  {
    CF2_MAX_HINT_EDGES = CF2_MAX_HINTS * 2
  };

  typedef struct  CF2_HintMapRec_
  {
    CF2_Font  font;

    /* initial map based on blue zones */
    struct CF2_HintMapRec_*  initialHintMap;

    /* working storage for 2nd pass adjustHints */
    CF2_ArrStack  hintMoves;

    FT_Bool  isValid;
    FT_Bool  hinted;

    CF2_Fixed  scale;
    CF2_UInt   count;

    /* start search from this index */
    CF2_UInt  lastIndex;

    CF2_HintRec  edge[CF2_MAX_HINT_EDGES]; /* 192 */

  } CF2_HintMapRec, *CF2_HintMap;

  FT_LOCAL( FT_Bool )
  cf2_hint_isValid( const CF2_Hint  hint );
  FT_LOCAL( FT_Bool )
  cf2_hint_isTop( const CF2_Hint  hint );
  FT_LOCAL( FT_Bool )
  cf2_hint_isBottom( const CF2_Hint  hint );
  FT_LOCAL( void )
  cf2_hint_lock( CF2_Hint  hint );

  FT_LOCAL( void )
  cf2_hintmap_init( CF2_HintMap   hintmap,
                    CF2_Font      font,
                    CF2_HintMap   initialMap,
                    CF2_ArrStack  hintMoves,
                    CF2_Fixed     scale );
  FT_LOCAL( void )
  cf2_hintmap_build( CF2_HintMap   hintmap,
                     CF2_ArrStack  hStemHintArray,
                     CF2_ArrStack  vStemHintArray,
                     CF2_HintMask  hintMask,
                     CF2_Fixed     hintOrigin,
                     FT_Bool       initialMap );

  /*
   * GlyphPath is a wrapper for drawing operations that scales the
   * coordinates according to the render matrix and HintMap.  It also tracks
   * open paths to control ClosePath and to insert MoveTo for broken fonts.
   *
   */
  typedef struct  CF2_GlyphPathRec_
  {
    /* TODO: gather some of these into a hinting context */

    CF2_Font              font;           /* font instance    */
    CF2_OutlineCallbacks  callbacks;      /* outline consumer */

    CF2_HintMapRec  hintMap;        /* current hint map            */
    CF2_HintMapRec  firstHintMap;   /* saved copy                  */
    CF2_HintMapRec  initialHintMap; /* based on all captured hints */

    CF2_ArrStackRec  hintMoves;  /* list of hint moves for 2nd pass */

    CF2_Fixed  scaleX;         /* matrix a */
    CF2_Fixed  scaleC;         /* matrix c */
    CF2_Fixed  scaleY;         /* matrix d */

    FT_Vector  fractionalTranslation;  /* including deviceXScale */
#if 0
    CF2_Fixed  hShift;    /* character space horizontal shift */
                          /* (for fauxing)                    */
#endif

    FT_Bool  pathIsOpen;     /* true after MoveTo                     */
    FT_Bool  pathIsClosing;  /* true when synthesizing closepath line */
    FT_Bool  darken;         /* true if stem darkening                */
    FT_Bool  moveIsPending;  /* true between MoveTo and offset MoveTo */

    /* references used to call `cf2_hintmap_build', if necessary */
    CF2_ArrStack         hStemHintArray;
    CF2_ArrStack         vStemHintArray;
    CF2_HintMask         hintMask;     /* ptr to the current mask */
    CF2_Fixed            hintOriginY;  /* copy of current origin  */
    const CF2_BluesRec*  blues;

    CF2_Fixed  xOffset;        /* character space offsets */
    CF2_Fixed  yOffset;

    /* character space miter limit threshold */
    CF2_Fixed  miterLimit;
    /* vertical/horizontal snap distance in character space */
    CF2_Fixed  snapThreshold;

    FT_Vector  offsetStart0;  /* first and second points of first */
    FT_Vector  offsetStart1;  /* element with offset applied      */

    /* current point, character space, before offset */
    FT_Vector  currentCS;
    /* current point, device space */
    FT_Vector  currentDS;
    /* start point of subpath, character space */
    FT_Vector  start;

    /* the following members constitute the `queue' of one element */
    FT_Bool  elemIsQueued;
    CF2_Int  prevElemOp;

    FT_Vector  prevElemP0;
    FT_Vector  prevElemP1;
    FT_Vector  prevElemP2;
    FT_Vector  prevElemP3;

  } CF2_GlyphPathRec, *CF2_GlyphPath;

  FT_LOCAL( void )
  cf2_glyphpath_init( CF2_GlyphPath         glyphpath,
                      CF2_Font              font,
                      CF2_OutlineCallbacks  callbacks,
                      CF2_Fixed             scaleY,
                      /* CF2_Fixed hShift, */
                      CF2_ArrStack          hStemHintArray,
                      CF2_ArrStack          vStemHintArray,
                      CF2_HintMask          hintMask,
                      CF2_Fixed             hintOrigin,
                      const CF2_Blues       blues,
                      const FT_Vector*      fractionalTranslation );
  FT_LOCAL( void )
  cf2_glyphpath_finalize( CF2_GlyphPath  glyphpath );

  FT_LOCAL( void )
  cf2_glyphpath_moveTo( CF2_GlyphPath  glyphpath,
                        CF2_Fixed      x,
                        CF2_Fixed      y );
  FT_LOCAL( void )
  cf2_glyphpath_lineTo( CF2_GlyphPath  glyphpath,
                        CF2_Fixed      x,
                        CF2_Fixed      y );
  FT_LOCAL( void )
  cf2_glyphpath_curveTo( CF2_GlyphPath  glyphpath,
                         CF2_Fixed      x1,
                         CF2_Fixed      y1,
                         CF2_Fixed      x2,
                         CF2_Fixed      y2,
                         CF2_Fixed      x3,
                         CF2_Fixed      y3 );
  FT_LOCAL( void )
  cf2_glyphpath_closeOpenPath( CF2_GlyphPath  glyphpath );

FT_END_HEADER

#endif /* PSHINT_H_ */

/* END */

repo_language: C

mime_type: text/x-c


text:
/****************************************************************************
 *
 * psft.h
 *
 *   FreeType Glue Component to Adobe's Interpreter (specification).
 *
 * Copyright 2013 Adobe Systems Incorporated.
 *
 * This software, and all works of authorship, whether in source or
 * object code form as indicated by the copyright notice(s) included
 * herein (collectively, the "Work") is made available, and may only be
 * used, modified, and distributed under the FreeType Project License,
 * LICENSE.TXT.  Additionally, subject to the terms and conditions of the
 * FreeType Project License, each contributor to the Work hereby grants
 * to any individual or legal entity exercising permissions granted by
 * the FreeType Project License and this section (hereafter, "You" or
 * "Your") a perpetual, worldwide, non-exclusive, no-charge,
 * royalty-free, irrevocable (except as stated in this section) patent
 * license to make, have made, use, offer to sell, sell, import, and
 * otherwise transfer the Work, where such license applies only to those
 * patent claims licensable by such contributor that are necessarily
 * infringed by their contribution(s) alone or by combination of their
 * contribution(s) with the Work to which such contribution(s) was
 * submitted.  If You institute patent litigation against any entity
 * (including a cross-claim or counterclaim in a lawsuit) alleging that
 * the Work or a contribution incorporated within the Work constitutes
 * direct or contributory patent infringement, then any patent licenses
 * granted to You under this License for that Work shall terminate as of
 * the date such litigation is filed.
 *
 * By using, modifying, or distributing the Work you indicate that you
 * have read and understood the terms and conditions of the
 * FreeType Project License as well as those provided in this section,
 * and you accept them fully.
 *
 */

#ifndef PSFT_H_
#define PSFT_H_

#include "pstypes.h"

  /* TODO: disable asserts for now */
#define CF2_NDEBUG

#include FT_SYSTEM_H

#include "psglue.h"
#include FT_INTERNAL_POSTSCRIPT_AUX_H    /* for PS_Decoder */

FT_BEGIN_HEADER

  FT_LOCAL( FT_Error )
  cf2_decoder_parse_charstrings( PS_Decoder*  decoder,
                                 FT_Byte*     charstring_base,
                                 FT_ULong     charstring_len );

  FT_LOCAL( CFF_SubFont )
  cf2_getSubfont( PS_Decoder*  decoder );

  FT_LOCAL( CFF_VStore )
  cf2_getVStore( PS_Decoder*  decoder );

  FT_LOCAL( FT_UInt )
  cf2_getMaxstack( PS_Decoder*  decoder );

#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  FT_LOCAL( FT_Error )
  cf2_getNormalizedVector( PS_Decoder*  decoder,
                           CF2_UInt    *len,
                           FT_Fixed*   *vec );
#endif

  FT_LOCAL( CF2_Fixed )
  cf2_getPpemY( PS_Decoder*  decoder );
  FT_LOCAL( CF2_Fixed )
  cf2_getStdVW( PS_Decoder*  decoder );
  FT_LOCAL( CF2_Fixed )
  cf2_getStdHW( PS_Decoder*  decoder );

  FT_LOCAL( void )
  cf2_getBlueMetrics( PS_Decoder*  decoder,
                      CF2_Fixed*   blueScale,
                      CF2_Fixed*   blueShift,
                      CF2_Fixed*   blueFuzz );
  FT_LOCAL( void )
  cf2_getBlueValues( PS_Decoder*  decoder,
                     size_t*      count,
                     FT_Pos*     *data );
  FT_LOCAL( void )
  cf2_getOtherBlues( PS_Decoder*  decoder,
                     size_t*      count,
                     FT_Pos*     *data );
  FT_LOCAL( void )
  cf2_getFamilyBlues( PS_Decoder*  decoder,
                      size_t*      count,
                      FT_Pos*     *data );
  FT_LOCAL( void )
  cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
                           size_t*      count,
                           FT_Pos*     *data );

  FT_LOCAL( CF2_Int )
  cf2_getLanguageGroup( PS_Decoder*  decoder );

  FT_LOCAL( CF2_Int )
  cf2_initGlobalRegionBuffer( PS_Decoder*  decoder,
                              CF2_Int      subrNum,
                              CF2_Buffer   buf );
  FT_LOCAL( FT_Error )
  cf2_getSeacComponent( PS_Decoder*  decoder,
                        CF2_Int      code,
                        CF2_Buffer   buf );
  FT_LOCAL( void )
  cf2_freeSeacComponent( PS_Decoder*  decoder,
                         CF2_Buffer   buf );
  FT_LOCAL( CF2_Int )
  cf2_initLocalRegionBuffer( PS_Decoder*  decoder,
                             CF2_Int      subrNum,
                             CF2_Buffer   buf );

  FT_LOCAL( CF2_Fixed )
  cf2_getDefaultWidthX( PS_Decoder*  decoder );
  FT_LOCAL( CF2_Fixed )
  cf2_getNominalWidthX( PS_Decoder*  decoder );

  FT_LOCAL( FT_Error )
  cf2_getT1SeacComponent( PS_Decoder*  decoder,
                          FT_UInt      glyph_index,
                          CF2_Buffer   buf );
  FT_LOCAL( void )
  cf2_freeT1SeacComponent( PS_Decoder*  decoder,
                           CF2_Buffer   buf );

  /*
   * FreeType client outline
   *
   * process output from the charstring interpreter
   */
  typedef struct  CF2_OutlineRec_
  {
    CF2_OutlineCallbacksRec  root;        /* base class must be first */
    PS_Decoder*              decoder;

  } CF2_OutlineRec, *CF2_Outline;

  FT_LOCAL( void )
  cf2_outline_reset( CF2_Outline  outline );
  FT_LOCAL( void )
  cf2_outline_close( CF2_Outline  outline );

FT_END_HEADER

#endif /* PSFT_H_ */

/* END */


text:
/****************************************************************************
 *
 * psglue.h
 *
 *   Adobe's code for shared stuff (specification only).
 *
 * Copyright 2007-2013 Adobe Systems Incorporated.
 *
 * This software, and all works of authorship, whether in source or
 * object code form as indicated by the copyright notice(s) included
 * herein (collectively, the "Work") is made available, and may only be
 * used, modified, and distributed under the FreeType Project License,
 * LICENSE.TXT.  Additionally, subject to the terms and conditions of the
 * FreeType Project License, each contributor to the Work hereby grants
 * to any individual or legal entity exercising permissions granted by
 * the FreeType Project License and this section (hereafter, "You" or
 * "Your") a perpetual, worldwide, non-exclusive, no-charge,
 * royalty-free, irrevocable (except as stated in this section) patent
 * license to make, have made, use, offer to sell, sell, import, and
 * otherwise transfer the Work, where such license applies only to those
 * patent claims licensable by such contributor that are necessarily
 * infringed by their contribution(s) alone or by combination of their
 * contribution(s) with the Work to which such contribution(s) was
 * submitted.  If You institute patent litigation against any entity
 * (including a cross-claim or counterclaim in a lawsuit) alleging that
 * the Work or a contribution incorporated within the Work constitutes
 * direct or contributory patent infringement, then any patent licenses
 * granted to You under this License for that Work shall terminate as of
 * the date such litigation is filed.
 *
 * By using, modifying, or distributing the Work you indicate that you
 * have read and understood the terms and conditions of the
 * FreeType Project License as well as those provided in this section,
 * and you accept them fully.
 *
 */

#ifndef PSGLUE_H_
#define PSGLUE_H_

/* common includes for other modules */
#include "pserror.h"
#include "psfixed.h"
#include "psarrst.h"
#include "psread.h"

FT_BEGIN_HEADER

  /* rendering parameters */

  /* apply hints to rendered glyphs */
#define CF2_FlagsHinted    1
  /* for testing */
#define CF2_FlagsDarkened  2

  /* type for holding the flags */
  typedef CF2_Int  CF2_RenderingFlags;

  /* elements of a glyph outline */
  typedef enum  CF2_PathOp_
  {
    CF2_PathOpMoveTo = 1,     /* change the current point */
    CF2_PathOpLineTo = 2,     /* line                     */
    CF2_PathOpQuadTo = 3,     /* quadratic curve          */
    CF2_PathOpCubeTo = 4      /* cubic curve              */

  } CF2_PathOp;

  /* a matrix of fixed point values */
  typedef struct  CF2_Matrix_
  {
    CF2_F16Dot16  a;
    CF2_F16Dot16  b;
    CF2_F16Dot16  c;
    CF2_F16Dot16  d;
    CF2_F16Dot16  tx;
    CF2_F16Dot16  ty;

  } CF2_Matrix;

  /* these typedefs are needed by more than one header file */
  /* and gcc compiler doesn't allow redefinition            */
  typedef struct CF2_FontRec_  CF2_FontRec, *CF2_Font;
  typedef struct CF2_HintRec_  CF2_HintRec, *CF2_Hint;

  /* A common structure for all callback parameters.                       */
  /*                                                                       */
  /* Some members may be unused.  For example, `pt0' is not used for       */
  /* `moveTo' and `pt3' is not used for `quadTo'.  The initial point `pt0' */
  /* is included for each path element for generality; curve conversions   */
  /* need it.  The `op' parameter allows one function to handle multiple   */
  /* element types.                                                        */

  typedef struct  CF2_CallbackParamsRec_
  {
    FT_Vector  pt0;
    FT_Vector  pt1;
    FT_Vector  pt2;
    FT_Vector  pt3;

    CF2_Int  op;

  } CF2_CallbackParamsRec, *CF2_CallbackParams;

  /* forward reference */
  typedef struct CF2_OutlineCallbacksRec_  CF2_OutlineCallbacksRec,
                                           *CF2_OutlineCallbacks;

  /* callback function pointers */
  typedef void
  (*CF2_Callback_Type)( CF2_OutlineCallbacks      callbacks,
                        const CF2_CallbackParams  params );

  struct  CF2_OutlineCallbacksRec_
  {
    CF2_Callback_Type  moveTo;
    CF2_Callback_Type  lineTo;
    CF2_Callback_Type  quadTo;
    CF2_Callback_Type  cubeTo;

    CF2_Int  windingMomentum;    /* for winding order detection */

    FT_Memory  memory;
    FT_Error*  error;
  };

FT_END_HEADER

#endif /* PSGLUE_H_ */

/* END */


text:
/****************************************************************************
 *
 * psblues.h
 *
 *   Adobe's code for handling Blue Zones (specification).
 *
 * Copyright 2009-2013 Adobe Systems Incorporated.
 *
 * This software, and all works of authorship, whether in source or
 * object code form as indicated by the copyright notice(s) included
 * herein (collectively, the "Work") is made available, and may only be
 * used, modified, and distributed under the FreeType Project License,
 * LICENSE.TXT.  Additionally, subject to the terms and conditions of the
 * FreeType Project License, each contributor to the Work hereby grants
 * to any individual or legal entity exercising permissions granted by
 * the FreeType Project License and this section (hereafter, "You" or
 * "Your") a perpetual, worldwide, non-exclusive, no-charge,
 * royalty-free, irrevocable (except as stated in this section) patent
 * license to make, have made, use, offer to sell, sell, import, and
 * otherwise transfer the Work, where such license applies only to those
 * patent claims licensable by such contributor that are necessarily
 * infringed by their contribution(s) alone or by combination of their
 * contribution(s) with the Work to which such contribution(s) was
 * submitted.  If You institute patent litigation against any entity
 * (including a cross-claim or counterclaim in a lawsuit) alleging that
 * the Work or a contribution incorporated within the Work constitutes
 * direct or contributory patent infringement, then any patent licenses
 * granted to You under this License for that Work shall terminate as of
 * the date such litigation is filed.
 *
 * By using, modifying, or distributing the Work you indicate that you
 * have read and understood the terms and conditions of the
 * FreeType Project License as well as those provided in this section,
 * and you accept them fully.
 *
 */

  /*
   * A `CF2_Blues' object stores the blue zones (horizontal alignment
   * zones) of a font.  These are specified in the CFF private dictionary
   * by `BlueValues', `OtherBlues', `FamilyBlues', and `FamilyOtherBlues'.
   * Each zone is defined by a top and bottom edge in character space.
   * Further, each zone is either a top zone or a bottom zone, as recorded
   * by `bottomZone'.
   *
   * The maximum number of `BlueValues' and `FamilyBlues' is 7 each.
   * However, these are combined to produce a total of 7 zones.
   * Similarly, the maximum number of `OtherBlues' and `FamilyOtherBlues'
   * is 5 and these are combined to produce an additional 5 zones.
   *
   * Blue zones are used to `capture' hints and force them to a common
   * alignment point.  This alignment is recorded in device space in
   * `dsFlatEdge'.  Except for this value, a `CF2_Blues' object could be
   * constructed independently of scaling.  Construction may occur once
   * the matrix is known.  Other features implemented in the Capture
   * method are overshoot suppression, overshoot enforcement, and Blue
   * Boost.
   *
   * Capture is determined by `BlueValues' and `OtherBlues', but the
   * alignment point may be adjusted to the scaled flat edge of
   * `FamilyBlues' or `FamilyOtherBlues'.  No alignment is done to the
   * curved edge of a zone.
   *
   */

#ifndef PSBLUES_H_
#define PSBLUES_H_

#include "psglue.h"

FT_BEGIN_HEADER

  /*
   * `CF2_Hint' is shared by `cf2hints.h' and
   * `cf2blues.h', but `cf2blues.h' depends on
   * `cf2hints.h', so define it here.  Note: The typedef is in
   * `cf2glue.h'.
   *
   */
  enum
  {
    CF2_GhostBottom = 0x1,  /* a single bottom edge           */
    CF2_GhostTop    = 0x2,  /* a single top edge              */
    CF2_PairBottom  = 0x4,  /* the bottom edge of a stem hint */
    CF2_PairTop     = 0x8,  /* the top edge of a stem hint    */
    CF2_Locked      = 0x10, /* this edge has been aligned     */
                            /* by a blue zone                 */
    CF2_Synthetic   = 0x20  /* this edge was synthesized      */
  };

  /*
   * Default value for OS/2 typoAscender/Descender when their difference
   * is not equal to `unitsPerEm'.  The default is based on -250 and 1100
   * in `CF2_Blues', assuming 1000 units per em here.
   *
   */
  enum
  {
    CF2_ICF_Top    = cf2_intToFixed(  880 ),
    CF2_ICF_Bottom = cf2_intToFixed( -120 )
  };

  /*
   * Constant used for hint adjustment and for synthetic em box hint
   * placement.
   */
#define CF2_MIN_COUNTER  cf2_doubleToFixed( 0.5 )

  /* shared typedef is in cf2glue.h */
  struct  CF2_HintRec_
  {
    CF2_UInt  flags;  /* attributes of the edge            */
    size_t    index;  /* index in original stem hint array */
                      /* (if not synthetic)                */
    CF2_Fixed  csCoord;
    CF2_Fixed  dsCoord;
    CF2_Fixed  scale;
  };

  typedef struct  CF2_BlueRec_
  {
    CF2_Fixed  csBottomEdge;
    CF2_Fixed  csTopEdge;
    CF2_Fixed  csFlatEdge; /* may be from either local or Family zones */
    CF2_Fixed  dsFlatEdge; /* top edge of bottom zone or bottom edge   */
                           /* of top zone (rounded)                    */
    FT_Bool  bottomZone;

  } CF2_BlueRec;

  /* max total blue zones is 12 */
  enum
  {
    CF2_MAX_BLUES      = 7,
    CF2_MAX_OTHERBLUES = 5
  };

  typedef struct  CF2_BluesRec_
  {
    CF2_Fixed  scale;
    CF2_UInt   count;
    FT_Bool    suppressOvershoot;
    FT_Bool    doEmBoxHints;

    CF2_Fixed  blueScale;
    CF2_Fixed  blueShift;
    CF2_Fixed  blueFuzz;

    CF2_Fixed  boost;

    CF2_HintRec  emBoxTopEdge;
    CF2_HintRec  emBoxBottomEdge;

    CF2_BlueRec  zone[CF2_MAX_BLUES + CF2_MAX_OTHERBLUES];

  } CF2_BluesRec, *CF2_Blues;

  FT_LOCAL( void )
  cf2_blues_init( CF2_Blues  blues,
                  CF2_Font   font );
  FT_LOCAL( FT_Bool )
  cf2_blues_capture( const CF2_Blues  blues,
                     CF2_Hint         bottomHintEdge,
                     CF2_Hint         topHintEdge );

FT_END_HEADER

#endif /* PSBLUES_H_ */

/* END */


text:
/****************************************************************************
 *
 * t1decode.h
 *
 *   PostScript Type 1 decoding routines (specification).
 *
 * Copyright (C) 2000-2020 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.
 *
 */

#ifndef T1DECODE_H_
#define T1DECODE_H_

#include <ft2build.h>
#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include FT_INTERNAL_TYPE1_TYPES_H

FT_BEGIN_HEADER

  FT_CALLBACK_TABLE
  const T1_Decoder_FuncsRec  t1_decoder_funcs;

  FT_LOCAL( FT_Int )
  t1_lookup_glyph_by_stdcharcode_ps( PS_Decoder*  decoder,
                                     FT_Int       charcode );

#ifdef T1_CONFIG_OPTION_OLD_ENGINE
  FT_LOCAL( FT_Error )
  t1_decoder_parse_glyph( T1_Decoder  decoder,
                          FT_UInt     glyph_index );

  FT_LOCAL( FT_Error )
  t1_decoder_parse_charstrings( T1_Decoder  decoder,
                                FT_Byte*    base,
                                FT_UInt     len );
#else
  FT_LOCAL( FT_Error )
  t1_decoder_parse_metrics( T1_Decoder  decoder,
                            FT_Byte*    charstring_base,
                            FT_UInt     charstring_len );
#endif

  FT_LOCAL( FT_Error )
  t1_decoder_init( T1_Decoder           decoder,
                   FT_Face              face,
                   FT_Size              size,
                   FT_GlyphSlot         slot,
                   FT_Byte**            glyph_names,
                   PS_Blend             blend,
                   FT_Bool              hinting,
                   FT_Render_Mode       hint_mode,
                   T1_Decoder_Callback  parse_glyph );

  FT_LOCAL( void )
  t1_decoder_done( T1_Decoder  decoder );

FT_END_HEADER

#endif /* T1DECODE_H_ */

/* END */