|
|
|
@ -17,7 +17,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <t2parse.h> |
|
|
|
|
#include <freetype/fterrors.h> |
|
|
|
|
#include <freetype/internal/t2errors.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/ |
|
|
|
@ -33,6 +33,7 @@ |
|
|
|
|
#define T2_Err_Stack_Underflow FT_Err_Invalid_Argument |
|
|
|
|
#define T2_Err_Syntax_Error FT_Err_Invalid_Argument |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum |
|
|
|
|
{ |
|
|
|
|
t2_kind_none = 0, |
|
|
|
@ -42,83 +43,87 @@ |
|
|
|
|
t2_kind_bool, |
|
|
|
|
t2_kind_delta, |
|
|
|
|
t2_kind_callback, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
t2_kind_max /* do not remove */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* now generate handlers for the most simple fields */ |
|
|
|
|
typedef FT_Error (*T2_Field_Reader)( T2_Parser* parser ); |
|
|
|
|
typedef TT_Error (*T2_Field_Reader)( T2_Parser* parser ); |
|
|
|
|
|
|
|
|
|
typedef struct T2_Field_Handler_ |
|
|
|
|
typedef struct T2_Field_Handler_ |
|
|
|
|
{ |
|
|
|
|
int kind; |
|
|
|
|
int code; |
|
|
|
|
FT_UInt offset; |
|
|
|
|
FT_Byte size; |
|
|
|
|
TT_UInt offset; |
|
|
|
|
TT_Byte size; |
|
|
|
|
T2_Field_Reader reader; |
|
|
|
|
FT_UInt array_max; |
|
|
|
|
FT_UInt count_offset; |
|
|
|
|
|
|
|
|
|
} T2_Field_Handler; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TT_UInt array_max; |
|
|
|
|
TT_UInt count_offset; |
|
|
|
|
|
|
|
|
|
} T2_Field_Handler; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOCAL_FUNC |
|
|
|
|
void T2_Parser_Init( T2_Parser* parser, FT_UInt code, void* object ) |
|
|
|
|
void T2_Parser_Init( T2_Parser* parser, |
|
|
|
|
TT_UInt code, |
|
|
|
|
void* object ) |
|
|
|
|
{ |
|
|
|
|
MEM_Set(parser,0,sizeof(*parser)); |
|
|
|
|
MEM_Set( parser, 0, sizeof ( *parser ) ); |
|
|
|
|
|
|
|
|
|
parser->top = parser->stack; |
|
|
|
|
parser->object_code = code; |
|
|
|
|
parser->object = object; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* reads an integer */ |
|
|
|
|
static |
|
|
|
|
FT_Long parse_t2_integer( FT_Byte* start, |
|
|
|
|
FT_Byte* limit ) |
|
|
|
|
TT_Long parse_t2_integer( TT_Byte* start, |
|
|
|
|
TT_Byte* limit ) |
|
|
|
|
{ |
|
|
|
|
FT_Byte* p = start; |
|
|
|
|
FT_Int v = *p++; |
|
|
|
|
FT_Long val = 0; |
|
|
|
|
TT_Byte* p = start; |
|
|
|
|
TT_Int v = *p++; |
|
|
|
|
TT_Long val = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (v == 28) |
|
|
|
|
if ( v == 28 ) |
|
|
|
|
{ |
|
|
|
|
if ( p+2 > limit ) goto Bad; |
|
|
|
|
val = (FT_Short)(((FT_Int)p[0] << 8) | p[1]); |
|
|
|
|
if ( p + 2 > limit ) |
|
|
|
|
goto Bad; |
|
|
|
|
|
|
|
|
|
val = (TT_Short)( ( (TT_Int)p[0] << 8 ) | p[1] ); |
|
|
|
|
p += 2; |
|
|
|
|
} |
|
|
|
|
else if (v == 29) |
|
|
|
|
else if ( v == 29 ) |
|
|
|
|
{ |
|
|
|
|
if ( p+4 > limit ) goto Bad; |
|
|
|
|
val = ((FT_Long)p[0] << 24) | |
|
|
|
|
((FT_Long)p[1] << 16) | |
|
|
|
|
((FT_Long)p[2] << 8) | p[3]; |
|
|
|
|
if ( p + 4 > limit ) |
|
|
|
|
goto Bad; |
|
|
|
|
|
|
|
|
|
val = ( (TT_Long)p[0] << 24 ) | |
|
|
|
|
( (TT_Long)p[1] << 16 ) | |
|
|
|
|
( (TT_Long)p[2] << 8 ) | p[3]; |
|
|
|
|
p += 4; |
|
|
|
|
} |
|
|
|
|
else if (v < 247) |
|
|
|
|
else if ( v < 247 ) |
|
|
|
|
{ |
|
|
|
|
val = v - 139; |
|
|
|
|
} |
|
|
|
|
else if (v < 251) |
|
|
|
|
else if ( v < 251 ) |
|
|
|
|
{ |
|
|
|
|
if (p+1 > limit) goto Bad; |
|
|
|
|
val = (v-247)*256 + p[0]+108; |
|
|
|
|
p ++; |
|
|
|
|
if ( p + 1 > limit ) |
|
|
|
|
goto Bad; |
|
|
|
|
|
|
|
|
|
val = ( v - 247 ) * 256 + p[0] + 108; |
|
|
|
|
p++; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
if (p+1 > limit) goto Bad; |
|
|
|
|
val = -(v-251)*256 - p[0]-108; |
|
|
|
|
p ++; |
|
|
|
|
if ( p + 1 > limit ) |
|
|
|
|
goto Bad; |
|
|
|
|
|
|
|
|
|
val = -( v - 251 ) * 256 - p[0] - 108; |
|
|
|
|
p++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Exit: |
|
|
|
@ -132,15 +137,16 @@ |
|
|
|
|
|
|
|
|
|
/* reads a real */ |
|
|
|
|
static |
|
|
|
|
FT_Fixed parse_t2_real( FT_Byte* start, |
|
|
|
|
FT_Byte* limit, |
|
|
|
|
FT_Int power_ten ) |
|
|
|
|
TT_Fixed parse_t2_real( TT_Byte* start, |
|
|
|
|
TT_Byte* limit, |
|
|
|
|
TT_Int power_ten ) |
|
|
|
|
{ |
|
|
|
|
FT_Byte* p = start; |
|
|
|
|
FT_Long num, divider, result, exp; |
|
|
|
|
FT_Int sign = 0, exp_sign = 0; |
|
|
|
|
FT_Byte nib; |
|
|
|
|
FT_Byte phase; |
|
|
|
|
TT_Byte* p = start; |
|
|
|
|
TT_Long num, divider, result, exp; |
|
|
|
|
TT_Int sign = 0, exp_sign = 0; |
|
|
|
|
TT_Byte nib; |
|
|
|
|
TT_Byte phase; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = 0; |
|
|
|
|
num = 0; |
|
|
|
@ -149,86 +155,98 @@ |
|
|
|
|
/* first of all, read the integer part */ |
|
|
|
|
phase = 4; |
|
|
|
|
p--; |
|
|
|
|
|
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
/* read one nibble at a time */ |
|
|
|
|
if (phase && ++p >= limit) goto Bad; |
|
|
|
|
nib = (p[0] >> phase) & 0xF; |
|
|
|
|
phase = 4-phase; |
|
|
|
|
if ( phase && ++p >= limit ) |
|
|
|
|
goto Bad; |
|
|
|
|
|
|
|
|
|
nib = ( p[0] >> phase ) & 0xF; |
|
|
|
|
phase = 4 - phase; |
|
|
|
|
|
|
|
|
|
if (nib == 0xE) |
|
|
|
|
if ( nib == 0xE ) |
|
|
|
|
sign = 1; |
|
|
|
|
else if (nib > 9) |
|
|
|
|
else if ( nib > 9 ) |
|
|
|
|
break; |
|
|
|
|
else |
|
|
|
|
result = result*10 + nib; |
|
|
|
|
result = result * 10 + nib; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* read decimal part, if any */ |
|
|
|
|
if (nib == 0xa) |
|
|
|
|
if ( nib == 0xa ) |
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
/* read one nibble at a time */ |
|
|
|
|
if (!phase && ++p >= limit) goto Bad; |
|
|
|
|
phase = 4-phase; |
|
|
|
|
nib = (p[0] >> phase) & 0xF; |
|
|
|
|
if ( !phase && ++p >= limit ) |
|
|
|
|
goto Bad; |
|
|
|
|
|
|
|
|
|
if (nib >= 10) |
|
|
|
|
phase = 4 - phase; |
|
|
|
|
nib = ( p[0] >> phase ) & 0xF; |
|
|
|
|
|
|
|
|
|
if ( nib >= 10 ) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
if (divider < 10000000L) |
|
|
|
|
{ |
|
|
|
|
num = num*10 + nib; |
|
|
|
|
num = num * 10 + nib; |
|
|
|
|
divider *= 10; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* read exponent, if any */ |
|
|
|
|
if (nib == 12) |
|
|
|
|
if ( nib == 12 ) |
|
|
|
|
{ |
|
|
|
|
exp_sign = 1; |
|
|
|
|
nib = 11; |
|
|
|
|
} |
|
|
|
|
if (nib == 11) |
|
|
|
|
|
|
|
|
|
if ( nib == 11 ) |
|
|
|
|
{ |
|
|
|
|
exp = 0; |
|
|
|
|
|
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
/* read one nibble at a time */ |
|
|
|
|
if (!phase && ++p >= limit) goto Bad; |
|
|
|
|
phase = 4-phase; |
|
|
|
|
nib = (p[0] >> phase) & 0xF; |
|
|
|
|
if ( !phase && ++p >= limit ) |
|
|
|
|
goto Bad; |
|
|
|
|
|
|
|
|
|
phase = 4 - phase; |
|
|
|
|
nib = ( p[0] >> phase ) & 0xF; |
|
|
|
|
|
|
|
|
|
if (nib >= 10) |
|
|
|
|
if ( nib >= 10 ) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
exp = exp*10 + nib; |
|
|
|
|
exp = exp * 10 + nib; |
|
|
|
|
} |
|
|
|
|
if (exp_sign) |
|
|
|
|
|
|
|
|
|
if ( exp_sign ) |
|
|
|
|
exp = -exp; |
|
|
|
|
|
|
|
|
|
power_ten += exp; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* raise to power of ten if needed */ |
|
|
|
|
while (power_ten > 0) |
|
|
|
|
while ( power_ten > 0 ) |
|
|
|
|
{ |
|
|
|
|
result = result*10; |
|
|
|
|
num = num*10; |
|
|
|
|
result = result * 10; |
|
|
|
|
num = num * 10; |
|
|
|
|
|
|
|
|
|
power_ten--; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (power_ten < 0) |
|
|
|
|
while ( power_ten < 0 ) |
|
|
|
|
{ |
|
|
|
|
result = result/10; |
|
|
|
|
divider = divider*10; |
|
|
|
|
result = result / 10; |
|
|
|
|
divider = divider * 10; |
|
|
|
|
|
|
|
|
|
power_ten++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (num) |
|
|
|
|
if ( num ) |
|
|
|
|
result += FT_DivFix( num, divider ); |
|
|
|
|
|
|
|
|
|
if (sign) |
|
|
|
|
if ( sign ) |
|
|
|
|
result = -result; |
|
|
|
|
|
|
|
|
|
Exit: |
|
|
|
@ -242,32 +260,34 @@ |
|
|
|
|
|
|
|
|
|
/* reads a number, either integer or real */ |
|
|
|
|
static |
|
|
|
|
FT_Long t2_parse_num( FT_Byte** d ) |
|
|
|
|
TT_Long t2_parse_num( TT_Byte** d ) |
|
|
|
|
{ |
|
|
|
|
return ( **d == 30 ? (parse_t2_real ( d[0], d[1], 0 ) >> 16): |
|
|
|
|
parse_t2_integer( d[0], d[1] ) ); |
|
|
|
|
return ( **d == 30 ? ( parse_t2_real( d[0], d[1], 0 ) >> 16 ) |
|
|
|
|
: parse_t2_integer( d[0], d[1] ) ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* reads a floating point number, either integer or real */ |
|
|
|
|
static |
|
|
|
|
FT_Fixed t2_parse_fixed( FT_Byte** d ) |
|
|
|
|
TT_Fixed t2_parse_fixed( TT_Byte** d ) |
|
|
|
|
{ |
|
|
|
|
return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 ) : |
|
|
|
|
parse_t2_integer( d[0], d[1] ) << 16 ); |
|
|
|
|
return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 ) |
|
|
|
|
: parse_t2_integer( d[0], d[1] ) << 16 ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static |
|
|
|
|
FT_Error parse_font_matrix( T2_Parser* parser ) |
|
|
|
|
TT_Error parse_font_matrix( T2_Parser* parser ) |
|
|
|
|
{ |
|
|
|
|
CFF_Top_Dict* dict = (CFF_Top_Dict*)parser->object; |
|
|
|
|
FT_Matrix* matrix = &dict->font_matrix; |
|
|
|
|
FT_Byte** data = parser->stack; |
|
|
|
|
FT_Error error; |
|
|
|
|
TT_Matrix* matrix = &dict->font_matrix; |
|
|
|
|
TT_Byte** data = parser->stack; |
|
|
|
|
TT_Error error; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error = T2_Err_Stack_Underflow; |
|
|
|
|
if (parser->top >= parser->stack + 4) |
|
|
|
|
|
|
|
|
|
if ( parser->top >= parser->stack + 4 ) |
|
|
|
|
{ |
|
|
|
|
matrix->xx = t2_parse_fixed( data++ ); |
|
|
|
|
matrix->yx = t2_parse_fixed( data++ ); |
|
|
|
@ -275,20 +295,23 @@ |
|
|
|
|
matrix->yy = t2_parse_fixed( data ); |
|
|
|
|
error = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static |
|
|
|
|
FT_Error parse_font_bbox( T2_Parser* parser ) |
|
|
|
|
TT_Error parse_font_bbox( T2_Parser* parser ) |
|
|
|
|
{ |
|
|
|
|
CFF_Top_Dict* dict = (CFF_Top_Dict*)parser->object; |
|
|
|
|
FT_BBox* bbox = &dict->font_bbox; |
|
|
|
|
FT_Byte** data = parser->stack; |
|
|
|
|
FT_Error error; |
|
|
|
|
TT_Byte** data = parser->stack; |
|
|
|
|
TT_Error error; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error = T2_Err_Stack_Underflow; |
|
|
|
|
if (parser->top >= parser->stack + 4) |
|
|
|
|
|
|
|
|
|
if ( parser->top >= parser->stack + 4 ) |
|
|
|
|
{ |
|
|
|
|
bbox->xMin = t2_parse_num( data++ ); |
|
|
|
|
bbox->yMin = t2_parse_num( data++ ); |
|
|
|
@ -296,247 +319,288 @@ |
|
|
|
|
bbox->yMax = t2_parse_num( data ); |
|
|
|
|
error = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static |
|
|
|
|
FT_Error parse_private_dict( T2_Parser* parser ) |
|
|
|
|
TT_Error parse_private_dict( T2_Parser* parser ) |
|
|
|
|
{ |
|
|
|
|
CFF_Top_Dict* dict = (CFF_Top_Dict*)parser->object; |
|
|
|
|
FT_Byte** data = parser->stack; |
|
|
|
|
FT_Error error; |
|
|
|
|
CFF_Top_Dict* dict = (CFF_Top_Dict*)parser->object; |
|
|
|
|
TT_Byte** data = parser->stack; |
|
|
|
|
TT_Error error; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error = T2_Err_Stack_Underflow; |
|
|
|
|
if (parser->top >= parser->stack + 2) |
|
|
|
|
|
|
|
|
|
if ( parser->top >= parser->stack + 2 ) |
|
|
|
|
{ |
|
|
|
|
dict->private_size = t2_parse_num( data++ ); |
|
|
|
|
dict->private_offset = t2_parse_num( data ); |
|
|
|
|
error = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static |
|
|
|
|
FT_Error parse_cid_ros( T2_Parser* parser ) |
|
|
|
|
TT_Error parse_cid_ros( T2_Parser* parser ) |
|
|
|
|
{ |
|
|
|
|
CFF_Top_Dict* dict = (CFF_Top_Dict*)parser->object; |
|
|
|
|
FT_Byte** data = parser->stack; |
|
|
|
|
FT_Error error; |
|
|
|
|
TT_Byte** data = parser->stack; |
|
|
|
|
TT_Error error; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error = T2_Err_Stack_Underflow; |
|
|
|
|
if (parser->top >= parser->stack + 3) |
|
|
|
|
|
|
|
|
|
if ( parser->top >= parser->stack + 3 ) |
|
|
|
|
{ |
|
|
|
|
dict->cid_registry = (FT_UInt)t2_parse_num( data++ ); |
|
|
|
|
dict->cid_ordering = (FT_UInt)t2_parse_num( data++ ); |
|
|
|
|
dict->cid_supplement = (FT_ULong)t2_parse_num( data ); |
|
|
|
|
dict->cid_registry = (TT_UInt)t2_parse_num( data++ ); |
|
|
|
|
dict->cid_ordering = (TT_UInt)t2_parse_num( data++ ); |
|
|
|
|
dict->cid_supplement = (TT_ULong)t2_parse_num( data ); |
|
|
|
|
error = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define T2_FIELD_NUM( code, name ) \ |
|
|
|
|
T2_FIELD( code, name, t2_kind_num ) |
|
|
|
|
#define T2_FIELD_FIXED( code, name ) \ |
|
|
|
|
T2_FIELD( code, name, t2_kind_fixed ) |
|
|
|
|
#define T2_FIELD_STRING( code, name ) \ |
|
|
|
|
T2_FIELD( code, name, t2_kind_string ) |
|
|
|
|
#define T2_FIELD_BOOL( code, name ) \ |
|
|
|
|
T2_FIELD( code, name, t2_kind_bool ) |
|
|
|
|
#define T2_FIELD_DELTA( code, name,max ) \ |
|
|
|
|
T2_FIELD( code, name, t2_kind_delta ) |
|
|
|
|
|
|
|
|
|
#define T2_FIELD_NUM(code,name) T2_FIELD( code, name, t2_kind_num ) |
|
|
|
|
#define T2_FIELD_FIXED(code,name) T2_FIELD( code, name, t2_kind_fixed ) |
|
|
|
|
#define T2_FIELD_STRING(code,name) T2_FIELD( code, name, t2_kind_string ) |
|
|
|
|
#define T2_FIELD_BOOL(code,name) T2_FIELD( code, name, t2_kind_bool ) |
|
|
|
|
#define T2_FIELD_DELTA(code,name,max) T2_FIELD( code, name, t2_kind_delta ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define T2_REF(s,f) (((s*)0)->f) |
|
|
|
|
#define T2_REF( s, f ) ( ((s*)0)->f ) |
|
|
|
|
|
|
|
|
|
#define T2_FIELD_CALLBACK( code, name ) \ |
|
|
|
|
{ t2_kind_callback, code | T2CODE, 0, 0, parse_ ## name, 0, 0 }, |
|
|
|
|
|
|
|
|
|
#undef T2_FIELD |
|
|
|
|
#define T2_FIELD( code, name, kind ) \ |
|
|
|
|
{ kind, code | T2CODE, \
|
|
|
|
|
(FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
|
|
|
|
|
sizeof( T2_REF( T2TYPE, name ) ), \
|
|
|
|
|
0 }, |
|
|
|
|
|
|
|
|
|
#undef T2_FIELD_DELTA |
|
|
|
|
#define T2_FIELD_DELTA( code, name, max ) \ |
|
|
|
|
{ t2_kind_delta, code | T2CODE, \
|
|
|
|
|
(FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
|
|
|
|
|
sizeof( T2_REF( T2TYPE, name ) ), \
|
|
|
|
|
0, \
|
|
|
|
|
max, (FT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name ) }, |
|
|
|
|
{ \
|
|
|
|
|
t2_kind_callback, \
|
|
|
|
|
code | T2CODE, \
|
|
|
|
|
0, 0, \
|
|
|
|
|
parse_ ## name, \
|
|
|
|
|
0, 0 }, |
|
|
|
|
|
|
|
|
|
#undef T2_FIELD |
|
|
|
|
#define T2_FIELD( code, name, kind ) \ |
|
|
|
|
{ \
|
|
|
|
|
kind, \
|
|
|
|
|
code | T2CODE, \
|
|
|
|
|
(TT_UInt)(char*)&T2_REF( T2TYPE, name ), \
|
|
|
|
|
sizeof( T2_REF( T2TYPE, name ) ), \
|
|
|
|
|
0 \
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
#undef T2_FIELD_DELTA |
|
|
|
|
#define T2_FIELD_DELTA( code, name, max ) \ |
|
|
|
|
{ \
|
|
|
|
|
t2_kind_delta, \
|
|
|
|
|
code | T2CODE, \
|
|
|
|
|
(TT_UInt)(char*)&T2_REF( T2TYPE, name ), \
|
|
|
|
|
sizeof( T2_REF( T2TYPE, name ) ), \
|
|
|
|
|
0, \
|
|
|
|
|
max, \
|
|
|
|
|
(TT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name ) \
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
#define T2CODE_TOPDICT 0x1000 |
|
|
|
|
#define T2CODE_PRIVATE 0x2000 |
|
|
|
|
|
|
|
|
|
static const T2_Field_Handler t2_field_handlers[] = |
|
|
|
|
{ |
|
|
|
|
#include <t2tokens.h> |
|
|
|
|
#include <t2tokens.h> |
|
|
|
|
{ 0, 0, 0, 0, 0, 0, 0 } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOCAL_FUNC |
|
|
|
|
FT_Error T2_Parser_Run( T2_Parser* parser, |
|
|
|
|
FT_Byte* start, |
|
|
|
|
FT_Byte* limit ) |
|
|
|
|
TT_Error T2_Parser_Run( T2_Parser* parser, |
|
|
|
|
TT_Byte* start, |
|
|
|
|
TT_Byte* limit ) |
|
|
|
|
{ |
|
|
|
|
FT_Byte* p = start; |
|
|
|
|
FT_Error error = 0; |
|
|
|
|
|
|
|
|
|
TT_Byte* p = start; |
|
|
|
|
TT_Error error = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parser->top = parser->stack; |
|
|
|
|
parser->start = start; |
|
|
|
|
parser->limit = limit; |
|
|
|
|
parser->cursor = start; |
|
|
|
|
|
|
|
|
|
while (p < limit) |
|
|
|
|
|
|
|
|
|
while ( p < limit ) |
|
|
|
|
{ |
|
|
|
|
FT_Byte v = *p; |
|
|
|
|
TT_Byte v = *p; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( v >= 27 && v != 31 ) |
|
|
|
|
{ |
|
|
|
|
/* its a number, we'll push its position on the stack */ |
|
|
|
|
if (parser->top - parser->stack >= T2_MAX_STACK_DEPTH) |
|
|
|
|
/* it's a number; we will push its position on the stack */ |
|
|
|
|
if ( parser->top - parser->stack >= T2_MAX_STACK_DEPTH ) |
|
|
|
|
goto Stack_Overflow; |
|
|
|
|
|
|
|
|
|
*parser->top ++ = p; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* now, skip it */ |
|
|
|
|
if (v == 30) |
|
|
|
|
if ( v == 30 ) |
|
|
|
|
{ |
|
|
|
|
/* skip real number */ |
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
if (p >= limit) goto Syntax_Error; |
|
|
|
|
if ( p >= limit ) |
|
|
|
|
goto Syntax_Error; |
|
|
|
|
v = p[0] >> 4; |
|
|
|
|
if (v == 15) break; |
|
|
|
|
if ( v == 15 ) |
|
|
|
|
break; |
|
|
|
|
v = p[0] & 0xF; |
|
|
|
|
if (v == 15) break; |
|
|
|
|
if ( v == 15 ) |
|
|
|
|
break; |
|
|
|
|
p++; |
|
|
|
|
} |
|
|
|
|
p++; |
|
|
|
|
} |
|
|
|
|
else if (v == 28)
|
|
|
|
|
else if ( v == 28 ) |
|
|
|
|
p += 2; |
|
|
|
|
else if (v == 29) |
|
|
|
|
else if ( v == 29 ) |
|
|
|
|
p += 4; |
|
|
|
|
else if (v > 246) |
|
|
|
|
else if ( v > 246 ) |
|
|
|
|
p += 1; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
/* this is not a number, hence it's an operator. Compute its code */ |
|
|
|
|
/* and look for it in our current list.. */ |
|
|
|
|
FT_UInt code; |
|
|
|
|
FT_Int num_args = parser->top - parser->stack; |
|
|
|
|
/* this is not a number, hence it's an operator. Compute its code */ |
|
|
|
|
/* and look for it in our current list. */ |
|
|
|
|
|
|
|
|
|
TT_UInt code; |
|
|
|
|
TT_Int num_args = parser->top - parser->stack; |
|
|
|
|
const T2_Field_Handler* field; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* first of all, a trivial check */ |
|
|
|
|
if ( num_args < 1 ) goto Stack_Underflow; |
|
|
|
|
if ( num_args < 1 ) |
|
|
|
|
goto Stack_Underflow; |
|
|
|
|
|
|
|
|
|
*parser->top = p; |
|
|
|
|
code = v; |
|
|
|
|
if (v == 12) |
|
|
|
|
if ( v == 12 ) |
|
|
|
|
{ |
|
|
|
|
/* two byte operator */ |
|
|
|
|
p++; |
|
|
|
|
code = 0x100 | p[0]; |
|
|
|
|
} |
|
|
|
|
code = code | parser->object_code; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for ( field = t2_field_handlers; field->kind; field++ ) |
|
|
|
|
{ |
|
|
|
|
if (field->code == code) |
|
|
|
|
if ( field->code == code ) |
|
|
|
|
{ |
|
|
|
|
/* we found our field's handler, read it.. */ |
|
|
|
|
FT_Long val; |
|
|
|
|
FT_Byte* q = (FT_Byte*)parser->object + field->offset; |
|
|
|
|
|
|
|
|
|
switch (field->kind) |
|
|
|
|
/* we found our field's handler; read it */ |
|
|
|
|
TT_Long val; |
|
|
|
|
TT_Byte* q = (TT_Byte*)parser->object + field->offset; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch ( field->kind ) |
|
|
|
|
{ |
|
|
|
|
case t2_kind_bool: |
|
|
|
|
case t2_kind_string: |
|
|
|
|
case t2_kind_num: |
|
|
|
|
val = t2_parse_num( parser->stack ); |
|
|
|
|
goto Store_Number; |
|
|
|
|
|
|
|
|
|
case t2_kind_fixed: |
|
|
|
|
val = t2_parse_fixed( parser->stack ); |
|
|
|
|
|
|
|
|
|
Store_Number:
|
|
|
|
|
switch (field->size) |
|
|
|
|
{ |
|
|
|
|
case 1: *(FT_Byte*) q = (FT_Byte)val; break; |
|
|
|
|
case 2: *(FT_Short*)q = (FT_Short)val; break; |
|
|
|
|
default: *(FT_Long*)q = val; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case t2_kind_delta: |
|
|
|
|
{ |
|
|
|
|
FT_Byte* qcount = (FT_Byte*)parser->object + |
|
|
|
|
field->count_offset; |
|
|
|
|
|
|
|
|
|
FT_Long val; |
|
|
|
|
FT_Byte** data = parser->stack; |
|
|
|
|
|
|
|
|
|
if (num_args > field->array_max) |
|
|
|
|
num_args = field->array_max; |
|
|
|
|
|
|
|
|
|
/* store count */ |
|
|
|
|
*qcount = (FT_Byte)num_args; |
|
|
|
|
|
|
|
|
|
val = 0; |
|
|
|
|
while (num_args > 0) |
|
|
|
|
{ |
|
|
|
|
val += t2_parse_num( data++ ); |
|
|
|
|
switch (field->size) |
|
|
|
|
{ |
|
|
|
|
case 1: *(FT_Byte*) q = (FT_Byte)val; break; |
|
|
|
|
case 2: *(FT_Short*)q = (FT_Short)val; break; |
|
|
|
|
default: *(FT_Long*)q = val;
|
|
|
|
|
} |
|
|
|
|
q += field->size; |
|
|
|
|
num_args--; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
default: /* callback */ |
|
|
|
|
error = field->reader( parser ); |
|
|
|
|
if (error) goto Exit; |
|
|
|
|
case t2_kind_bool: |
|
|
|
|
case t2_kind_string: |
|
|
|
|
case t2_kind_num: |
|
|
|
|
val = t2_parse_num( parser->stack ); |
|
|
|
|
goto Store_Number; |
|
|
|
|
|
|
|
|
|
case t2_kind_fixed: |
|
|
|
|
val = t2_parse_fixed( parser->stack ); |
|
|
|
|
|
|
|
|
|
Store_Number: |
|
|
|
|
switch ( field->size ) |
|
|
|
|
{ |
|
|
|
|
case 1: |
|
|
|
|
*(TT_Byte*)q = (TT_Byte)val; |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
*(TT_Short*)q = (TT_Short)val; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
*(TT_Long*)q = val; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case t2_kind_delta: |
|
|
|
|
{ |
|
|
|
|
TT_Byte* qcount = (TT_Byte*)parser->object + |
|
|
|
|
field->count_offset; |
|
|
|
|
|
|
|
|
|
TT_Long val; |
|
|
|
|
TT_Byte** data = parser->stack; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( num_args > field->array_max ) |
|
|
|
|
num_args = field->array_max; |
|
|
|
|
|
|
|
|
|
/* store count */ |
|
|
|
|
*qcount = (TT_Byte)num_args; |
|
|
|
|
|
|
|
|
|
val = 0; |
|
|
|
|
while ( num_args > 0 ) |
|
|
|
|
{ |
|
|
|
|
val += t2_parse_num( data++ ); |
|
|
|
|
switch ( field->size ) |
|
|
|
|
{ |
|
|
|
|
case 1: |
|
|
|
|
*(TT_Byte*)q = (TT_Byte)val; |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
*(TT_Short*)q = (TT_Short)val; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
*(TT_Long*)q = val; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
q += field->size; |
|
|
|
|
num_args--; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
default: /* callback */ |
|
|
|
|
error = field->reader( parser ); |
|
|
|
|
if ( error ) |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
goto Found; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* this is an unknown operator, or it is unsupported, we will ignore */ |
|
|
|
|
/* it for now... */ |
|
|
|
|
/* this is an unknown operator, or it is unsupported; */ |
|
|
|
|
/* we will ignore it for now. */ |
|
|
|
|
|
|
|
|
|
Found:
|
|
|
|
|
Found: |
|
|
|
|
/* clear stack */ |
|
|
|
|
parser->top = parser->stack; |
|
|
|
|
} |
|
|
|
|
p++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Exit: |
|
|
|
|
return error; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Stack_Overflow: |
|
|
|
|
error = FT_Err_Invalid_Argument; |
|
|
|
|
error = T2_Err_Invalid_Argument; |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Stack_Underflow: |
|
|
|
|
error = FT_Err_Invalid_Argument; |
|
|
|
|
error = T2_Err_Invalid_Argument; |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Syntax_Error: |
|
|
|
|
error = FT_Err_Invalid_Argument; |
|
|
|
|
error = T2_Err_Invalid_Argument; |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* END */ |
|
|
|
|