Edit

kc3-lang/freetype/src/type1/t1parse.c

Branch :

  • Show log

    Commit

  • Author : Werner Lemberg
    Date : 2000-07-08 19:51:42
    Hash : 7fa51b55
    Message : Formatting. Adding some trivial error checking. Adding/Fixing tracing levels.

  • src/type1/t1parse.c
  • /***************************************************************************/
    /*                                                                         */
    /*  t1parse.c                                                              */
    /*                                                                         */
    /*    Type 1 parser (body).                                                */
    /*                                                                         */
    /*  Copyright 1996-2000 by                                                 */
    /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
    /*                                                                         */
    /*  This file is part of the FreeType project, and may only be used,       */
    /*  modified, and distributed under the terms of the FreeType project      */
    /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
    /*  this file you indicate that you have read the license and              */
    /*  understand and accept it fully.                                        */
    /*                                                                         */
    /***************************************************************************/
    
    
    #include <freetype/internal/ftdebug.h>
    #include <freetype/internal/t1types.h>
    
    
    #ifdef FT_FLAT_COMPILE
    
    #include "t1parse.h"
    
    #else
    
    #include <type1/t1parse.h>
    
    #endif
    
    
    #include <stdio.h>  /* for sscanf()  */
    #include <string.h> /* for strncpy() */
    
    
      /*************************************************************************/
      /*                                                                       */
      /* <Function>                                                            */
      /*    T1_New_Table                                                       */
      /*                                                                       */
      /* <Description>                                                         */
      /*    Initializes a T1_Table structure.                                  */
      /*                                                                       */
      /* <InOut>                                                               */
      /*    table  :: The address of the target table.                         */
      /*                                                                       */
      /* <Input>                                                               */
      /*    count  :: The table size (i.e. maximum number of elements).        */
      /*    memory :: The memory object to use for all subsequent              */
      /*              reallocations.                                           */
      /*                                                                       */
      /* <Return>                                                              */
      /*    FreeType error code.  0 means success.                             */
      /*                                                                       */
      LOCAL_FUNC
      FT_Error  T1_New_Table( T1_Table*  table,
                              FT_Int     count,
                              FT_Memory  memory )
      {
    	 FT_Error  error;
    
    
    	 table->memory = memory;
    
    	 if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) )
    		 return error;
    
    	 if ( ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
    	 {
    	   FREE( table->elements );
    	   return error;
    	}
    
    	table->max_elems = count;
    	table->num_elems = 0;
    
    	table->block        = 0;
    	table->capacity     = 0;
    	table->cursor       = 0;
    
    	return error;
      }
    
    
      static
      FT_Error  reallocate_t1_table( T1_Table*  table,
                                     FT_Int     new_size )
      {
        FT_Memory  memory   = table->memory;
        FT_Byte*   old_base = table->block;
        FT_Error   error;
    
    
        /* reallocate the base block */
        if ( REALLOC( table->block, table->capacity, new_size ) )
          return error;
        table->capacity = new_size;
    
        /* shift all offsets if necessary */
        if ( old_base )
        {
          FT_Long    delta  = table->block - old_base;
          FT_Byte**  offset = table->elements;
          FT_Byte**  limit  = offset + table->max_elems;
    
    
          if ( delta )
            for ( ; offset < limit; offset ++ )
              if (offset[0])
                offset[0] += delta;
        }
    
        return T1_Err_Ok;
      }
    
    
      /*************************************************************************/
      /*                                                                       */
      /* <Function>                                                            */
      /*    T1_Add_Table                                                       */
      /*                                                                       */
      /* <Description>                                                         */
      /*    Adds an object to a T1_Table, possibly growing its memory block.   */
      /*                                                                       */
      /* <InOut>                                                               */
      /*    table  :: The target table.                                        */
      /*                                                                       */
      /* <Input>                                                               */
      /*    index  :: 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 failed.                                               */
      /*                                                                       */
      LOCAL_FUNC
      FT_Error  T1_Add_Table( T1_Table*  table,
                              FT_Int     index,
                              void*      object,
                              FT_Int     length )
      {
    	if ( index < 0 || index > table->max_elems )
        {
    	  FT_ERROR(( "T1_Add_Table: invalid index\n" ));
    	  return T1_Err_Syntax_Error;
        }
    
        /* grow the base block if needed */
        if ( table->cursor + length > table->capacity )
        {
          FT_Error  error;
          FT_Int    new_size = table->capacity;
    
    
          while ( new_size < table->cursor + length )
            new_size += 1024;
    
          error = reallocate_t1_table( table, new_size );
          if ( error )
            return error;
        }
    
        /* add the object to the base block and adjust offset */
        table->elements[index] = table->block + table->cursor;
        table->lengths [index] = length;
        MEM_Copy( table->block + table->cursor, object, length );
    
        table->cursor += length;
    
        return T1_Err_Ok;
      }
    
    
      /*************************************************************************/
      /*                                                                       */
      /* <Function>                                                            */
      /*    T1_Done_Table                                                      */
      /*                                                                       */
      /* <Description>                                                         */
      /*    Finalize a T1_Table (reallocate it to its current cursor).         */
      /*                                                                       */
      /* <Input>                                                               */
      /*    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.  */
      /*                                                                       */
      LOCAL_FUNC
      void  T1_Done_Table( T1_Table*  table )
      {
        FT_Memory  memory = table->memory;
        FT_Error   error;
        FT_Byte*   old_base;
    
    
        /* should never fail, as rec.cursor <= rec.size */
        old_base = table->block;
        if ( !old_base )
          return;
    
        (void)REALLOC( table->block, table->capacity, table->cursor );
        table->capacity = table->cursor;
    
        if ( old_base != table->block )
        {
          FT_Long    delta   = table->block - old_base;
          FT_Byte**  element = table->elements;
          FT_Byte**  limit   = element + table->max_elems;
    
    
          for ( ; element < limit; element++ )
            if ( element[0] )
              element[0] += delta;
        }
      }
    
    
      LOCAL_FUNC
      FT_String*  CopyString( T1_Parser*  parser )
      {
        FT_String*  string = NULL;
        T1_Token*   token  = parser->args++;
        FT_Memory   memory = parser->tokenizer->memory;
        FT_Error    error;
    
    
        if ( token->kind == tok_string )
        {
          FT_Int  len = token->len - 2;
    
    
          if ( ALLOC( string, len + 1 ) )
          {
            parser->error = error;
            return 0;
          }
    
          MEM_Copy( string, parser->tokenizer->base + token->start + 1, len );
          string[len] = '\0';
    
          parser->error = T1_Err_Ok;
        }
        else
        {
          FT_ERROR(( "T1_CopyString: syntax error, string token expected!\n" ));
          parser->error = T1_Err_Syntax_Error;
        }
    
        return string;
      }
    
    
      static
      FT_Error  parse_int( FT_Byte*  base,
                           FT_Byte*  limit,
                           FT_Long*  result )
      {
        FT_Bool  sign = 0;
        FT_Long  sum  = 0;
    
    
        if ( base >= limit )
          goto Fail;
    
        /* check sign */
        if ( *base == '+' )
          base++;
    
        else if ( *base == '-' )
        {
          sign++;
          base++;
        }
    
        /* parse digits */
        if ( base >= limit )
          goto Fail;
    
        do
        {
          sum = ( 10 * sum + ( *base++ - '0' ) );
    
        } while ( base < limit );
    
        if ( sign )
          sum = -sum;
    
        *result = sum;
        return T1_Err_Ok;
    
      Fail:
        FT_ERROR(( "parse_int: integer expected\n" ));
        *result = 0;
        return T1_Err_Syntax_Error;
      }
    
    
      static
      FT_Error  parse_float( FT_Byte*  base,
                             FT_Byte*  limit,
                             FT_Long   scale,
                             FT_Long*  result )
      {
    #if 1
    
        /* XXX: We are simply much too lazy to code this function   */
        /*      properly for now.  We will do that when the rest of */
        /*      the driver works properly.                          */
        char    temp[32];
        int     len = limit - base;
        double  value;
    
    
        if ( len > 31 )
          goto Fail;
    
        strncpy( temp, (char*)base, len );
        temp[len] = '\0';
        if ( sscanf( temp, "%lf", &value ) != 1 )
          goto Fail;
    
        *result = (FT_Long)( scale * value );
        return 0;
    
    #else
    
        FT_Byte*  cur;
        FT_Bool   sign        = 0;  /* sign                        */
        FT_Long   number_int  = 0;  /* integer part                */
        FT_Long   number_frac = 0;  /* fractional part             */
        FT_Long   exponent    = 0;  /* exponent value              */
        FT_Int    num_frac    = 0;  /* number of fractional digits */
    
    
        /* check sign */
        if ( *base == '+' )
          base++;
    
        else if ( *base == '-' )
        {
          sign++;
          base++;
        }
    
        /* find integer part */
        cur = base;
        while ( cur < limit )
        {
          FT_Byte  c = *cur;
    
    
          if ( c == '.' || c == 'e' || c == 'E' )
            break;
    
          cur++;
        }
    
        if ( cur > base )
        {
          error = parse_integer( base, cur, &number_int );
          if ( error )
            goto Fail;
        }
    
        /* read fractional part, if any */
        if ( *cur == '.' )
        {
          cur++;
          base = cur;
          while ( cur < limit )
          {
            FT_Byte  c = *cur;
    
    
            if ( c == 'e' || c == 'E' )
              break;
            cur++;
          }
    
          num_frac = cur - base;
    
          if ( cur > base )
          {
            error = parse_integer( base, cur, &number_frac );
            if ( error )
              goto Fail;
            base = cur;
          }
       }
    
        /* read exponent, if any */
        if ( *cur == 'e' || *cur == 'E' )
        {
          cur++;
          base = cur;
          error = parse_integer( base, limit, &exponent );
          if ( error )
            goto Fail;
    
          /* now check that exponent is within `correct bounds' */
          /* i.e. between -6 and 6                              */
          if ( exponent < -6 || exponent > 6 )
            goto Fail;
        }
    
        /* now adjust integer value and exponent for fractional part */
        while ( num_frac > 0 )
        {
          number_int *= 10;
          exponent--;
          num_frac--;
        }
    
        number_int += num_frac;
    
        /* skip point if any, read fractional part */
        if ( cur + 1 < limit )
        {
          if (*cur..
        }
    
        /* now compute scaled float value */
        /* XXX: incomplete!               */
    
    #endif /* 1 */
    
      Fail:
        FT_ERROR(( "parse_float: syntax error!\n" ));
        return T1_Err_Syntax_Error;
      }
    
    
      static
      FT_Error  parse_integer( FT_Byte*  base,
                               FT_Byte*  limit,
                               FT_Long*  result )
      {
        FT_Byte*  cur;
    
    
        /* the lexical analyser accepts floats as well as integers */
        /* now; check that we really have an int in this token     */
        cur = base;
        while ( cur < limit )
        {
          FT_Byte  c = *cur++;
    
    
          if ( c == '.' || c == 'e' || c == 'E' )
            goto Float_Number;
        }
    
        /* now read the number's value */
        return parse_int( base, limit, result );
    
      Float_Number:
        /* we really have a float there; simply call parse_float in this */
        /* case with a scale of `10' to perform round                    */
        {
          FT_Error error;
    
    
          error = parse_float( base, limit, 10, result );
          if ( !error )
          {
            if ( *result >= 0 )
              *result = ( *result + 5 ) / 10;      /* round value */
            else
              *result = -( ( 5 - *result ) / 10 );
          }
          return error;
        }
      }
    
    
      LOCAL_FUNC
      FT_Long  CopyInteger( T1_Parser*  parser )
      {
        FT_Long    sum   = 0;
        T1_Token*  token = parser->args++;
    
    
        if ( token->kind == tok_number )
        {
          FT_Byte*  base  = parser->tokenizer->base + token->start;
          FT_Byte*  limit = base + token->len;
    
    
          /* now read the number's value */
          parser->error = parse_integer( base, limit, &sum );
          return sum;
        }
    
        FT_ERROR(( "CopyInteger: number expected\n" ));
        parser->args--;
        parser->error = T1_Err_Syntax_Error;
        return 0;
      }
    
    
      LOCAL_FUNC
      FT_Bool   CopyBoolean( T1_Parser*  parser )
      {
        FT_Error   error  = T1_Err_Ok;
        FT_Bool    result = 0;
        T1_Token*  token  = parser->args++;
    
    
        if ( token->kind == tok_keyword )
        {
          if ( token->kind2 == key_false )
            result = 0;
    
          else if ( token->kind2 == key_true )
            result = !0;
    
          else
            goto Fail;
        }
        else
        {
          Fail:
            FT_ERROR(( "CopyBoolean:" ));
            FT_ERROR(( " syntax error; `false' or `true' expected\n" ));
            error = T1_Err_Syntax_Error;
        }
        parser->error = error;
        return result;
      }
    
    
      LOCAL_FUNC
      FT_Long   CopyFloat( T1_Parser*  parser,
                           FT_Int      scale )
      {
        FT_Error   error;
        FT_Long    sum = 0;
        T1_Token*  token = parser->args++;
    
    
        if ( token->kind == tok_number )
        {
          FT_Byte*  base  = parser->tokenizer->base + token->start;
          FT_Byte*  limit = base + token->len;
    
    
          error = parser->error = parse_float( base, limit, scale, &sum );
          if ( error )
            goto Fail;
    
          return sum;
        }
    
      Fail:
        FT_ERROR(( "CopyFloat: syntax error!\n" ));
        parser->error = T1_Err_Syntax_Error;
        return 0;
      }
    
    
      LOCAL_FUNC
      void  CopyBBox( T1_Parser*  parser,
                      FT_BBox*    bbox )
      {
        T1_Token*  token = parser->args++;
        FT_Int     n;
        FT_Error   error;
    
    
        if ( token->kind == tok_program ||
             token->kind == tok_array   )
        {
          /* get rid of `['/`]', or `{'/`}' */
          FT_Byte*  base  = parser->tokenizer->base + token->start + 1;
          FT_Byte*  limit = base + token->len - 2;
          FT_Byte*  cur;
          FT_Byte*  start;
    
    
          /* read each parameter independently */
          cur = base;
          for ( n = 0; n < 4; n++ )
          {
            FT_Long*  result;
    
    
            /* skip whitespace */
            while ( cur < limit && *cur == ' ' )
              cur++;
    
            /* skip numbers */
            start = cur;
            while ( cur < limit && *cur != ' ' )
              cur++;
    
            /* compute result address */
            switch ( n )
            {
            case 0:
              result = &bbox->xMin;
              break;
            case 1:
              result = &bbox->yMin;
              break;
            case 2:
              result = &bbox->xMax;
              break;
            default:
              result = &bbox->yMax;
            }
    
            error = parse_integer( start, cur, result );
            if ( error )
              goto Fail;
          }
          parser->error = 0;
          return;
        }
    
      Fail:
        FT_ERROR(( "CopyBBox: syntax error!\n" ));
        parser->error = T1_Err_Syntax_Error;
      }
    
    
      LOCAL_FUNC
      void  CopyMatrix( T1_Parser*  parser,
                        FT_Matrix*  matrix )
      {
        T1_Token* token = parser->args++;
        FT_Error  error;
    
    
        if ( token->kind == tok_array )
        {
          /* get rid of `[' and `]' */
          FT_Byte*  base  = parser->tokenizer->base + token->start + 1;
          FT_Byte*  limit = base + token->len - 2;
          FT_Byte*  cur;
          FT_Byte*  start;
          FT_Int    n;
    
    
          /* read each parameter independently */
          cur = base;
          for ( n = 0; n < 4; n++ )
          {
            FT_Long*  result;
    
    
            /* skip whitespace */
            while ( cur < limit && *cur == ' ' )
              cur++;
    
            /* skip numbers */
            start = cur;
            while ( cur < limit && *cur != ' ')
              cur++;
    
            /* compute result address */
            switch ( n )
            {
            case 0:
              result = &matrix->xx;
              break;
            case 1:
              result = &matrix->yx;
              break;
            case 2:
              result = &matrix->xy;
              break;
            default:
              result = &matrix->yy;
            }
    
            error = parse_float( start, cur, 65536000L, result );
            if ( error )
              goto Fail;
          }
          parser->error = 0;
          return;
        }
    
      Fail:
        FT_ERROR(( "CopyMatrix: syntax error!\n" ));
        parser->error = T1_Err_Syntax_Error;
      }
    
    
      LOCAL_FUNC
      void  CopyArray( T1_Parser*  parser,
                       FT_Byte*    num_elements,
                       FT_Short*   elements,
                       FT_Int      max_elements )
      {
        T1_Token* token = parser->args++;
        FT_Error  error;
    
    
        if ( token->kind == tok_array   ||
             token->kind == tok_program )   /* in the case of MinFeature */
        {
          /* get rid of `['/`]', or `{'/`}' */
          FT_Byte*  base  = parser->tokenizer->base + token->start + 1;
          FT_Byte*  limit = base + token->len - 2;
          FT_Byte*  cur;
          FT_Byte*  start;
          FT_Int    n;
    
    
          /* read each parameter independently */
          cur = base;
          for ( n = 0; n < max_elements; n++ )
          {
            FT_Long  result;
    
    
            /* test end of string */
            if ( cur >= limit )
              break;
    
            /* skip whitespace */
            while ( cur < limit && *cur == ' ' )
              cur++;
    
            /* end of list? */
            if ( cur >= limit )
              break;
    
            /* skip numbers */
            start = cur;
            while ( cur < limit && *cur != ' ' )
              cur++;
    
            error = parse_integer( start, cur, &result );
            if ( error )
              goto Fail;
    
            *elements++ = (FT_Short)result;
          }
    
          if ( num_elements )
            *num_elements = (FT_Byte)n;
    
          parser->error = 0;
          return;
        }
    
      Fail:
        FT_ERROR(( "CopyArray: syntax error!\n" ));
        parser->error = T1_Err_Syntax_Error;
      }
    
    
    /* END */