shithub: freetype+ttf2subf

Download patch

ref: e57ca7dec6a41dcf26c9551525d3645d1d73ab86
parent: 60b32e16e75cd3387160487693a24b61b08684b6
author: David Turner <[email protected]>
date: Wed Nov 6 20:36:29 EST 2002

* src/otlayout/otlayout.h, src/otlyaout/otlconf.h,
        src/otlayout/otlgsub.c, src/otlayout/otlgsub.h, src/otlayout/otlparse.c,
        src/otlayout/otlparse.h, src/otlayout/otlutils.h:

          updating the OpenType Layout code, adding support fot the first
          GSUB lookups. Nothing that really compiles for now though

        * src/autohint/ahhint.c: disabled serif stem width quantization. It
        produces slightly better shapes though this is not distinguishable
        with many fonts.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2002-11-07  David Turner  <[email protected]>
+
+        * src/otlayout/otlayout.h, src/otlyaout/otlconf.h,
+        src/otlayout/otlgsub.c, src/otlayout/otlgsub.h, src/otlayout/otlparse.c,
+        src/otlayout/otlparse.h, src/otlayout/otlutils.h:
+
+          updating the OpenType Layout code, adding support fot the first
+          GSUB lookups. Nothing that really compiles for now though
+
 2002-11-05  David Turner  <[email protected]>
 
         * include/freetype/config/ftoption.h, src/gzip/ftgzip.c: added
--- a/src/otlayout/otlayout.h
+++ b/src/otlayout/otlayout.h
@@ -24,9 +24,13 @@
   typedef int               OTL_Int;
   typedef unsigned int      OTL_UInt;
 
+  typedef long              OTL_Long;
+  typedef unsigned long     OTL_ULong;
+
   typedef short             OTL_Int16;
   typedef unsigned short    OTL_UInt16;
 
+
 #if OTL_SIZEOF_INT == 4
 
   typedef int               OTL_Int32;
@@ -58,6 +62,8 @@
     OTL_Err_InvalidFormat,
     OTL_Err_InvalidOffset,
 
+    OTL_Err_Max
+
   } OTL_Error;
 
 
@@ -64,16 +70,47 @@
  /************************************************************************/
  /************************************************************************/
  /*****                                                              *****/
+ /*****                     MEMORY MANAGEMENT                        *****/
+ /*****                                                              *****/
+ /************************************************************************/
+ /************************************************************************/
+
+  typedef OTL_Pointer  (*OTL_AllocFunc)( OTL_ULong    size,
+                                         OTL_Pointer  data );
+
+  typedef OTL_Pointer  (*OTL_ReallocFunc)( OTL_Pointer   block,
+                                           OTL_ULong     size,
+                                           OTL_Pointer   data );
+
+  typedef void         (*OTL_FreeFunc)( OTL_Pointer  block,
+                                        OTL_Pointer  data );
+
+  typedef struct OTL_MemoryRec_
+  {
+    OTL_Pointer      mem_data;
+    OTL_AllocFunc    mem_alloc;
+    OTL_ReallocFunc  mem_realloc;
+    OTL_FreeFunc     mem_free;
+
+  } OTL_MemoryRec, *OTL_Memory;
+
+ /************************************************************************/
+ /************************************************************************/
+ /*****                                                              *****/
  /*****                        ENUMERATIONS                          *****/
  /*****                                                              *****/
  /************************************************************************/
  /************************************************************************/
 
+/* re-define OTL_MAKE_TAG to something different if you're not */
+/* using an ASCII-based character set (Vaxes anyone ?)         */
+#ifndef  OTL_MAKE_TAG
 #define  OTL_MAKE_TAG(c1,c2,c3,c4)         \
            ( ( (OTL_UInt32)(c1) << 24 ) |  \
                (OTL_UInt32)(c2) << 16 ) |  \
                (OTL_UInt32)(c3) <<  8 ) |  \
                (OTL_UInt32)(c4)         )
