forsyth20121205-174063a80cc13 years agoHistory
1170 lines · 34.8 KB · C
RawDownload
/***************************************************************************//*                                                                         *//*  t1decode.c                                                             *//*                                                                         *//*    PostScript Type 1 decoding routines (body).                          *//*                                                                         *//*  Copyright 2000-2001, 2002 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_POSTSCRIPT_HINTS_H#include FT_OUTLINE_H #include "t1decode.h"#include "psobjs.h" #include "psauxerr.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_t1decode    typedef enum  T1_Operator_  {    op_none = 0,    op_endchar,    op_hsbw,    op_seac,    op_sbw,    op_closepath,    op_hlineto,    op_hmoveto,    op_hvcurveto,    op_rlineto,    op_rmoveto,    op_rrcurveto,    op_vhcurveto,    op_vlineto,    op_vmoveto,    op_dotsection,    op_hstem,    op_hstem3,    op_vstem,    op_vstem3,    op_div,    op_callothersubr,    op_callsubr,    op_pop,    op_return,    op_setcurrentpoint,     op_max    /* never remove this one */   } T1_Operator;    static  const FT_Int  t1_args_count[op_max] =  {    0, /* none */    0, /* endchar */    2, /* hsbw */    5, /* seac */    4, /* sbw */    0, /* closepath */    1, /* hlineto */    1, /* hmoveto */    4, /* hvcurveto */    2, /* rlineto */    2, /* rmoveto */    6, /* rrcurveto */    4, /* vhcurveto */    1, /* vlineto */    1, /* vmoveto */    0, /* dotsection */    2, /* hstem */    6, /* hstem3 */    2, /* vstem */    6, /* vstem3 */    2, /* div */   -1, /* callothersubr */    1, /* callsubr */    0, /* pop */    0, /* return */    2  /* setcurrentpoint */  };    /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    t1_lookup_glyph_by_stdcharcode                                     */  /*                                                                       */  /* <Description>                                                         */  /*    Looks up a given glyph by its StandardEncoding charcode.  Used to  */  /*    implement the SEAC Type 1 operator.                                */  /*                                                                       */  /* <Input>                                                               */  /*    face     :: The current face object.                               */  /*                                                                       */  /*    charcode :: The character code to look for.                        */  /*                                                                       */  /* <Return>                                                              */  /*    A glyph index in the font face.  Returns -1 if the corresponding   */  /*    glyph wasn't found.                                                */  /*                                                                       */  static FT_Int  t1_lookup_glyph_by_stdcharcode( T1_Decoder  decoder,                                  FT_Int      charcode )  {    FT_UInt           n;    const FT_String*  glyph_name;    PSNames_Service   psnames = decoder->psnames;      /* check range of standard char code */    if ( charcode < 0 || charcode > 255 )      return -1;     glyph_name = psnames->adobe_std_strings(                   psnames->adobe_std_encoding[charcode]);     for ( n = 0; n < decoder->num_glyphs; n++ )    {      FT_String*  name = (FT_String*)decoder->glyph_names[n];        if ( name && name[0] == glyph_name[0]  &&           ft_strcmp( name,glyph_name ) == 0 )        return n;    }     return -1;  }    /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    t1operator_seac                                                    */  /*                                                                       */  /* <Description>                                                         */  /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */  /*                                                                       */  /* <Input>                                                               */  /*    decoder :: The current CID decoder.                                */  /*                                                                       */  /*    asb     :: The accent's side bearing.                              */  /*                                                                       */  /*    adx     :: The horizontal offset of the accent.                    */  /*                                                                       */  /*    ady     :: The vertical offset of the accent.                      */  /*                                                                       */  /*    bchar   :: The base character's StandardEncoding charcode.         */  /*                                                                       */  /*    achar   :: The accent character's StandardEncoding charcode.       */  /*                                                                       */  /* <Return>                                                              */  /*    FreeType error code.  0 means success.                             */  /*                                                                       */  static FT_Error  t1operator_seac( T1_Decoder  decoder,                   FT_Pos      asb,                   FT_Pos      adx,                   FT_Pos      ady,                   FT_Int      bchar,                   FT_Int      achar )  {    FT_Error     error;    FT_Int       bchar_index, achar_index;#if 0    FT_Int       n_base_points;    FT_Outline*  base = decoder->builder.base;#endif    FT_Vector    left_bearing, advance;      /* seac weirdness */    adx += decoder->builder.left_bearing.x;     /* `glyph_names' is set to 0 for CID fonts which do not */    /* include an encoding.  How can we deal with these?    */    if ( decoder->glyph_names == 0 )    {      FT_ERROR(( "t1operator_seac:" ));      FT_ERROR(( " glyph names table not available in this font!\n" ));      return PSaux_Err_Syntax_Error;    }     bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );    achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );     if ( bchar_index < 0 || achar_index < 0 )    {      FT_ERROR(( "t1operator_seac:" ));      FT_ERROR(( " invalid seac character code arguments\n" ));      return PSaux_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_CheckSubGlyphs( 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 - asb;      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;      goto Exit;    }     /* First load `bchar' in builder */    /* now load the unscaled outline */     FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */     error = t1_decoder_parse_glyph( decoder, bchar_index );    if ( error )      goto Exit; #if 0    n_base_points = base->n_points;#endif     /* 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;     decoder->builder.pos_x = adx - asb;    decoder->builder.pos_y = ady;     /* Now load `achar' on top of */    /* the base outline           */    error = t1_decoder_parse_glyph( decoder, achar_index );    if ( error )      goto Exit;     /* restore the left side bearing and   */    /* advance width of the base character */     decoder->builder.left_bearing = left_bearing;    decoder->builder.advance      = advance;     /* XXX: old code doesn't work with PostScript hinter */#if 0    /* Finally, move the accent */    if ( decoder->builder.load_points )    {      FT_Outline  dummy;        dummy.n_points = (short)( base->n_points - n_base_points );      dummy.points   = base->points + n_base_points;       FT_Outline_Translate( &dummy, adx - asb, ady );    }#else    decoder->builder.pos_x = 0;    decoder->builder.pos_y = 0;#endif   Exit:    return error;  }    /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    t1_decoder_parse_charstrings                                       */  /*                                                                       */  /* <Description>                                                         */  /*    Parses a given Type 1 charstrings program.                         */  /*                                                                       */  /* <Input>                                                               */  /*    decoder         :: The current Type 1 decoder.                     */  /*                                                                       */  /*    charstring_base :: The base address 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 )  t1_decoder_parse_charstrings( T1_Decoder  decoder,                                FT_Byte*    charstring_base,                                FT_UInt     charstring_len )  {    FT_Error         error;    T1_Decoder_Zone  zone;    FT_Byte*         ip;    FT_Byte*         limit;    T1_Builder       builder = &decoder->builder;    FT_Pos           x, y, orig_x, orig_y;     T1_Hints_Funcs   hinter;      /* we don't want to touch the source code -- use macro trick */#define start_point    t1_builder_start_point#define check_points   t1_builder_check_points#define add_point      t1_builder_add_point#define add_point1     t1_builder_add_point1#define add_contour    t1_builder_add_contour#define close_contour  t1_builder_close_contour     /* First of all, initialize the decoder */    decoder->top  = decoder->stack;    decoder->zone = decoder->zones;    zone          = decoder->zones;     builder->path_begun  = 0;     hinter = (T1_Hints_Funcs)builder->hints_funcs;     zone->base           = charstring_base;    limit = zone->limit  = charstring_base + charstring_len;    ip    = zone->cursor = zone->base;     error = PSaux_Err_Ok;     x = orig_x = builder->pos_x;    y = orig_y = builder->pos_y;     /* begin hints recording session, if any */    if ( hinter )      hinter->open( hinter->hints );     /* now, execute loop */    while ( ip < limit )    {      FT_Long*     top   = decoder->top;      T1_Operator  op    = op_none;      FT_Long      value = 0;        /*********************************************************************/      /*                                                                   */      /* Decode operator or operand                                        */      /*                                                                   */      /*                                                                   */       /* first of all, decompress operator or value */      switch ( *ip++ )      {      case 1:        op = op_hstem;        break;       case 3:        op = op_vstem;        break;      case 4:        op = op_vmoveto;        break;      case 5:        op = op_rlineto;        break;      case 6:        op = op_hlineto;        break;      case 7:        op = op_vlineto;        break;      case 8:        op = op_rrcurveto;        break;      case 9:        op = op_closepath;        break;      case 10:        op = op_callsubr;        break;      case 11:        op = op_return;        break;       case 13:        op = op_hsbw;        break;      case 14:        op = op_endchar;        break;       case 15:          /* undocumented, obsolete operator */        op = op_none;        break;       case 21:        op = op_rmoveto;        break;      case 22:        op = op_hmoveto;        break;       case 30:        op = op_vhcurveto;        break;      case 31:        op = op_hvcurveto;        break;       case 12:        if ( ip > limit )        {          FT_ERROR(( "t1_decoder_parse_charstrings: "                     "invalid escape (12+EOF)\n" ));          goto Syntax_Error;        }         switch ( *ip++ )        {        case 0:          op = op_dotsection;          break;        case 1:          op = op_vstem3;          break;        case 2:          op = op_hstem3;          break;        case 6:          op = op_seac;          break;        case 7:          op = op_sbw;          break;        case 12:          op = op_div;          break;        case 16:          op = op_callothersubr;          break;        case 17:          op = op_pop;          break;        case 33:          op = op_setcurrentpoint;          break;         default:          FT_ERROR(( "t1_decoder_parse_charstrings: "                     "invalid escape (12+%d)\n",                     ip[-1] ));          goto Syntax_Error;        }        break;       case 255:    /* four bytes integer */        if ( ip + 4 > limit )

Lines 1–500 of 1170.