#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 | |
} | |
} |