+#endif
 
   typedef enum OTL_ScriptTag_
   {
@@ -153,8 +190,8 @@
 
 #define  OTL_INVALID(e)  otl_validator_error( valid, e )
 
-#define  OTL_INVALID_TOO_SHORT  OTL_INVALID( OTL_Err_InvalidOffset );
-#define  OTL_INVALID_DATA       OTL_INVALID( OTL_Err_InvalidFormat );
+#define  OTL_INVALID_TOO_SHORT  OTL_INVALID( OTL_Err_InvalidOffset )
+#define  OTL_INVALID_DATA       OTL_INVALID( OTL_Err_InvalidFormat )
 
 #define  OTL_CHECK(_count)   OTL_BEGIN_STMNT                       \
                                if ( p + (_count) > valid->limit )  \
--- a/src/otlayout/otlconf.h
+++ b/src/otlayout/otlconf.h
@@ -43,10 +43,10 @@
 
 #define  OTL_BEGIN_STMNT  do {
 #define  OTL_END_STMNT    } while (0)
-#define  OTL_DUMMY_STMNT  do { } while (0)
+#define  OTL_DUMMY_STMNT  OTL_BEGIN_STMNT OTL_END_STMNT
 
 #define  OTL_UNUSED( x )       (x)=(x)
-#define  OTL_UNUSED_CONST(x)  (void)(x)
+#define  OTL_UNUSED_CONST(x)   (void)(x)
 
 
 #include <limits.h>
@@ -67,6 +67,11 @@
 #else
 #  error  "unsupported number of bytes in 'long' type!"
 #endif
+
+#include <setjmp.h>
+#define  OTL_jmp_buf   jmp_buf
+#define  otl_setjmp    setjmp
+#define  otl_longjmp   longjmp
 
 /* */
 
--- a/src/otlayout/otlgsub.c
+++ b/src/otlayout/otlgsub.c
@@ -9,6 +9,28 @@
  /************************************************************************/
  /************************************************************************/
 
+ /*
+  *  1: Single Substitution - Table format(s)
+  *
+  *  This table is used to substiture individual glyph indices
+  *  with another one. There are only two sub-formats:
+  *
+  *   Name         Offset    Size       Description
+  *   ------------------------------------------
+  *   format       0         2          sub-table format (1)
+  *   offset       2         2          offset to coverage table
+  *   delta        4         2          16-bit delta to apply on all
+  *                                     covered glyph indices
+  *
+  *   Name         Offset    Size       Description
+  *   ------------------------------------------
+  *   format       0         2          sub-table format (2)
+  *   offset       2         2          offset to coverage table
+  *   count        4         2          coverage table count
+  *   substs[]     6         2*count    substituted glyph indices,
+  *
+  */
+
   static void
   otl_gsub_lookup1_validate( OTL_Bytes      table,
                              OTL_Validator  valid )
@@ -42,6 +64,10 @@
           otl_coverage_validate( table + coverage, valid );
 
           OTL_CHECK( 2*count );
+
+          /* NB: we don't check that there are at most 'count'   */
+          /*     elements in the coverage table. This is delayed */
+          /*     to the lookup function...                       */
         }
         break;
 
@@ -51,6 +77,63 @@
   }
 
 
+  static OTL_Bool
+  otl_gsub_lookup1_apply( OTL_Bytes   table,
+                          OTL_Parser  parser )
+  {
+    OTL_Bytes  p = table;
+    OTL_Bytes  coverage;
+    OTL_UInt   format, gindex, property;
+    OTL_Int    index;
+    OTL_Bool   subst = 0;
+
+    if ( parser->context_len != 0xFFFF && parser->context_len < 1 )
+      goto Exit;
+
+    gindex = otl_parser_get_gindex( parser );
+
+    if ( !otl_parser_check_property( parser, gindex, &property ) )
+      goto Exit;
+
+    format   = OTL_NEXT_USHORT(p);
+    coverage = table + OTL_NEXT_USHORT(p);
+    index    = otl_coverage_lookup( coverage, gindex );
+
+    if ( index >= 0 )
+    {
+      switch ( format )
+      {
+        case 1:
+          {
+            OTL_Int  delta = OTL_NEXT_SHORT(p);
+
+            gindex = ( gindex + delta ) & 0xFFFF;
+            otl_parser_replace_1( parser, gindex );
+            subst = 1;
+          }
+          break;
+
+        case 2:
+          {
+            OTL_UInt  count = OTL_NEXT_USHORT(p);
+
+            if ( (OTL_UInt) index < count )
+            {
+              p += index*2;
+              otl_parser_replace_1( parser, OTL_PEEK_USHORT(p) );
+              subst = 1;
+            }
+          }
+          break;
+
+        default:
+          ;
+      }
+    }
+  Exit:
+    return subst;
+  }
+
  /************************************************************************/
  /************************************************************************/
  /*****                                                              *****/
