shithub: freetype+ttf2subf

Download patch

ref: 18789bfe9f5b350b37fe5e9fbca36393d5dd777a
parent: dbe4872bf0e21a88303cad237c931ea224633007
author: David Turner <[email protected]>
date: Tue Feb 15 07:53:31 EST 2000

Added prototype OpenType Layout support
sources. This is not a port of the OTL extension
of FT 1.x, as it uses a very different design.

These sources are placed here for comments
and peer-review

git/fs: mount .git/fs: mount/attach disallowed
--- /dev/null
+++ b/src/otlayout/oltypes.c
@@ -1,0 +1,496 @@
+#include <oltypes.h>
+
+  LOCAL_FUNC
+  TT_Error  OTL_Table_Init( OTL_Table*  table,
+                            FT_Memory   memory )
+  {
+    MEM_Set( table, 0, sizeof(*table) );
+    table->memory = memory;
+  }
+
+ /* read a script list table */
+ /* use with any table       */
+  LOCAL_FUNC
+  TT_Error  OTL_Table_Set_Scripts( OTL_Table*  table,
+                                   TT_Byte*    bytes,
+                                   TT_Long     len,
+                                   OTL_Type    otl_type )
+  {
+    TT_Byte*  p;
+    TT_Byte*  start = bytes;
+    TT_UInt   count, max_langs;
+    TT_Error  error;
+
+    /* skip version of the JSTF table */    
+    if (otl_type == otl_jstf)
+      start += 4;
+      
+    p = start;
+      
+    /* we must allocate the script_tags and language_tags arrays     */
+    /* this requires that we compute the maximum number of languages */
+    /* per script..                                                  */
+    
+    count     = table->num_scripts = OTL_UShort(p);
+    max_langs = 0;
+    for ( ; count > 0; count++ )
+    {
+      TT_Byte*  script;
+      TT_UInt   num_langs;
+      
+      p += 4; /* skip tag */
+      script = bytes + OTL_UShort(p);
+
+      /* skip the baseValues or extenders field of the BASE and JSTF table */
+      if (otl_type == otl_type_base || otl_type == otl_type_jstf)
+        script += 2;
+
+      /* test if there is a default language system */
+      if ( OTL_UShort(script) )
+        num_langs++;
+      
+      /* test other language systems */
+      num_langs += OTL_UShort(script); /* add other lang sys */
+      
+      if (num_langs > max_langs)
+        max_langs = num_langs;
+    }
+
+    /* good, now allocate the tag arrays */
+    if ( !ALLOC_ARRAY( table->script_tags,
+                      table->num_scripts + max_langs,
+                      TT_ULong ) )
+    {
+      table->language_tags = table->script_tags + table->num_scripts;
+      table->max_languages = max_langs;
+      table->num_languages = 0;
+      table->otl_type      = otl_type;
+  
+      table->scripts_table = bytes;
+      table->scripts_len   = len;
+      
+      /* fill the script_tags array */
+      {
+        TT_UInt  n;
+        TT_Byte* p = start + 2; /* skip count */
+        
+        for ( n = 0; n < table->num_scripts; n++ )
+        {
+          table->script_tags[n] = OTL_ULong(p);
+          p += 2; /* skip offset */
+        }
+      }
+    }
+    return error;
+  }
+
+
+
+ /* add a features list to the table   */
+ /* use only with a GSUB or GPOS table */
+  LOCAL_FUNC
+  TT_Error  OTL_Table_Set_Features( OTL_Table*  table,
+                                    TT_Byte*    bytes,
+                                    TT_Long     len )
+  {
+    TT_Error  error;
+    TT_Byte*  p = bytes;
+    TT_UInt   count;
+    
+    table->max_features = count = OTL_UShort(p);
+    if ( !ALLOC_ARRAY( table->feature_tags, count, TT_ULong ) &&
+         !ALLOC_ARRAY( table->features,     count, TT_Bool  ) )
+    {
+      table->features_table = bytes;
+      table->features_len   = len;
+    }
+    return error;     
+  }
+
+
+ /* add a lookup list to the table     */
+ /* use only with a GSUB or GPOS table */
+  LOCAL_FUNC
+  TT_Error  OTL_Table_Set_Lookups( OTL_Table*  table,
+                                   TT_Byte*    bytes,
+                                   TT_Long     len )
+  {
+    TT_Error  error;
+    TT_Byte*  p = bytes;
+    TT_UInt   count;
+    
+    table->max_lookups = count = OTL_UShort(p);
+    if ( !ALLOC_ARRAY( table->lookups, count, TT_Bool ) )
+    {
+      table->lookups_table = bytes;
+      table->lookups_len   = len;
+    }
+    return error;     
+  }
+
+ /* discard table arrays */
+  LOCAL_FUNC
+  void      OTL_Table_Done( OTL_Table*  table )
+  {
+    FREE( table->scrip_tags );
+    FREE( table->language_tags );
+    FREE( table->feature_tags );
+    FREE( table->lookups );
+  }
+
+
+ /* return the list of available languages for a given script */
+ /* use with any table..                                      */
+  LOCAL_FUNC
+  void  OTL_Get_Languages_List( OTL_Table*  table,
+                                TT_ULong    script_tag )
+  {
+    TT_UInt  n;
+    TT_Byte* p;
+    TT_Byte* script = 0;
+    TT_Byte* start = table->scripts_table;
+    
+    if ( table->otl_type == otl_type_jstf )  /* skip version for JSTF */
+      start += 4;
+      
+    p = start + 6; /* skip count+first tag */
+    
+    for ( n = 0; n < table->num_scripts; n++, p += 6 )
+    {
+      if ( table->script_tags[n] == script_tag )
+      {
+        script = table->scripts_table + OTL_UShort(p);
+        break;
+      }
+    }
+    
+    table->cur_script = script;
+    if (!script)
+      table->num_languages = 0;
+    else
+    {
+      /* now fill the language_tags array with the appropriate values    */
+      /* not that we put a '0' tag in front of the list to indicate that */
+      /* there is a default language for this script..                   */
+      TT_ULong* tags = table->language_tags;
+      
+      switch (table->otl_type)
+      {
+        case otl_type_base:
+        case otl_type_jstf:
+          script += 2;    /* skip basevalue or extenders */
+          /* fall-through */
+          
+        default:
+          if ( OTL_UShort(script) )
+            *tags++ = 0;
+      }
+      
+      count = OTL_UShort(script);
+      for ( ; count > 0; count-- )
+      {
+        *tags++ = OTL_ULong(script);
+        script += 2; /* skip offset */
+      }
+      
+      table->num_langs = tags - table->language_tags;
+    }
+  }
+
+  
+ /* return the list of available features for the current script/language */
+ /* use with a GPOS or GSUB script table                                  */
+  LOCAL_FUNC
+  void OTL_Get_Features_List( OTL_Table*  table,
+                              TT_ULong    language_tag )
+  {
+    TT_UInt   n;
+    TT_Byte*  script   = table->cur_script;
+    TT_Byte*  language = 0;
+    TT_UShort offset;
+
+    /* clear feature selection table */
+    for ( n = 0; n < table->max_features; n++ )
+      table->features[n] = 0;
+
+    /* now, look for the current language */
+    if ( language_tag == 0 )
+    {
+      offset = OTL_UShort(script);
+      if (!offset) return; /* if there is no default language, exit */
+        
+      language = script - 2 + offset;
+    }
+    else
+    {
+      TT_Byte*  p = script + 8; /* skip default+count+1st tag */
+      TT_UShort index;
+      
+      for ( n = 0; n < table->num_languages; n++, p+=6 )
+      {
+        if ( table->language_tags[n] == language_tag )
+        {
+          language = script + OTL_UShort(p);
+          break;
+        }
+      }
+
+      table->cur_language = language; 
+      if (!language) return;
+      
+      p     = language + 2;   /* skip lookup order */
+      index = OTL_UShort(p);  /* required feature index */
+      if (index != 0xFFFF)
+      {
+        if (index < table->max_features)
+          table->features[index] = 1;
+      }
+      
+      count = OTL_UShort(p);
+      for ( ; count > 0; count-- )
+      {
+        index = OTL_UShort(p);
+        if (index < table->max_features)
+          table->features[index] = 1;
+      }
+    }
+  }
+
+
+ /* return the list of lookups for the current features list */
+ /* use only with a GSUB or GPOS table                       */
+  LOCAL_FUNC
+  void  OTL_Get_Lookups_List( OTL_Table*  table )
+  {
+    TT_UInt  n;
+    TT_Byte* features = table->features_table;
+    TT_Byte* p        = features + 6; /* skip count+1st tag */
+    
+    /* clear lookup list */
+    for ( n = 0; n < table->max_lookups; n++ )
+      table->lookups[n] = 0;
+      
+    /* now, parse the features list */
+    for ( n = 0; n < table->features; n++ )
+    {
+      if (table->features[n])
+      {
+        TT_UInt   count;
+        TT_UShort index;
+        TT_Byte*  feature;
+        
+        feature = features + OTL_UShort(p);
+        p      += 4;  /* skip tag */
+        
+        /* now, select all lookups from this feature */
+        count = OTL_UShort(feature);
+        for ( ; count > 0; count-- )
+        {
+          index = OTL_UShort(feature);
+          if (index < table->max_lookups)
+            table->lookups[index] = 1;
+        }
+      }
+    }
+  }
+  
+
+ /* find the basevalues and minmax for the current script/language */  
+ /* only use it with a BASE table..                                */
+  LOCAL_FUNC
+  void OTL_Get_Baseline_Values( OTL_Table*  table,
+                                TT_ULong    language_tag )
+  {
+    TT_Byte*  script   = table->cur_script;
+    TT_Byte*  p        = script;
+    TT_UShort offset, count;
+
+    table->cur_basevalues = 0;
+    table->cur_minmax     = 0;
+    
+    /* read basevalues */    
+    offset = OTL_UShort(p);
+    if (offset)
+      table->cur_basevalues = script + offset;
+      
+    offset = OTL_UShort(p);
+    if (offset)
+      table->cur_minmax = script + offset;
+
+    count = OTL_UShort(p);
+    for ( ; count > 0; count-- )
+    {
+      TT_ULong  tag;
+      
+      tag = OTL_ULong(p);
+      if ( language_tag == tag )
+      {
+        table->cur_minmax = script + OTL_UShort(p);
+        break;
+      }
+      p += 2; /* skip offset */
+    }
+  }
+
+
+ /* compute the coverage value of a given glyph id */
+  LOCAL_FUNC
+  TT_Long  OTL_Get_Coverage_Index( TT_Byte*  coverage,
+                                   TT_UInt   glyph_id )
+  {
+    TT_Long    result = -1;
+    TT_UInt    count, index, start, end;
+    TT_Byte*   p = coverage;
+    
+    switch ( OTL_UShort(p) )
+    {
+      case 1:  /* coverage format 1 - array of glyph indices */
+        {
+          count = OTL_UShort(p);
+          for ( index = 0; index < count; index++ )
+          {
+            if ( OTL_UShort(p) == glyph_id )
+            {
+              result = index;
+              break;
+            }
+          }
+        }
+        break;
+        
+      case 2:
+        {
+          count = OTL_UShort(p);
+          for ( ; count > 0; count-- )
+          {
+            start = OTL_UShort(p);
+            end   = OTL_UShort(p);
+            index = OTL_UShort(p);
+            if (start <= glyph_id && glyph_id <= end)
+            {
+              result = glyph_id - start + index;
+              break;
+            }
+          }
+        }
+        break;
+    }
+    return result;
+  }
+
+
+ /* compute the class value of a given glyph_id */
+  LOCAL_FUNC
+  TT_UInt  OTL_Get_Glyph_Class( TT_Byte*  class_def,
+                                TT_UInt   glyph_id )
+  {
+    TT_Byte*  p = class_def;
+    TT_UInt   result = 0;
+    TT_UInt   start, end, count, index;
+    
+    switch ( OTL_UShort(p) )
+    {
+      case 1:
+        {
+          start = OTL_UShort(p);
+          count = OTL_UShort(p);
+          
+          glyph_id -= start;
+          if (glyph_id < count)
+          {
+            p += 2*glyph_id;
+            result = OTL_UShort(p);
+          }
+        }
+        break;
+      
+      case 2:
+        {
+          count = OTL_UShort(p);
+          for ( ; count > 0; count-- )
+          {
+            start = OTL_UShort(p);
+            end   = OTL_UShort(p);
+            index = OTL_UShort(p);
+            if ( start <= glyph_id && glyph_id <= end )
+            {
+              result = index;
+              break;
+            }
+          }
+        }
+        break;
+    }
+    return result;
+  }
+
+
+ /* compute the adjustement necessary for a given device size */
+  LOCAL_FUNC
+  TT_Int  OTL_Get_Device_Adjustment( TT_Byte* device,
+                                     TT_UInt  size )
+  {
+    TT_Byte*  p = device;
+    TT_Int    result = 0;
+    TT_UInt   start, end;
+    TT_Short  value;
+    
+    start = OTL_UShort(p);
+    end   = OTL_UShort(p);
+    if (size >= start && size <= end)
+    {
+      /* I know we could do all of this without a switch, with */
+      /* clever shifts and everything, but it makes the code   */
+      /* really difficult to understand..                      */
+      
+      size -= start;
+      switch ( OTL_UShort(p) )
+      {
+        case 1: /* 2-bits per value */
+          {
+            p     += 2*(size >> 3);
+            size   = (size & 7) << 1;
+            value  = (TT_Short)((TT_Short)OTL_UShort(p) << size);
+            result = value >> 14;
+          }
+          break;
+          
+        case 2: /* 4-bits per value */
+          {
+            p     += 2*(size >> 2);
+            size   = (size & 3) << 2;
+            value  = (TT_Short)((TT_Short)OTL_UShort(p) << size);
+            result = value >> 12;
+          }
+          break;
+          
+        case 3: /* 8-bits per value */
+          {
+            p     += 2*(size >> 1);
+            size   = (size & 1) << 3;
+            value  = (TT_Short)((TT_Short)OTL_UShort(p) << size);
+            result = value >> 8;
+          }
+          break;
+      }
+    }
+    return result;
+  }
+  
+ /* compute a BaseCoord value */
+  LOCAL_FUNC
+  TT_Int  OTL_Get_Base_Coordinate( TT_Byte*   base_coord,
+                                   TT_UShort *format
+                                   TT_UShort *ref_glyph_id,
+                                   TT_Byte*  *device )
+  {
+    TT_Byte*  p =base_coord;
+    TT_Int    result = 0;
+    
+    *format = OTL_UShort(p);
+    
+    switch (*format)
+    {
+      case
+    }
+  }
--- /dev/null
+++ b/src/otlayout/oltypes.h
@@ -1,0 +1,238 @@
+#ifndef OLTYPES_H
+#define OLTYPES_H
+
+#include <ftobjs.h>
+#include <tttypes.h>
+
+ /*************************************************************
+  *
+  * <Struct> OTL_Table
+  *
+  * <Description>
+  *    The base table of most OpenType Layout sub-tables.
+  *    Provides a simple way to scan a table for script,
+  *    languages, features and lookups..
+  *
+  * <Fields>
+  *    num_scripts  :: number of scripts in table's script list
+  *    script_tags  :: array of tags for each table script
+  *
+  *    max_languages :: max number of languages for any script in
+  *                     the table.
+  *    num_languages :: number of languages available for current script
+  *    language_tags :: tags of all languages available for current script.
+  *
+  *    max_features  :: total number of features in table
+  *    feature_tags  :: tags of all features for current script/language
+  *    
+  *    max_lookups   :: total number of lookups in table
+  *    lookups       :: selection flags for all lookups for current
+  *                     feature list.
+  *
+  ****************************************************************/
+
+  typedef enum OTL_Type_
+  {
+    otl_type_none = 0,
+    otl_type_base,
+    otl_type_gdef,
+    otl_type_gpos,
+    otl_type_gsub,
+    otl_type_jstf
+  
+  } OTL_Type;
+  
+  
+  typedef struct OTL_Table_
+  {
+    FT_Memory memory;
+
+    TT_Int    num_scripts;
+    TT_Tag*   script_tags;
+    
+    TT_Int    max_languages;
+    TT_Int    num_languages;
+    TT_Tag*   language_tags;
+
+    TT_Int    max_features;
+    TT_Tag*   feature_tags;
+    TT_Bool*  features;
+
+    TT_Int    max_lookups;
+    TT_Bool*  lookups;
+    
+    TT_Byte*  scripts_table;
+    TT_Long   scripts_len;
+    
+    TT_Byte*  features_table;
+    TT_Long*  features_len;
+    
+    TT_Byte*  lookups_table;
+    TT_Byte*  lookups_len;
+
+    TT_Byte*  cur_script;   /* current script   */
+    TT_Byte*  cur_language; /* current language */
+    
+    TT_Byte*  cur_base_values;
+    TT_Byte*  cur_min_max;
+
+    OTL_Type  otl_type;
+
+  } OTL_Table;
+
+
+  LOCAL_DEF
+  TT_Error  OTL_Table_Init( OTL_Table*  table,
+                            FT_Memory   memory );
+
+  LOCAL_DEF
+  TT_Error  OTL_Table_Set_Scripts( OTL_Table*  table,
+                                   TT_Byte*    bytes,
+                                   TT_Long     len,
+                                   OTL_Type    otl_type );
+
+  LOCAL_DEF
+  TT_Error  OTL_Table_Set_Features( OTL_Table*  table,
+                                    TT_Byte*    bytes,
+                                    TT_Long     len );
+
+  LOCAL_DEF
+  TT_Error  OTL_Table_Set_Lookups( OTL_Table*  table,
+                                   TT_Byte*    bytes,
+                                   TT_Long     len );
+
+  LOCAL_DEF
+  void      OTL_Table_Done( OTL_Table*  table );
+
+
+
+/*****************************************************
+ *
+ *  Typical uses:
+ *
+ *  - after OTL_Table_Set_Scripts have been called :
+ *
+ *      table->script_tags contains the list of tags of all
+ *      scripts defined for this table.
+ *
+ *      table->num_scripts is the number of scripts
+ *
+ */
+ 
+/********************************************************
+ *
+ *  - after calling OTL_Table_Set_Features:
+ *
+ *      table->max_features is the number of all features
+ *      in the table
+ *
+ *      table->feature_tags is the list of tags of all
+ *      features in the table
+ *
+ *      table->features[] is an array of boolean used to
+ *      indicate which feature is active for a given script/language
+ *      it is empty (zero-filled) by default.
+ *
+ */
+ 
+/*******************************************************************
+ *
+ *  - after calling OTL_Get_Languages_List(script_tag):
+ *
+ *      table->num_languages is the number of language systems
+ *      available for the script, including the default
+ *      langsys if there is one
+ *
+ *      table->language_tags contains the list of tags of all
+ *      languages for the script. Note that the default langsys
+ *      has tag "0" and is always placed first in "language_tags".
+ *
+ *
+ *
+ */
+  LOCAL_DEF
+  void  OTL_Get_Languages_List( OTL_Table*  table,
+                                TT_ULong    script_tag );
+
+
+/*******************************************************************
+ *
+ *  - after calling OTL_Get_Features_List(language_tag):
+ *
+ *      table->features[] is an array of booleans used to indicate
+ *      which features are active for the current script/language
+ *
+ *      note that this function must be called after OTL_Get_Languages
+ *      which remembers the last "script_tag" used..
+ *
+ *      A client application can change the table->features[] array
+ *      to add or remove features from the list.
+ *
+ *
+ *
+ */
+  LOCAL_DEF
+  void OTL_Get_Features_List( OTL_Table*  table,
+                              TT_ULong    language_tag );
+
+  LOCAL_DEF
+  void OTL_Get_Baseline_Values( OTL_Table*  table,
+                                TT_ULong    language_tag );
+
+  LOCAL_DEF
+  void OTL_Get_Justification( OTL_Table*  table,
+                              TT_ULong    language_tag );
+ 
+/*******************************************************************
+ *
+ *  - after calling OTL_Get_Lookups_List():
+ *
+ *      The function uses the table->features[] array of boolean
+ *      to determine which lookups must be processed.
+ *
+ *      It fills the table->lookups[] array accordingly. It is also
+ *      an array of booleans (one for each lookup).
+ *
+ *
+ */
+
+  LOCAL_DEF
+  void  OTL_Get_Lookups_List( OTL_Table*  table );
+
+
+/***************************************************************
+ *
+ *  So the whole thing looks like:
+ *
+ *
+ *  1.  A client specifies a given script and requests available
+ *      language through OTL_Get_Languages_List()
+ *
+ *  2.  It selects the language tag it needs, then calls
+ *      OTL_Get_Features_List()
+ *
+ *  3.  It updates the list of active features if it needs to
+ *
+ *  4.  It calls OTL_Get_Lookups_List()
+ *      It now has a list of active lookups in "table->lookups[]"
+ *
+ *  5.  The lookups are processed according to the table's type..
+ *
+ */
+
+
+
+  LOCAL_DEF
+  TT_Long  OTL_Get_Coverage_Index( TT_Byte*  coverage,
+                                   TT_UInt   glyph_id );
+
+
+#define OTL_Byte(p)   (p++, p[-1])
+
+#define OTL_UShort(p) (p+=2, ((TT_UShort)p[-2] << 8) | p[-1])
+
+#define OTL_ULong(p)  (p+=4, ((TT_ULong)p[-4] << 24) |        \
+                             ((TT_ULong)p[-3] << 16) |        \
+                             ((TT_ULong)p[-2] << 8 ) | p[-1] )
+
+#endif /* OLTYPES_H */