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
This commit is contained in:
David Turner 2000-02-15 12:53:31 +00:00
parent dbe4872bf0
commit 18789bfe9f
2 changed files with 734 additions and 0 deletions

496
src/otlayout/oltypes.c Normal file
View File

@ -0,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
}
}

238
src/otlayout/oltypes.h Normal file
View File

@ -0,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 */