@@ -59,6 +142,26 @@
  /************************************************************************/
  /************************************************************************/
 
+ /*
+  *  2: Multiple Substitution - Table format(s)
+  *
+  *  Replaces a single glyph with one or more glyphs.
+  *
+  *   Name         Offset    Size       Description
+  *   -----------------------------------------------------------
+  *   format       0         2          sub-table format (1)
+  *   offset       2         2          offset to coverage table
+  *   count        4         2          coverage table count
+  *   sequencess[] 6         2*count    offsets to sequence items
+  *
+  *   each sequence item has the following format:
+  *
+  *   Name         Offset    Size       Description
+  *   -----------------------------------------------------------
+  *   count        0         2          number of replacement glyphs
+  *   gindices[]   2         2*count    string of glyph indices
+  */
+
   static void
   otl_seq_validate( OTL_Bytes      table,
                     OTL_Validator  valid )
@@ -69,6 +172,9 @@
     OTL_CHECK( 2 );
     count = OTL_NEXT_USHORT( p );
 
+    /* XXX: according to the spec, 'count' should be > 0     */
+    /*      we can deal with these cases pretty well however */
+
     OTL_CHECK( 2*count );
     /* check glyph indices */
   }
@@ -106,6 +212,45 @@
     }
   }
 
+
+  static OTL_Bool
+  otl_gsub_lookup2_apply( OTL_Bytes    table,
+                          OTL_Parser   parser )
+  {
+    OTL_Bytes  p = table;
+    OTL_Bytes  coverage, sequence;
+    OTL_UInt   format, gindex, index, property;
+    OTL_Int    index;
+    OTL_Bool   subst = 0;
+
+    if ( context_len != 0xFFFF && context_len < 1 )
+      goto Exit;
+
+    gindex = otl_parser_get_gindex( parser );
+
+    if ( !otl_parser_check_property( parser, gindex, &property ) )
+      goto Exit;
+
+    p        += 2;  /* skip format */
+    coverage  = table + OTL_NEXT_USHORT(p);
+    seq_count = OTL_NEXT_USHORT(p);
+    index     = otl_coverage_lookup( coverage, gindex );
+
+    if ( (OTL_UInt) index >= seq_count )
+      goto Exit;
+
+    p       += index*2;
+    sequence = table + OTL_PEEK_USHORT(p);
+    p        = sequence;
+    count    = OTL_NEXT_USHORT(p);
+
+    otl_parser_replace_n( parser, count, p );
+    subst = 1;
+
+   Exit:
+    return subst;
+  }
+
  /************************************************************************/
  /************************************************************************/
  /*****                                                              *****/
@@ -114,6 +259,28 @@
  /************************************************************************/
  /************************************************************************/
 
+ /*
+  *  3: Alternate Substitution - Table format(s)
+  *
+  *  Replaces a single glyph by another one taken liberally
+  *  in a list of alternatives
+  *
+  *   Name         Offset    Size       Description
+  *   -----------------------------------------------------------
+  *   format       0         2          sub-table format (1)
+  *   offset       2         2          offset to coverage table
+  *   count        4         2          coverage table count
+  *   alternates[] 6         2*count    offsets to alternate items
+  *
+  *   each alternate item has the following format:
+  *
+  *   Name         Offset    Size       Description
+  *   -----------------------------------------------------------
+  *   count        0         2          number of replacement glyphs
+  *   gindices[]   2         2*count    string of glyph indices, each one
+  *                                     is a valid alternative
+  */
+
   static void
   otl_alternate_set_validate( OTL_Bytes      table,
                               OTL_Validator  valid )
