|
|
|
@ -24,6 +24,7 @@ |
|
|
|
|
|
|
|
|
|
#include "sferrors.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef TT_CONFIG_OPTION_BDF |
|
|
|
|
|
|
|
|
|
/*************************************************************************/ |
|
|
|
@ -35,168 +36,176 @@ |
|
|
|
|
#undef FT_COMPONENT |
|
|
|
|
#define FT_COMPONENT trace_ttbdf |
|
|
|
|
|
|
|
|
|
FT_LOCAL_DEF( void ) |
|
|
|
|
tt_face_free_bdf_props( TT_Face face ) |
|
|
|
|
{ |
|
|
|
|
TT_BDF bdf = &face->bdf; |
|
|
|
|
|
|
|
|
|
if ( bdf->loaded ) |
|
|
|
|
FT_LOCAL_DEF( void ) |
|
|
|
|
tt_face_free_bdf_props( TT_Face face ) |
|
|
|
|
{ |
|
|
|
|
FT_Stream stream = FT_FACE(face)->stream; |
|
|
|
|
|
|
|
|
|
if ( bdf->table != NULL ) |
|
|
|
|
FT_FRAME_RELEASE( bdf->table ); |
|
|
|
|
TT_BDF bdf = &face->bdf; |
|
|
|
|
|
|
|
|
|
bdf->table_end = NULL; |
|
|
|
|
bdf->strings = NULL; |
|
|
|
|
bdf->strings_size = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( bdf->loaded ) |
|
|
|
|
{ |
|
|
|
|
FT_Stream stream = FT_FACE(face)->stream; |
|
|
|
|
|
|
|
|
|
static FT_Error |
|
|
|
|
tt_face_load_bdf_props( TT_Face face, |
|
|
|
|
FT_Stream stream ) |
|
|
|
|
{ |
|
|
|
|
TT_BDF bdf = &face->bdf; |
|
|
|
|
FT_ULong length; |
|
|
|
|
FT_Error error; |
|
|
|
|
|
|
|
|
|
FT_ZERO( bdf ); |
|
|
|
|
if ( bdf->table != NULL ) |
|
|
|
|
FT_FRAME_RELEASE( bdf->table ); |
|
|
|
|
|
|
|
|
|
error = tt_face_goto_table( face, TTAG_BDF, stream, &length ); |
|
|
|
|
if ( error || |
|
|
|
|
length < 8 || |
|
|
|
|
FT_FRAME_EXTRACT( length, bdf->table ) ) |
|
|
|
|
{ |
|
|
|
|
error = FT_Err_Invalid_Table; |
|
|
|
|
goto Exit; |
|
|
|
|
bdf->table_end = NULL; |
|
|
|
|
bdf->strings = NULL; |
|
|
|
|
bdf->strings_size = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bdf->table_end = bdf->table + length; |
|
|
|
|
|
|
|
|
|
static FT_Error |
|
|
|
|
tt_face_load_bdf_props( TT_Face face, |
|
|
|
|
FT_Stream stream ) |
|
|
|
|
{ |
|
|
|
|
FT_Byte* p = bdf->table; |
|
|
|
|
FT_UInt version = FT_NEXT_USHORT(p); |
|
|
|
|
FT_UInt num_strikes = FT_NEXT_USHORT(p); |
|
|
|
|
FT_UInt32 strings = FT_NEXT_ULONG(p); |
|
|
|
|
|
|
|
|
|
if ( version != 0x0001 || |
|
|
|
|
strings < 8 || |
|
|
|
|
(strings-8)/4 < num_strikes || |
|
|
|
|
strings+1 > length ) |
|
|
|
|
TT_BDF bdf = &face->bdf; |
|
|
|
|
FT_ULong length; |
|
|
|
|
FT_Error error; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FT_ZERO( bdf ); |
|
|
|
|
|
|
|
|
|
error = tt_face_goto_table( face, TTAG_BDF, stream, &length ); |
|
|
|
|
if ( error || |
|
|
|
|
length < 8 || |
|
|
|
|
FT_FRAME_EXTRACT( length, bdf->table ) ) |
|
|
|
|
{ |
|
|
|
|
BadTable: |
|
|
|
|
FT_FRAME_RELEASE( bdf->table ); |
|
|
|
|
FT_ZERO( bdf ); |
|
|
|
|
error = FT_Err_Invalid_Table; |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bdf->num_strikes = num_strikes; |
|
|
|
|
bdf->strings = bdf->table + strings; |
|
|
|
|
bdf->strings_size = length - strings; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* check the strike descriptors
|
|
|
|
|
*/ |
|
|
|
|
{ |
|
|
|
|
FT_UInt count = bdf->num_strikes; |
|
|
|
|
FT_Byte* p = bdf->table + 8; |
|
|
|
|
FT_Byte* strike = p + count*4; |
|
|
|
|
bdf->table_end = bdf->table + length; |
|
|
|
|
|
|
|
|
|
for ( ; count > 0; count-- ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt num_items = FT_PEEK_USHORT(p+2); |
|
|
|
|
FT_Byte* p = bdf->table; |
|
|
|
|
FT_UInt version = FT_NEXT_USHORT( p ); |
|
|
|
|
FT_UInt num_strikes = FT_NEXT_USHORT( p ); |
|
|
|
|
FT_UInt32 strings = FT_NEXT_ULONG ( p ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* we don't need to check the value sets themselves, since this
|
|
|
|
|
* is done later |
|
|
|
|
*/ |
|
|
|
|
strike += 10*num_items; |
|
|
|
|
if ( version != 0x0001 || |
|
|
|
|
strings < 8 || |
|
|
|
|
( strings - 8 ) / 4 < num_strikes || |
|
|
|
|
strings + 1 > length ) |
|
|
|
|
{ |
|
|
|
|
BadTable: |
|
|
|
|
FT_FRAME_RELEASE( bdf->table ); |
|
|
|
|
FT_ZERO( bdf ); |
|
|
|
|
error = FT_Err_Invalid_Table; |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p += 4; |
|
|
|
|
bdf->num_strikes = num_strikes; |
|
|
|
|
bdf->strings = bdf->table + strings; |
|
|
|
|
bdf->strings_size = length - strings; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( strike > bdf->strings ) |
|
|
|
|
goto BadTable; |
|
|
|
|
} |
|
|
|
|
/* check the strike descriptors */ |
|
|
|
|
{ |
|
|
|
|
FT_UInt count = bdf->num_strikes; |
|
|
|
|
FT_Byte* p = bdf->table + 8; |
|
|
|
|
FT_Byte* strike = p + count * 4; |
|
|
|
|
|
|
|
|
|
bdf->loaded = 1; |
|
|
|
|
|
|
|
|
|
Exit: |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
for ( ; count > 0; count-- ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt num_items = FT_PEEK_USHORT( p + 2 ); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We don't need to check the value sets themselves, since this |
|
|
|
|
* is done later. |
|
|
|
|
*/ |
|
|
|
|
strike += 10 * num_items; |
|
|
|
|
|
|
|
|
|
FT_LOCAL_DEF( FT_Error ) |
|
|
|
|
tt_face_find_bdf_prop( TT_Face face, |
|
|
|
|
const char* property_name, |
|
|
|
|
BDF_PropertyRec *aprop ) |
|
|
|
|
{ |
|
|
|
|
TT_BDF bdf = &face->bdf; |
|
|
|
|
FT_Size size = FT_FACE(face)->size; |
|
|
|
|
FT_Error error = 0; |
|
|
|
|
FT_Byte* p; |
|
|
|
|
FT_UInt count; |
|
|
|
|
FT_Byte* strike; |
|
|
|
|
FT_UInt property_len; |
|
|
|
|
p += 4; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
aprop->type = BDF_PROPERTY_TYPE_NONE; |
|
|
|
|
if ( strike > bdf->strings ) |
|
|
|
|
goto BadTable; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( bdf->loaded == 0 ) |
|
|
|
|
{ |
|
|
|
|
error = tt_face_load_bdf_props( face, FT_FACE(face)->stream ); |
|
|
|
|
if ( error ) |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
bdf->loaded = 1; |
|
|
|
|
|
|
|
|
|
count = bdf->num_strikes; |
|
|
|
|
p = bdf->table + 8; |
|
|
|
|
strike = p + 4*count; |
|
|
|
|
Exit: |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
error = FT_Err_Invalid_Argument; |
|
|
|
|
|
|
|
|
|
if ( size == NULL || property_name == NULL ) |
|
|
|
|
goto Exit; |
|
|
|
|
FT_LOCAL_DEF( FT_Error ) |
|
|
|
|
tt_face_find_bdf_prop( TT_Face face, |
|
|
|
|
const char* property_name, |
|
|
|
|
BDF_PropertyRec *aprop ) |
|
|
|
|
{ |
|
|
|
|
TT_BDF bdf = &face->bdf; |
|
|
|
|
FT_Size size = FT_FACE(face)->size; |
|
|
|
|
FT_Error error = 0; |
|
|
|
|
FT_Byte* p; |
|
|
|
|
FT_UInt count; |
|
|
|
|
FT_Byte* strike; |
|
|
|
|
FT_UInt property_len; |
|
|
|
|
|
|
|
|
|
property_len = ft_strlen( property_name ); |
|
|
|
|
if ( property_len == 0 ) |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
for ( ; count > 0; count-- ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt _ppem = FT_NEXT_USHORT(p); |
|
|
|
|
FT_UInt _count = FT_NEXT_USHORT(p); |
|
|
|
|
aprop->type = BDF_PROPERTY_TYPE_NONE; |
|
|
|
|
|
|
|
|
|
if ( _ppem == size->metrics.y_ppem ) |
|
|
|
|
if ( bdf->loaded == 0 ) |
|
|
|
|
{ |
|
|
|
|
count = _count; |
|
|
|
|
goto FoundStrike; |
|
|
|
|
error = tt_face_load_bdf_props( face, FT_FACE( face )->stream ); |
|
|
|
|
if ( error ) |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
strike += 10*_count; |
|
|
|
|
} |
|
|
|
|
goto Exit; |
|
|
|
|
count = bdf->num_strikes; |
|
|
|
|
p = bdf->table + 8; |
|
|
|
|
strike = p + 4 * count; |
|
|
|
|
|
|
|
|
|
FoundStrike: |
|
|
|
|
p = strike; |
|
|
|
|
for ( ; count > 0; count-- ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt type = FT_PEEK_USHORT(p+4); |
|
|
|
|
error = FT_Err_Invalid_Argument; |
|
|
|
|
|
|
|
|
|
if ( (type & 0x10) != 0 ) |
|
|
|
|
if ( size == NULL || property_name == NULL ) |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
property_len = ft_strlen( property_name ); |
|
|
|
|
if ( property_len == 0 ) |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
for ( ; count > 0; count-- ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt32 name_offset = FT_PEEK_ULONG(p); |
|
|
|
|
FT_UInt32 value = FT_PEEK_ULONG(p+6); |
|
|
|
|
|
|
|
|
|
/* be a bit paranoid for invalid entries here */ |
|
|
|
|
if ( name_offset < bdf->strings_size && |
|
|
|
|
property_len < bdf->strings_size - name_offset && |
|
|
|
|
ft_strncmp( property_name, (const char*)bdf->strings + name_offset, |
|
|
|
|
bdf->strings_size - name_offset ) == 0 ) |
|
|
|
|
FT_UInt _ppem = FT_NEXT_USHORT( p ); |
|
|
|
|
FT_UInt _count = FT_NEXT_USHORT( p ); |
|
|
|
|
|
|
|
|
|
if ( _ppem == size->metrics.y_ppem ) |
|
|
|
|
{ |
|
|
|
|
switch ( type & 0x0F ) |
|
|
|
|
count = _count; |
|
|
|
|
goto FoundStrike; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
strike += 10 * _count; |
|
|
|
|
} |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
FoundStrike: |
|
|
|
|
p = strike; |
|
|
|
|
for ( ; count > 0; count-- ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt type = FT_PEEK_USHORT( p + 4 ); |
|
|
|
|
|
|
|
|
|
if ( ( type & 0x10 ) != 0 ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt32 name_offset = FT_PEEK_ULONG( p ); |
|
|
|
|
FT_UInt32 value = FT_PEEK_ULONG( p + 6 ); |
|
|
|
|
|
|
|
|
|
/* be a bit paranoid for invalid entries here */ |
|
|
|
|
if ( name_offset < bdf->strings_size && |
|
|
|
|
property_len < bdf->strings_size - name_offset && |
|
|
|
|
ft_strncmp( property_name, |
|
|
|
|
(const char*)bdf->strings + name_offset, |
|
|
|
|
bdf->strings_size - name_offset ) == 0 ) |
|
|
|
|
{ |
|
|
|
|
switch ( type & 0x0F ) |
|
|
|
|
{ |
|
|
|
|
case 0x00: /* string */ |
|
|
|
|
case 0x01: /* atoms */ |
|
|
|
|
/* check that the content is really 0-terminated */ |
|
|
|
@ -204,7 +213,7 @@ FoundStrike: |
|
|
|
|
ft_memchr( bdf->strings + value, 0, bdf->strings_size ) ) |
|
|
|
|
{ |
|
|
|
|
aprop->type = BDF_PROPERTY_TYPE_ATOM; |
|
|
|
|
aprop->u.atom = (const char*) bdf->strings + value; |
|
|
|
|
aprop->u.atom = (const char*)bdf->strings + value; |
|
|
|
|
error = 0; |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
@ -224,14 +233,17 @@ FoundStrike: |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
p += 10; |
|
|
|
|
} |
|
|
|
|
p += 10; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Exit: |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
Exit: |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif /* TT_CONFIG_OPTION_BDF */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* END */ |