]> git.saurik.com Git - wxWidgets.git/blobdiff - src/freetype/type1/t1parse.c
Added FreeType II beta 8.
[wxWidgets.git] / src / freetype / type1 / t1parse.c
diff --git a/src/freetype/type1/t1parse.c b/src/freetype/type1/t1parse.c
new file mode 100644 (file)
index 0000000..8b7ca25
--- /dev/null
@@ -0,0 +1,761 @@
+/***************************************************************************/
+/*                                                                         */
+/*  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 */