@@ -161,6 +328,52 @@
     }
   }
 
+
+  static OTL_Bool
+  otl_gsub_lookup3_apply( OTL_Bytes    table,
+                          OTL_Parser   parser )
+  {
+    OTL_Bytes  p = table;
+    OTL_Bytes  coverage, alternates;
+    OTL_UInt   format, gindex, index, property;
+    OTL_Int    index;
+    OTL_Bool   subst = 0;
+
+    OTL_GSUB_Alternate  alternate = parser->alternate;
+
+    if ( context_len != 0xFFFF && context_len < 1 )
+      goto Exit;
+
+    if ( alternate == NULL )
+      goto Exit;
+
+    gindex = otl_parser_get_gindex( parser );
+
+    if ( !otl_parser_check_property( parser, gindex, &property ) )
+      goto Exit;
+
+    p        += 2;  /* skip format */
+    coverage  = table + OTL_NEXT_USHORT(p);
+    seq_count = OTL_NEXT_USHORT(p);
+    index     = otl_coverage_lookup( coverage, gindex );
+
+    if ( (OTL_UInt) index >= seq_count )
+      goto Exit;
+
+    p         += index*2;
+    alternates = table + OTL_PEEK_USHORT(p);
+    p          = alternates;
+    count      = OTL_NEXT_USHORT(p);
+
+    gindex = alternate->handler_func(
+                 gindex, count, p, alternate->handler_data );
+
+    otl_parser_replace_1( parser, gindex );
+    subst = 1;
+
+   Exit:
+    return subst;
+  }
 
  /************************************************************************/
  /************************************************************************/
--- a/src/otlayout/otlgsub.h
+++ b/src/otlayout/otlgsub.h
@@ -5,6 +5,18 @@
 
 OTL_BEGIN_HEADER
 
+  typedef OTL_UInt  (*OTL_GSUB_AlternateFunc)( OTL_UInt     gindex,
+                                               OTL_UInt     count,
+                                               OTL_Bytes    alternates,
+                                               OTL_Pointer  data );
+
+  typedef struct OTL_GSUB_AlternateRec_
+  {
+    OTL_GSUB_AlternateFunc  handler_func;
+    OTL_Pointer             handler_data;
+
+  } OTL_GSUB_AlternateRec, *OTL_GSUB_Alternate;
+
   OTL_LOCAL( void )
   otl_gsub_validate( OTL_Bytes      table,
                      OTL_Validator  valid );
