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
--- /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 */