Charles.Forsyth20060303a828770d19 years agoHistory
681 lines · 16.8 KB · C
RawDownload
/***************************************************************************//*                                                                         *//*  cffparse.c                                                             *//*                                                                         *//*    CFF token stream parser (body)                                       *//*                                                                         *//*  Copyright 1996-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 "cffparse.h"#include FT_INTERNAL_STREAM_H #include "cfferrs.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_cffparse    enum  {    cff_kind_none = 0,    cff_kind_num,    cff_kind_fixed,    cff_kind_string,    cff_kind_bool,    cff_kind_delta,    cff_kind_callback,     cff_kind_max  /* do not remove */  };    /* now generate handlers for the most simple fields */  typedef FT_Error  (*CFF_Field_Reader)( CFF_Parser  parser );   typedef struct  CFF_Field_Handler_  {    int               kind;    int               code;    FT_UInt           offset;    FT_Byte           size;    CFF_Field_Reader  reader;    FT_UInt           array_max;    FT_UInt           count_offset;   } CFF_Field_Handler;    FT_LOCAL_DEF( void )  cff_parser_init( CFF_Parser  parser,                   FT_UInt     code,                   void*       object )  {    FT_MEM_ZERO( parser, sizeof ( *parser ) );     parser->top         = parser->stack;    parser->object_code = code;    parser->object      = object;  }    /* read an integer */  static FT_Long  cff_parse_integer( FT_Byte*  start,                     FT_Byte*  limit )  {    FT_Byte*  p   = start;    FT_Int    v   = *p++;    FT_Long   val = 0;      if ( v == 28 )    {      if ( p + 2 > limit )        goto Bad;       val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );      p  += 2;    }    else if ( v == 29 )    {      if ( p + 4 > limit )        goto Bad;       val = ( (FT_Long)p[0] << 24 ) |            ( (FT_Long)p[1] << 16 ) |            ( (FT_Long)p[2] <<  8 ) |                       p[3];      p += 4;    }    else if ( v < 247 )    {      val = v - 139;    }    else if ( v < 251 )    {      if ( p + 1 > limit )        goto Bad;       val = ( v - 247 ) * 256 + p[0] + 108;      p++;    }    else    {      if ( p + 1 > limit )        goto Bad;       val = -( v - 251 ) * 256 - p[0] - 108;      p++;    }   Exit:    return val;   Bad:    val = 0;    goto Exit;  }    /* read a real */  static FT_Fixed  cff_parse_real( FT_Byte*  start,                  FT_Byte*  limit,                  FT_Int    power_ten )  {    FT_Byte*  p    = start;    FT_Long   num, divider, result, exp;    FT_Int    sign = 0, exp_sign = 0;    FT_UInt   nib;    FT_UInt   phase;      result  = 0;    num     = 0;    divider = 1;     /* first of all, read the integer part */    phase = 4;     for (;;)    {      /* If we entered this iteration with phase == 4, we need to */      /* read a new byte.  This also skips past the intial 0x1E.  */      if ( phase )      {        p++;         /* Make sure we don't read past the end. */        if ( p >= limit )          goto Bad;      }       /* Get the nibble. */      nib   = ( p[0] >> phase ) & 0xF;      phase = 4 - phase;       if ( nib == 0xE )        sign = 1;      else if ( nib > 9 )        break;      else        result = result * 10 + nib;    }     /* read decimal part, if any */    if ( nib == 0xa )      for (;;)      {        /* If we entered this iteration with phase == 4, we need */        /* to read a new byte.                                   */        if ( phase )        {          p++;           /* Make sure we don't read past the end. */          if ( p >= limit )            goto Bad;        }         /* Get the nibble. */        nib   = ( p[0] >> phase ) & 0xF;        phase = 4 - phase;        if ( nib >= 10 )          break;         if ( divider < 10000000L )        {          num      = num * 10 + nib;          divider *= 10;        }      }     /* read exponent, if any */    if ( nib == 12 )    {      exp_sign = 1;      nib      = 11;    }     if ( nib == 11 )    {      exp = 0;       for (;;)      {        /* If we entered this iteration with phase == 4, we need */        /* to read a new byte.                                   */        if ( phase )        {          p++;           /* Make sure we don't read past the end. */          if ( p >= limit )            goto Bad;        }         /* Get the nibble. */        nib   = ( p[0] >> phase ) & 0xF;        phase = 4 - phase;        if ( nib >= 10 )          break;         exp = exp * 10 + nib;      }       if ( exp_sign )        exp = -exp;       power_ten += (FT_Int)exp;    }     /* raise to power of ten if needed */    while ( power_ten > 0 )    {      result = result * 10;      num    = num * 10;       power_ten--;    }     while ( power_ten < 0 )    {      result  = result / 10;      divider = divider * 10;       power_ten++;    }     /* Move the integer part into the high 16 bits. */    result <<= 16;     /* Place the decimal part into the low 16 bits. */    if ( num )      result |= FT_DivFix( num, divider );     if ( sign )      result = -result;   Exit:    return result;   Bad:    result = 0;    goto Exit;  }    /* read a number, either integer or real */  static FT_Long  cff_parse_num( FT_Byte**  d )  {    return ( **d == 30 ? ( cff_parse_real   ( d[0], d[1], 0 ) >> 16 )                       :   cff_parse_integer( d[0], d[1] ) );  }    /* read a floating point number, either integer or real */  static FT_Fixed  cff_parse_fixed( FT_Byte**  d )  {    return ( **d == 30 ? cff_parse_real   ( d[0], d[1], 0 )                       : cff_parse_integer( d[0], d[1] ) << 16 );  }   /* read a floating point number, either integer or real, */  /* but return 1000 times the number read in.             */  static FT_Fixed  cff_parse_fixed_thousand( FT_Byte**  d )  {    return **d ==      30 ? cff_parse_real     ( d[0], d[1], 3 )         : (FT_Fixed)FT_MulFix( cff_parse_integer( d[0], d[1] ) << 16, 1000 );  }   static FT_Error  cff_parse_font_matrix( CFF_Parser  parser )  {    CFF_FontRecDict  dict   = (CFF_FontRecDict)parser->object;    FT_Matrix*       matrix = &dict->font_matrix;    FT_Vector*       offset = &dict->font_offset;    FT_UShort*       upm    = &dict->units_per_em;    FT_Byte**        data   = parser->stack;    FT_Error         error;    FT_Fixed         temp;      error = CFF_Err_Stack_Underflow;     if ( parser->top >= parser->stack + 6 )    {      matrix->xx = cff_parse_fixed_thousand( data++ );      matrix->yx = cff_parse_fixed_thousand( data++ );      matrix->xy = cff_parse_fixed_thousand( data++ );      matrix->yy = cff_parse_fixed_thousand( data++ );      offset->x  = cff_parse_fixed_thousand( data++ );      offset->y  = cff_parse_fixed_thousand( data   );       temp = ABS( matrix->yy );       *upm = (FT_UShort)FT_DivFix( 0x10000L, FT_DivFix( temp, 1000 ) );       if ( temp != 0x10000L )      {        matrix->xx = FT_DivFix( matrix->xx, temp );        matrix->yx = FT_DivFix( matrix->yx, temp );        matrix->xy = FT_DivFix( matrix->xy, temp );        matrix->yy = FT_DivFix( matrix->yy, temp );        offset->x  = FT_DivFix( offset->x,  temp );        offset->y  = FT_DivFix( offset->y,  temp );      }       /* note that the offsets must be expressed in integer font units */      offset->x >>= 16;      offset->y >>= 16;       error = CFF_Err_Ok;    }     return error;  }    static FT_Error  cff_parse_font_bbox( CFF_Parser  parser )  {    CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;    FT_BBox*         bbox = &dict->font_bbox;    FT_Byte**        data = parser->stack;    FT_Error         error;      error = CFF_Err_Stack_Underflow;     if ( parser->top >= parser->stack + 4 )    {      bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );      bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );      bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );      bbox->yMax = FT_RoundFix( cff_parse_fixed( data   ) );      error = CFF_Err_Ok;    }     return error;  }    static FT_Error  cff_parse_private_dict( CFF_Parser  parser )  {    CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;    FT_Byte**        data = parser->stack;    FT_Error         error;      error = CFF_Err_Stack_Underflow;     if ( parser->top >= parser->stack + 2 )    {      dict->private_size   = cff_parse_num( data++ );      dict->private_offset = cff_parse_num( data   );      error = CFF_Err_Ok;    }     return error;  }    static FT_Error  cff_parse_cid_ros( CFF_Parser  parser )  {    CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;    FT_Byte**        data = parser->stack;    FT_Error         error;      error = CFF_Err_Stack_Underflow;     if ( parser->top >= parser->stack + 3 )    {      dict->cid_registry   = (FT_UInt)cff_parse_num ( data++ );      dict->cid_ordering   = (FT_UInt)cff_parse_num ( data++ );      dict->cid_supplement = (FT_ULong)cff_parse_num( data );      error = CFF_Err_Ok;    }     return error;  }  #define CFF_FIELD_NUM( code, name ) \          CFF_FIELD( code, name, cff_kind_num )#define CFF_FIELD_FIXED( code, name ) \          CFF_FIELD( code, name, cff_kind_fixed )#define CFF_FIELD_STRING( code, name ) \          CFF_FIELD( code, name, cff_kind_string )#define CFF_FIELD_BOOL( code, name ) \          CFF_FIELD( code, name, cff_kind_bool )#define CFF_FIELD_DELTA( code, name, max ) \          CFF_FIELD( code, name, cff_kind_delta ) #define CFF_FIELD_CALLBACK( code, name ) \          {                              \            cff_kind_callback,           \            code | CFFCODE,              \            0, 0,                        \            cff_parse_ ## name,          \            0, 0                         \          }, #undef  CFF_FIELD#define CFF_FIELD( code, name, kind ) \          {                          \            kind,                    \            code | CFFCODE,          \            FT_FIELD_OFFSET( name ), \            FT_FIELD_SIZE( name ),   \            0, 0, 0                  \          }, #undef  CFF_FIELD_DELTA#define CFF_FIELD_DELTA( code, name, max ) \        {                                  \          cff_kind_delta,                  \          code | CFFCODE,                  \          FT_FIELD_OFFSET( name ),         \          FT_FIELD_SIZE_DELTA( name ),     \          0,                               \          max,                             \          FT_FIELD_OFFSET( num_ ## name )  \        }, #define CFFCODE_TOPDICT  0x1000#define CFFCODE_PRIVATE  0x2000   static const CFF_Field_Handler  cff_field_handlers[] =  { #include "cfftoken.h"     { 0, 0, 0, 0, 0, 0, 0 }  };    FT_LOCAL_DEF( FT_Error )  cff_parser_run( CFF_Parser  parser,                  FT_Byte*    start,                  FT_Byte*    limit )  {    FT_Byte*  p     = start;    FT_Error  error = CFF_Err_Ok;      parser->top    = parser->stack;    parser->start  = start;    parser->limit  = limit;    parser->cursor = start;     while ( p < limit )    {      FT_UInt  v = *p;  

Lines 1–500 of 681.