--- /dev/null
+++ b/src/otlayout/otlparse.c
@@ -1,0 +1,142 @@
+#include "otlparse.h"
+#include "otlutils.h"
+
+  static void
+  otl_string_ensure( OTL_String  string,
+                     OTL_UInt    count,
+                     OTL_Parser  parser )
+  {
+    count += string->length;
+
+    if ( count > string->capacity )
+    {
+      OTL_UInt    old_count = string->capacity;
+      OTL_UInt    new_count = old_count;
+      OTL_Memory  memory    = parser->memory;
+
+      while ( new_count < count )
+        new_count += (new_count >> 1) + 16;
+
+      if ( OTL_MEM_RENEW_ARRAY( string->glyphs, old_count, new_count ) )
+        otl_parser_error( parser, OTL_Parse_Err_Memory );
+
+      string->capacity = new_count;
+    }
+  }
+
+#define  OTL_STRING_ENSURE(str,count,parser)                   \
+           OTL_BEGIN_STMNT                                     \
+             if ( (str)->length + (count) > (str)>capacity )   \
+               otl_string_ensure( str, count, parser );        \
+           OTL_END_STMNT
+
+
+  OTL_LOCALDEF( OTL_UInt )
+  otl_parser_get_gindex( OTL_Parser  parser )
+  {
+    OTL_String  in = parser->str_in;
+
+    if ( in->cursor >= in->num_glyphs )
+      otl_parser_error( parser, OTL_Err_Parser_Internal );
+
+    return in->str[ in->cursor ].gindex;
+  }
+
+
+  OTL_LOCALDEF( void )
+  otl_parser_error( OTL_Parser      parser,
+                    OTL_ParseError  error; )
+  {
+    parser->error = error;
+    otl_longjmp( parser->jump_buffer, 1 );
+  }
+
+#define  OTL_PARSER_UNCOVERED(x)  otl_parser_error( x, OTL_Parse_Err_UncoveredGlyph );
+
+  OTL_LOCAL( void )
+  otl_parser_check_property( OTL_Parser  parser,
+                             OTL_UInt    gindex,
+                             OTL_UInt    flags,
+                             OTL_UInt   *aproperty );
+
+  OTL_LOCALDEF( void )
+  otl_parser_replace_1( OTL_Parser  parser,
+                        OTL_UInt    gindex )
+  {
+    OTL_String       in  = parser->str_in;
+    OTL_String       out = parser->str_out;
+    OTL_StringGlyph  glyph, in_glyph;
+
+    /* sanity check */
+    if ( in == NULL               ||
+         out == NULL              ||
+         in->length == 0          ||
+         in->cursor >= in->length )
+    {
+      /* report as internal error, since these should */
+      /* never happen !!                              */
+      otl_parser_error( parser, OTL_Err_Parse_Internal );
+    }
+
+    OTL_STRING_ENSURE( out, 1, parser );
+    glyph    = out->glyphs + out->length;
+    in_glyph = in->glyphs  + in->cursor;
+
+    glyph->gindex        = gindex;
+    glyph->property      = in_glyph->property;
+    glyph->lig_component = in_glyph->lig_component;
+    glyph->lig_id        = in_glyph->lig_id;
+
+    out->length += 1;
+    out->cursor  = out->length;
+    in->cursor  += 1;
+  }
+
+  OTL_LOCALDEF( void )
+  otl_parser_replace_n( OTL_Parser  parser,
+                        OTL_UInt    count,
+                        OTL_Bytes   indices )
+  {
+    OTL_UInt         lig_component, lig_id, property;
+    OTL_String       in  = parser->str_in;
+    OTL_String       out = parser->str_out;
+    OTL_StringGlyph  glyph, in_glyph;
+    OTL_Bytes        p = indices;
+
+    /* sanity check */
+    if ( in == NULL               ||
+         out == NULL              ||
+         in->length == 0          ||
+         in->cursor >= in->length )
+    {
+      /* report as internal error, since these should */
+      /* never happen !!                              */
+      otl_parser_error( parser, OTL_Err_Parse_Internal );
+    }
+
+    OTL_STRING_ENSURE( out, count, parser );
+    glyph    = out->glyphs + out->length;
+    in_glyph = in->glyphs  + in->cursor;
+
+    glyph->gindex = gindex;
+
+    lig_component = in_glyph->lig_component;
+    lig_id        = in_glyph->lid_id;
+    property      = in_glyph->property;
+
+    for ( ; count > 0; count-- )
+    {
+      glyph->gindex        = OTL_NEXT_USHORT(p);
+      glyph->property      = property;
+      glyph->lig_component = lig_component;
+      glyph->lig_id        = lig_id;
+
+      out->length ++;
+    }
+
+    out->cursor  = out->length;
+    in->cursor  += 1;
+  }
+
+
+
--- /dev/null
+++ b/src/otlayout/otlparse.h
@@ -1,0 +1,99 @@
+#ifndef __OTL_PARSER_H__
+#define __OTL_PARSER_H__
+
+#include "otlayout.h"
+#include "otlgdef.h"
+#include "otlgsub.h"
+#include "otlgpos.h"
+
+OTL_BEGIN_HEADER
+
+  typedef struct OTL_ParserRec_*   OTL_Parser;
+
+  typedef struct OTL_StringRec_*   OTL_String;
+
+  typedef struct OTL_StringGlyphRec_
+  {
+    OTL_UInt  gindex;
+    OTL_UInt  properties;
+    OTL_UInt  lig_component;
+    OTL_UInt  lig_id;
+
+  } OTL_StringGlyphRec, *OTL_StringGlyph;
+
+  typedef struct OTL_StringRec_
+  {
+    OTL_StringGlyph  glyphs;
+    OTL_UInt         cursor;
+    OTL_UInt         length;
+    OTL_UInt         capacity;
+
+  } OTL_StringRec;
+
+  typedef struct OTL_ParserRec_
+  {
+    OTL_Bytes      tab_gdef;
+    OTL_Bytes      tab_gsub;
+    OTL_Bytes      tab_gpos;
+    OTL_Bytes      tab_base;
+    OTL_Bytes      tab_jstf;
+
+    OTL_Alternate  alternate;  /* external alternate handler */
+
+    OTL_UInt       context_len;
+    OTL_UInt       markup_flags;
+
+    OTL_jmp_buf    jump_buffer;
+    OTL_Memory     memory;
+    OTL_Error      error;
+
+    OTL_StringRec  strings[2];
+    OTL_String     str_in;
+    OTL_String     str_out;
+
+  } OTL_ParserRec;
+
+  typedef enum
+  {
+    OTL_Err_Parser_Ok = 0,
+    OTL_Err_Parser_InvalidData,
+    OTL_Err_Parser_UncoveredGlyph
+
+  } OTL_ParseError;
+
+  OTL_LOCAL( OTL_UInt )
+  otl_parser_get_gindex( OTL_Parser  parser );
+
+
+  OTL_LOCAL( void )
+  otl_parser_error( OTL_Parser  parser, OTL_ParserError  error );
+
+#define  OTL_PARSER_UNCOVERED(x)  \
+           otl_parser_error( x, OTL_Err_Parser_UncoveredGlyph )
+
+  OTL_LOCAL( void )
+  otl_parser_check_property( OTL_Parser  parser,
+                             OTL_UInt    gindex,
+                             OTL_UInt    flags,
+                             OTL_UInt   *aproperty );
+
+ /* copy current input glyph to output */
+  OTL_LOCAL( void )
+  otl_parser_copy_1( OTL_Parser  parser );
+
+ /* copy current input glyph to output, replacing its index */
+  OTL_LOCAL( void )
+  otl_parser_replace_1( OTL_Parser  parser,
+                        OTL_UInt    gindex );
+
+ /* copy current input glyph to output, replacing it by several indices */
+ /* read directly from the table                                        */
+  OTL_LOCAL( void )
+  otl_parser_replace_n( OTL_Parser  parser,
+                        OTL_UInt    count,
+                        OTL_Bytes   indices );
+
+OTL_END_HEADER
+
+#endif /* __OTL_PARSER_H__ */
+
--- /dev/null
+++ b/src/otlayout/otlutils.h
@@ -1,0 +1,33 @@
+#ifndef __OTLAYOUT_UTILS_H__
+#define __OTLAYOUT_UTILS_H__
+
+#include "otlayout.h"
+
+OTL_BEGIN_HEADER
+
+  OTL_LOCAL( OTL_Error )
+  otl_mem_alloc( OTL_Pointer*  pblock,
+                 OTL_ULong     size,
+                 OTL_Memory    memory );
+
+  OTL_LOCAL( void )
+  otl_mem_free( OTL_Pointer*  pblock,
+                OTL_Memory    memory );
+
+  OTL_LOCAL( OTL_Error )
+  otl_mem_realloc( OTL_Pointer  *pblock,
+                   OTL_ULong     cur_size,
+                   OTL_ULong     new_size,
+                   OTL_Memory    memory );
+
+#define  OTL_MEM_ALLOC(p,s)       otl_mem_alloc( (void**)&(p), (s), memory )
+#define  OTL_MEM_FREE(p)          otl_mem_free( (void**)&(p), memory )
+#define  OTL_MEM_REALLOC(p,c,n)   otl_mem_realloc( (void**)&(p), (c), (s), memory )
+
+#define  OTL_MEM_NEW(p)   OTL_MEM_ALLOC(p,sizeof(*(p)))
+#define  OTL_MEM_NEW_ARRAY(p,c)  OTL_MEM_ALLOC(p,(c)*sizeof(*(p)))
+#define  OTL_MEM_RENEW_ARRAY(p,c,n)  OTL_MEM_REALLOC(p,(c)*sizeof(*(p)),(n)*sizeof(*(p)))
+
+OTL_END_HEADER
+
+#endif /* __OTLAYOUT_UTILS_H__ */