Charles.Forsyth20060303a828770d19 years agoHistory
1403 lines · 37.4 KB · C
RawDownload
/***************************************************************************//*                                                                         *//*  psobjs.c                                                               *//*                                                                         *//*    Auxiliary functions for PostScript fonts (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 FT_INTERNAL_POSTSCRIPT_AUX_H#include FT_INTERNAL_DEBUG_H #include "psobjs.h" #include "psauxerr.h"    /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                             PS_TABLE                          *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/   /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    ps_table_new                                                       */  /*                                                                       */  /* <Description>                                                         */  /*    Initializes a PS_Table.                                            */  /*                                                                       */  /* <InOut>                                                               */  /*    table  :: The address of the target table.                         */  /*                                                                       */  /* <Input>                                                               */  /*    count  :: The table size = the maximum number of elements.         */  /*                                                                       */  /*    memory :: The memory object to use for all subsequent              */  /*              reallocations.                                           */  /*                                                                       */  /* <Return>                                                              */  /*    FreeType error code.  0 means success.                             */  /*                                                                       */  FT_LOCAL_DEF( FT_Error )  ps_table_new( PS_Table   table,                FT_Int     count,                FT_Memory  memory )  {    FT_Error  error;      table->memory = memory;    if ( FT_NEW_ARRAY( table->elements, count ) ||         FT_NEW_ARRAY( table->lengths,  count ) )      goto Exit;     table->max_elems = count;    table->init      = 0xDEADBEEFUL;    table->num_elems = 0;    table->block     = 0;    table->capacity  = 0;    table->cursor    = 0;     *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;   Exit:    if ( error )      FT_FREE( table->elements );     return error;  }    static void  shift_elements( PS_Table  table,                  FT_Byte*  old_base )  {    FT_Long    delta  = (FT_Long)( table->block - old_base );    FT_Byte**  offset = table->elements;    FT_Byte**  limit  = offset + table->max_elems;      for ( ; offset < limit; offset++ )    {      if ( offset[0] )        offset[0] += delta;    }  }    static FT_Error  reallocate_t1_table( PS_Table  table,                       FT_Long   new_size )  {    FT_Memory  memory   = table->memory;    FT_Byte*   old_base = table->block;    FT_Error   error;      /* allocate new base block */    if ( FT_ALLOC( table->block, new_size ) )      return error;     /* copy elements and shift offsets */    if (old_base )    {      FT_MEM_COPY( table->block, old_base, table->capacity );      shift_elements( table, old_base );      FT_FREE( old_base );    }     table->capacity = new_size;     return PSaux_Err_Ok;  }    /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    ps_table_add                                                       */  /*                                                                       */  /* <Description>                                                         */  /*    Adds an object to a PS_Table, possibly growing its memory block.   */  /*                                                                       */  /* <InOut>                                                               */  /*    table  :: The target table.                                        */  /*                                                                       */  /* <Input>                                                               */  /*    idx  :: The index of the object in the table.                      */  /*                                                                       */  /*    object :: The address of the object to copy in memory.             */  /*                                                                       */  /*    length :: The length in bytes of the source object.                */  /*                                                                       */  /* <Return>                                                              */  /*    FreeType error code.  0 means success.  An error is returned if a  */  /*    reallocation fails.                                                */  /*                                                                       */  FT_LOCAL_DEF( FT_Error )  ps_table_add( PS_Table  table,                FT_Int    idx,                void*     object,                FT_Int    length )  {    if ( idx < 0 || idx > table->max_elems )    {      FT_ERROR(( "ps_table_add: invalid index\n" ));      return PSaux_Err_Invalid_Argument;    }     /* grow the base block if needed */    if ( table->cursor + length > table->capacity )    {      FT_Error   error;      FT_Offset  new_size  = table->capacity;      FT_Long    in_offset;        in_offset = (FT_Long)((FT_Byte*)object - table->block);      if ( (FT_ULong)in_offset >= table->capacity )        in_offset = -1;       while ( new_size < table->cursor + length )      {        /* increase size by 25% and round up to the nearest multiple of 1024 */        new_size += (new_size >> 2) + 1;        new_size  = ( new_size + 1023 ) & -1024;      }       error = reallocate_t1_table( table, new_size );      if ( error )        return error;       if ( in_offset >= 0 )        object = table->block + in_offset;    }     /* add the object to the base block and adjust offset */    table->elements[idx] = table->block + table->cursor;    table->lengths [idx] = length;    FT_MEM_COPY( table->block + table->cursor, object, length );     table->cursor += length;    return PSaux_Err_Ok;  }    /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    ps_table_done                                                      */  /*                                                                       */  /* <Description>                                                         */  /*    Finalizes a PS_TableRec (i.e., reallocate it to its current        */  /*    cursor).                                                           */  /*                                                                       */  /* <InOut>                                                               */  /*    table :: The target table.                                         */  /*                                                                       */  /* <Note>                                                                */  /*    This function does NOT release the heap's memory block.  It is up  */  /*    to the caller to clean it, or reference it in its own structures.  */  /*                                                                       */  FT_LOCAL_DEF( void )  ps_table_done( PS_Table  table )  {    FT_Memory  memory = table->memory;    FT_Error   error;    FT_Byte*   old_base = table->block;      /* should never fail, because rec.cursor <= rec.size */    if ( !old_base )      return;     if ( FT_ALLOC( table->block, table->cursor ) )      return;    FT_MEM_COPY( table->block, old_base, table->cursor );    shift_elements( table, old_base );     table->capacity = table->cursor;    FT_FREE( old_base );     FT_UNUSED( error );  }    FT_LOCAL_DEF( void )  ps_table_release( PS_Table  table )  {    FT_Memory  memory = table->memory;      if ( (FT_ULong)table->init == 0xDEADBEEFUL )    {      FT_FREE( table->block );      FT_FREE( table->elements );      FT_FREE( table->lengths );      table->init = 0;    }  }    /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                            T1 PARSER                          *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/  #define IS_T1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )#define IS_T1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' ) #define IS_T1_SPACE( c )  ( IS_T1_WHITESPACE( c ) || IS_T1_LINESPACE( c ) )    FT_LOCAL_DEF( void )  ps_parser_skip_spaces( PS_Parser  parser )  {    FT_Byte* cur   = parser->cursor;    FT_Byte* limit = parser->limit;      while ( cur < limit )    {      FT_Byte  c = *cur;        if ( !IS_T1_SPACE( c ) )        break;      cur++;    }    parser->cursor = cur;  }    FT_LOCAL_DEF( void )  ps_parser_skip_alpha( PS_Parser  parser )  {    FT_Byte* cur   = parser->cursor;    FT_Byte* limit = parser->limit;      while ( cur < limit )    {      FT_Byte  c = *cur;        if ( IS_T1_SPACE( c ) )        break;      cur++;    }    parser->cursor = cur;  }    FT_LOCAL_DEF( void )  ps_parser_to_token( PS_Parser  parser,                      T1_Token   token )  {    FT_Byte*  cur;    FT_Byte*  limit;    FT_Byte   starter, ender;    FT_Int    embed;      token->type  = T1_TOKEN_TYPE_NONE;    token->start = 0;    token->limit = 0;     /* first of all, skip space */    ps_parser_skip_spaces( parser );     cur   = parser->cursor;    limit = parser->limit;     if ( cur < limit )    {      switch ( *cur )      {        /************* check for strings ***********************/      case '(':        token->type = T1_TOKEN_TYPE_STRING;        ender = ')';        goto Lookup_Ender;         /************* check for programs/array ****************/      case '{':        token->type = T1_TOKEN_TYPE_ARRAY;        ender = '}';        goto Lookup_Ender;         /************* check for table/array ******************/      case '[':        token->type = T1_TOKEN_TYPE_ARRAY;        ender = ']';       Lookup_Ender:        embed   = 1;        starter = *cur++;        token->start = cur;        while ( cur < limit )        {          if ( *cur == starter )            embed++;          else if ( *cur == ender )          {            embed--;            if ( embed <= 0 )            {              token->limit = cur++;              break;            }          }          cur++;        }        break;         /* **************** otherwise, it's any token **********/      default:        token->start = cur++;        token->type  = T1_TOKEN_TYPE_ANY;        while ( cur < limit && !IS_T1_SPACE( *cur ) )          cur++;         token->limit = cur;      }       if ( !token->limit )      {        token->start = 0;        token->type  = T1_TOKEN_TYPE_NONE;      }       parser->cursor = cur;    }  }    FT_LOCAL_DEF( void )  ps_parser_to_token_array( PS_Parser  parser,                            T1_Token   tokens,                            FT_UInt    max_tokens,                            FT_Int*    pnum_tokens )  {    T1_TokenRec  master;      *pnum_tokens = -1;     ps_parser_to_token( parser, &master );    if ( master.type == T1_TOKEN_TYPE_ARRAY )    {      FT_Byte*  old_cursor = parser->cursor;      FT_Byte*  old_limit  = parser->limit;      T1_Token  cur        = tokens;      T1_Token  limit      = cur + max_tokens;        parser->cursor = master.start;      parser->limit  = master.limit;       while ( parser->cursor < parser->limit )      {        T1_TokenRec  token;          ps_parser_to_token( parser, &token );        if ( !token.type )          break;         if ( cur < limit )          *cur = token;         cur++;      }       *pnum_tokens = (FT_Int)( cur - tokens );       parser->cursor = old_cursor;      parser->limit  = old_limit;    }  }    static FT_Long  T1Radix( FT_Long    radixBase,           FT_Byte**  cur,           FT_Byte*   limit )  {    FT_Long  result = 0;    FT_Byte  radixEndChar0 =               (FT_Byte)( radixBase > 10 ? '9' + 1 : '0' + radixBase );    FT_Byte  radixEndChar1 =               (FT_Byte)( 'A' + radixBase - 10 );    FT_Byte  radixEndChar2 =               (FT_Byte)( 'a' + radixBase - 10 );      while( *cur < limit )    {      if ( (*cur)[0] >= '0' && (*cur)[0] < radixEndChar0 )        result = result * radixBase + (*cur)[0] - '0';       else if ( radixBase > 10 &&                (*cur)[0] >= 'A' && (*cur)[0] < radixEndChar1 )        result = result * radixBase + ( (*cur)[0] - 'A' + 10 );       else if ( radixBase > 10 &&                (*cur)[0] >= 'a' && (*cur)[0] < radixEndChar2 )        result = result * radixBase + ( (*cur)[0] - 'a' + 10 );       else        return result;       (*cur)++;    }     return result;  }    static FT_Long  t1_toint( FT_Byte**  cursor,            FT_Byte*   limit )  {    FT_Long   result = 0;    FT_Byte*  cur    = *cursor;    FT_Byte   c      = '\0', d;      for ( ; cur < limit; cur++ )    {      c = *cur;      d = (FT_Byte)( c - '0' );      if ( d < 10 )        break;       if ( c == '-' )      {        cur++;        break;      }    } 

Lines 1–500 of 1403.