bug that prevented FreeType 2.x and FreeType 1.x to produce bit-by-bit identical monochrome glyph bitmaps with native TrueType hinting. The culprit was a single-bit flag that wasn't set correctly by the TrueType glyph loader !! * src/otlayout/otlayout.h, src/otlayout/otlbase.c, src/otlayout/otlbase.h, src/otlayout/otlconf.h, src/otlayout/otlgdef.c, src/otlayout/otlgdef.h, src/otlayout/otlgpos.c, src/otlayout/otlgpos.h, src/otlayout/otlgsub.c, src/otlayout/otlgsub.h, src/otlayout/otljstf.c, src/otlayout/otljstf.h, src/otlayout/otltable.c, src/otlayout/otltable.h, src/otlayout/otltags.h: adding OpenType Layout source files. Module is still incompleteBRANCH-2-1-5
parent
75e6d1ce91
commit
c9484caf7a
18 changed files with 2870 additions and 90 deletions
@ -0,0 +1,168 @@ |
||||
#ifndef __OT_LAYOUT_H__ |
||||
#define __OT_LAYOUT_H__ |
||||
|
||||
|
||||
#include "otlconf.h" |
||||
|
||||
OTL_BEGIN_HEADER |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** BASE DATA TYPES *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
typedef unsigned char OTL_Byte; |
||||
typedef const OTL_Byte* OTL_Bytes; |
||||
|
||||
typedef int OTL_Error; |
||||
|
||||
typedef void* OTL_Pointer; |
||||
|
||||
typedef int OTL_Int; |
||||
typedef unsigned int OTL_UInt; |
||||
|
||||
typedef short OTL_Int16; |
||||
typedef unsigned short OTL_UInt16; |
||||
|
||||
#if OTL_SIZEOF_INT == 4 |
||||
|
||||
typedef int OTL_Int32; |
||||
typedef unsigned int OTL_UInt32; |
||||
|
||||
#elif OTL_SIZEOF_LONG == 4 |
||||
|
||||
typedef long OTL_Int32; |
||||
typedef unsigned long OTL_UInt32; |
||||
|
||||
#else |
||||
# error "no 32-bits type found" |
||||
#endif |
||||
|
||||
typedef OTL_UInt32 OTL_Tag; |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** ERROR CODES *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
typedef enum |
||||
{ |
||||
OTL_Err_Ok = 0, |
||||
OTL_Err_InvalidArgument, |
||||
OTL_Err_InvalidFormat, |
||||
OTL_Err_InvalidOffset, |
||||
|
||||
} OTL_Error; |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** ENUMERATIONS *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
#define OTL_MAKE_TAG(c1,c2,c3,c4) \ |
||||
( ( (OTL_UInt32)(c1) << 24 ) | \
|
||||
(OTL_UInt32)(c2) << 16 ) | \
|
||||
(OTL_UInt32)(c3) << 8 ) | \
|
||||
(OTL_UInt32)(c4) ) |
||||
|
||||
typedef enum OTL_ScriptTag_ |
||||
{ |
||||
OTL_SCRIPT_NONE = 0, |
||||
|
||||
#define OTL_SCRIPT_TAG(c1,c2,c3,c4,s,n) OTL_SCRIPT_TAG_ ## n = OTL_MAKE_TAG(c1,c2,c3,c4), |
||||
#include "otltags.h" |
||||
|
||||
OTL_SCRIPT_MAX |
||||
|
||||
} OTL_ScriptTag; |
||||
|
||||
|
||||
typedef enum OTL_LangTag_ |
||||
{ |
||||
OTL_LANG_DEFAULT = 0, |
||||
|
||||
#define OTL_LANG_TAG(c1,c2,c3,c4,s,n) OTL_LANG_TAG_ ## n = OTL_MAKE_TAG(c1,c2,c3,c4), |
||||
#include "otltags.h" |
||||
|
||||
OTL_LANG_MAX |
||||
|
||||
} OTL_LangTag; |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** MEMORY READS *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
#define OTL_PEEK_USHORT(p) ( ((OTL_UInt)((p)[0]) << 8) | \ |
||||
((OTL_UInt)((p)[1]) ) ) |
||||
|
||||
#define OTL_PEEK_ULONG(p) ( ((OTL_UInt32)((p)[0]) << 24) | \ |
||||
((OTL_UInt32)((p)[1]) << 16) | \
|
||||
((OTL_UInt32)((p)[2]) << 8) | \
|
||||
((OTL_UInt32)((p)[3]) ) ) |
||||
|
||||
#define OTL_PEEK_SHORT(p) ((OTL_Int16)OTL_PEEK_USHORT(p)) |
||||
|
||||
#define OTL_PEEK_LONG(p) ((OTL_Int32)OTL_PEEK_ULONG(p)) |
||||
|
||||
#define OTL_NEXT_USHORT(p) ( (p) += 2, OTL_PEEK_USHORT((p)-2) ) |
||||
#define OTL_NEXT_ULONG(p) ( (p) += 4, OTL_PEEK_ULONG((p)-4) ) |
||||
|
||||
#define OTL_NEXT_SHORT(p) ((OTL_Int16)OTL_NEXT_USHORT(p)) |
||||
#define OTL_NEXT_LONG(p) ((OTL_Int32)OTL_NEXT_ULONG(p)) |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** VALIDATION *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
typedef struct OTL_ValidatorRec_* OTL_Validator; |
||||
|
||||
typedef struct OTL_ValidatorRec_ |
||||
{ |
||||
OTL_Bytes limit; |
||||
OTL_Bytes base; |
||||
OTL_Error error; |
||||
OTL_jmp_buf jump_buffer; |
||||
|
||||
} OTL_ValidatorRec; |
||||
|
||||
typedef void (*OTL_ValidateFunc)( OTL_Bytes table, |
||||
OTL_Valid valid ); |
||||
|
||||
OTL_API( void ) |
||||
otl_validator_error( OTL_Validator validator, |
||||
OTL_Error error ); |
||||
|
||||
#define OTL_INVALID(e) otl_validator_error( valid, e ) |
||||
|
||||
#define OTL_INVALID_TOO_SHORT OTL_INVALID( OTL_Err_InvalidOffset ); |
||||
#define OTL_INVALID_DATA OTL_INVALID( OTL_Err_InvalidFormat ); |
||||
|
||||
#define OTL_CHECK(_count) OTL_BEGIN_STMNT \ |
||||
if ( p + (_count) > valid->limit ) \
|
||||
OTL_INVALID_TOO_SHORT; \
|
||||
OTL_END_STMNT |
||||
|
||||
/* */ |
||||
|
||||
OTL_END_HEADER |
||||
|
||||
#endif /* __OPENTYPE_LAYOUT_H__ */ |
@ -0,0 +1,181 @@ |
||||
#include "otlbase.h" |
||||
#include "otlcommn.h" |
||||
|
||||
static void |
||||
otl_base_coord_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
|
||||
format = OTL_NEXT_USHORT( p ); |
||||
p += 2; |
||||
|
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
break; |
||||
|
||||
case 2: |
||||
OTL_CHECK( 4 ); |
||||
break; |
||||
|
||||
case 3: |
||||
OTL_CHECK( 2 ); |
||||
otl_device_table_validate( table + OTL_PEEK_USHORT( p ) ); |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_base_tag_list_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK(2); |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( count*4 ); |
||||
} |
||||
|
||||
|
||||
|
||||
static void |
||||
otl_base_values_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
|
||||
p += 2; /* skip default index */ |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
|
||||
for ( ; count > 0; count-- ) |
||||
otl_base_coord_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_base_minmax_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt min_coord, max_coord, count; |
||||
|
||||
OTL_CHECK(6); |
||||
min_coord = OTL_NEXT_USHORT( p ); |
||||
max_coord = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( min_coord ) |
||||
otl_base_coord_validate( table + min_coord, valid ); |
||||
|
||||
if ( max_coord ) |
||||
otl_base_coord_validate( table + max_coord, valid ); |
||||
|
||||
OTL_CHECK( count*8 ); |
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
p += 4; /* ignore tag */ |
||||
min_coord = OTL_NEXT_USHORT( p ); |
||||
max_coord = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( min_coord ) |
||||
otl_base_coord_validate( table + min_coord, valid ); |
||||
|
||||
if ( max_coord ) |
||||
otl_base_coord_validate( table + max_coord, valid ); |
||||
} |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_base_script_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt values, default_minmax; |
||||
|
||||
OTL_CHECK(6); |
||||
|
||||
values = OTL_NEXT_USHORT( p ); |
||||
default_minmax = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( values ) |
||||
otl_base_values_validate( table + values, valid ); |
||||
|
||||
if ( default_minmax ) |
||||
otl_base_minmax_validate( table + default_minmax, valid ); |
||||
|
||||
OTL_CHECK( count*6 ); |
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
p += 4; /* ignore tag */ |
||||
otl_base_minmax_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_base_script_list_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK(2); |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK(count*6); |
||||
|
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
p += 4; /* ignore script tag */ |
||||
otl_base_script_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
} |
||||
} |
||||
|
||||
static void |
||||
otl_axis_table_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt tags; |
||||
|
||||
OTL_CHECK(4); |
||||
|
||||
tags = OTL_NEXT_USHORT( p ); |
||||
if ( tags ) |
||||
otl_base_tag_list_validate ( table + tags ); |
||||
|
||||
otl_base_script_list_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
} |
||||
|
||||
|
||||
OTL_LOCALDEF( void ) |
||||
otl_base_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
|
||||
OTL_CHECK(6); |
||||
|
||||
if ( OTL_NEXT_ULONG( p ) != 0x10000UL ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
otl_axis_table_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
otl_axis_table_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
} |
@ -0,0 +1,14 @@ |
||||
#ifndef __OTL_BASE_H__ |
||||
#define __OTL_BASE_H__ |
||||
|
||||
#include "otlayout.h" |
||||
|
||||
OTL_BEGIN_HEADER |
||||
|
||||
OTL_LOCAL( void ) |
||||
otl_base_validate( OTL_Bytes table, |
||||
OTL_Validator valid ); |
||||
|
||||
OTL_END_HEADER |
||||
|
||||
#endif /* __OTL_BASE_H__ */ |
@ -0,0 +1,73 @@ |
||||
#ifndef __OT_LAYOUT_CONFIG_H__ |
||||
#define __OT_LAYOUT_CONFIG_H__ |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** CONFIGURATION MACROS *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
#ifdef __cplusplus |
||||
# define OTL_BEGIN_HEADER extern "C" { |
||||
#else |
||||
# define OTL_BEGIN_HEADER /* nothing */ |
||||
#endif |
||||
|
||||
#ifdef __cplusplus |
||||
# define OTL_END_HEADER } |
||||
#else |
||||
# define OTL_END_HEADER /* nothing */ |
||||
#endif |
||||
|
||||
#ifndef OTL_API |
||||
# ifdef __cplusplus |
||||
# define OTL_API( x ) extern "C" |
||||
# else |
||||
# define OTL_API( x ) extern x |
||||
# endif |
||||
#endif |
||||
|
||||
#ifndef OTL_APIDEF |
||||
# define OTL_APIDEF( x ) x |
||||
#endif |
||||
|
||||
#ifndef OTL_LOCAL |
||||
# define OTL_LOCAL( x ) extern x |
||||
#endif |
||||
|
||||
#ifndef OTL_LOCALDEF |
||||
# define OTL_LOCALDEF( x ) x |
||||
#endif |
||||
|
||||
#define OTL_BEGIN_STMNT do { |
||||
#define OTL_END_STMNT } while (0) |
||||
#define OTL_DUMMY_STMNT do { } while (0) |
||||
|
||||
#define OTL_UNUSED( x ) (x)=(x) |
||||
#define OTL_UNUSED_CONST(x) (void)(x) |
||||
|
||||
|
||||
#include <limits.h> |
||||
#if UINT_MAX == 0xFFFFU |
||||
# define OTL_SIZEOF_INT 2 |
||||
#elif UINT_MAX == 0xFFFFFFFFU |
||||
# define OTL_SIZEOF_INT 4 |
||||
#elif UINT_MAX > 0xFFFFFFFFU && UINT_MAX == 0xFFFFFFFFFFFFFFFFU |
||||
# define OTL_SIZEOF_INT 8 |
||||
#else |
||||
# error "unsupported number of bytes in 'int' type!" |
||||
#endif |
||||
|
||||
#if ULONG_MAX == 0xFFFFFFFFU |
||||
# define OTL_SIZEOF_LONG 4 |
||||
#elif ULONG_MAX > 0xFFFFFFFFU && ULONG_MAX == 0xFFFFFFFFFFFFFFFFU |
||||
# define OTL_SIZEOF_LONG 8 |
||||
#else |
||||
# error "unsupported number of bytes in 'long' type!" |
||||
#endif |
||||
|
||||
/* */ |
||||
|
||||
#endif /* __OT_LAYOUT_CONFIG_H__ */ |
@ -0,0 +1,175 @@ |
||||
#include "otlgdef.h" |
||||
#include "otlcommn.h" |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** ATTACHMENTS LIST *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_attach_point_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
if ( p + 2 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
if ( table + count*2 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_attach_list_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_Bytes coverage; |
||||
OTL_UInt count; |
||||
|
||||
if ( p + 4 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
coverage = table + OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( coverage, valid ); |
||||
if ( count != otl_coverage_get_count( coverage ) ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
if ( p + count*2 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
for ( ; count > 0; count-- ) |
||||
otl_attach_point_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** LIGATURE CARETS *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_caret_value_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
|
||||
if ( p + 4 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
case 2: |
||||
break; |
||||
|
||||
case 3: |
||||
{ |
||||
OTL_Bytes device; |
||||
|
||||
p += 2; |
||||
if ( p + 2 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
otl_device_table_validate( table + OTL_PEEK_USHORT( p ) ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_ligature_glyph_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
if ( p + 2 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( p + count*2 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
for ( ; count > 0; count-- ) |
||||
otl_caret_value_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_ligature_caret_list_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_Bytes coverage; |
||||
OTL_UInt count; |
||||
|
||||
if ( p + 4 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
coverage = table + OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( coverage, valid ); |
||||
if ( count != otl_coverage_get_count( coverage ) ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
if ( p + count*2 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
for ( ; count > 0; count-- ) |
||||
otl_ligature_glyph_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GDEF TABLE *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
OTL_APIDEF( void ) |
||||
otl_gdef_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
|
||||
if ( p + 12 > valid->limit ) |
||||
OTL_INVALID_TOO_SHORT; |
||||
|
||||
/* check format */ |
||||
if ( OTL_NEXT_ULONG( p ) != 0x00010000UL ) |
||||
OTL_INVALID_FORMAT; |
||||
|
||||
/* validate class definition table */ |
||||
otl_class_definition_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
|
||||
/* validate attachment point list */ |
||||
otl_attach_list_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
|
||||
/* validate ligature caret list */ |
||||
otl_ligature_caret_list_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
|
||||
/* validate mark attach class */ |
||||
otl_class_definition_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
} |
||||
|
@ -0,0 +1,14 @@ |
||||
#ifndef __OTL_GDEF_H__ |
||||
#define __OTL_GDEF_H__ |
||||
|
||||
#include "otltable.h" |
||||
|
||||
OTL_BEGIN_HEADER |
||||
|
||||
OTL_API( void ) |
||||
otl_gdef_validate( OTL_Bytes table, |
||||
OTL_Valid valid ); |
||||
|
||||
OTL_END_HEADER |
||||
|
||||
#endif /* __OTL_GDEF_H__ */ |
@ -0,0 +1,980 @@ |
||||
#include "otlgpos.h" |
||||
#include "otlcommn.h" |
||||
|
||||
/* forward declaration */ |
||||
static OTL_ValidateFunc otl_gpos_validate_funcs[]; |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** VALUE RECORDS *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static OTL_UInt |
||||
otl_value_length( OTL_UInt format ) |
||||
{ |
||||
FT_UInt count; |
||||
|
||||
count = (( format & 0xAA ) >> 1) + ( format & 0x55 ); |
||||
count = (( count & 0xCC ) >> 2) + ( count & 0x33 ); |
||||
count = (( count & 0xF0 ) >> 4) + ( count & 0x0F ); |
||||
|
||||
return count; |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_value_validate( OTL_Bytes table, |
||||
OTL_Bytes pos_table, |
||||
OTL_UInt format, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count, device; |
||||
|
||||
if ( format >= 0x100U ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
for ( count = 4; count > 0; count-- ) |
||||
{ |
||||
if ( format & 1 ) |
||||
{ |
||||
OTL_CHECK( 2 ); |
||||
p += 2; |
||||
} |
||||
|
||||
format >>= 1; |
||||
} |
||||
|
||||
for ( count = 4; count > 0; count-- ) |
||||
{ |
||||
if ( format & 1 ) |
||||
{ |
||||
OTL_CHECK( 2 ); |
||||
device = OTL_NEXT_USHORT( p ); |
||||
if ( device ) |
||||
otl_device_table_validate( pos_table + device, valid ); |
||||
} |
||||
format >>= 1; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** ANCHORS *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_anchor_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 6 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
p += 4; |
||||
|
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
break; |
||||
|
||||
case 2: |
||||
OTL_CHECK( 2 ); /* anchor point */ |
||||
break; |
||||
|
||||
case 3: |
||||
{ |
||||
OTL_UInt x_device, y_device; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
x_device = OTL_NEXT_USHORT( p ); |
||||
y_device = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( x_device ) |
||||
otl_device_table_validate( table + x_device, valid ); |
||||
|
||||
if ( y_device ) |
||||
otl_device_table_validate( table + y_device, valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** MARK ARRAY *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_mark_array_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( count * 4 ); |
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
p += 2; /* ignore class index */ |
||||
otl_anchor_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS LOOKUP TYPE 1 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_gpos_lookup1_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
{ |
||||
FT_UInt coverage, value_format; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
value_format = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
otl_value_validate( p, table, value_format, valid ); |
||||
} |
||||
break; |
||||
|
||||
case 2: |
||||
{ |
||||
FT_UInt coverage, value_format, count, len; |
||||
|
||||
OTL_CHECK( 6 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
value_format = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
len = otl_value_length( value_format ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( count * len ); |
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
otl_value_validate( p, table, value_format, valid ); |
||||
p += len; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS LOOKUP TYPE 2 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static otl_gpos_pairset_validate( OTL_Bytes table, |
||||
OTL_Bytes pos_table, |
||||
OTL_UInt format1, |
||||
OTL_UInt format2, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt len1, len2, count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
len1 = otl_value_length( format1 ); |
||||
len2 = otl_value_length( format2 ); |
||||
|
||||
OTL_CHECK( count * (len1+len2+2) ); |
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
p += 2; /* ignore glyph id */ |
||||
otl_value_validate( p, pos_table, format1, valid ); |
||||
p += len1; |
||||
|
||||
otl_value_validate( p, pos_table, format2, valid ); |
||||
p += len2; |
||||
} |
||||
} |
||||
|
||||
static void |
||||
otl_gpos_lookup2_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch (format) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage, value1, value2, count; |
||||
|
||||
OTL_CHECK( 8 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
value1 = OTL_NEXT_USHORT( p ); |
||||
value2 = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
otl_gpos_pairset_validate( table + OTL_NEXT_USHORT( p ), |
||||
table, value1, value2, valid ); |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case 2: |
||||
{ |
||||
OTL_UInt coverage, value1, value2, class1, class2, count1, count2; |
||||
OTL_UInt len1, len2; |
||||
|
||||
OTL_CHECK( 14 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
value1 = OTL_NEXT_USHORT( p ); |
||||
value2 = OTL_NEXT_USHORT( p ); |
||||
class1 = OTL_NEXT_USHORT( p ); |
||||
class2 = OTL_NEXT_USHORT( p ); |
||||
count1 = OTL_NEXT_USHORT( p ); |
||||
count2 = OTL_NEXT_USHORT( p ); |
||||
|
||||
len1 = otl_value_length( value1 ); |
||||
len2 = otl_value_length( value2 ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( count1*count2*(len1+len2) ); |
||||
for ( ; count1 > 0; count1-- ) |
||||
{ |
||||
for ( ; count2 > 0; count2-- ) |
||||
{ |
||||
otl_value_validate( p, table, value1, valid ); |
||||
p += len1; |
||||
|
||||
otl_value_validate( p, table, value2, valid ); |
||||
p += len2; |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS LOOKUP TYPE 3 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_gpos_lookup3_validate( OTL_Bytes table, |
||||
OTL_Valid valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch (format) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage, count, anchor1, anchor2; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( count*4 ); |
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
anchor1 = OTL_NEXT_USHORT( p ); |
||||
anchor2 = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( anchor1 ) |
||||
otl_anchor_validate( table + anchor1, valid ); |
||||
|
||||
if ( anchor2 ) |
||||
otl_anchor_validate( table + anchor2, valid ); |
||||
} |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS LOOKUP TYPE 4 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_base_array_validate( OTL_Bytes table, |
||||
OTL_UInt class_count, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count, count2; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*class_count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
for ( count2 = class_count; count2 > 0; count2-- ) |
||||
otl_anchor_validate( table + OTL_NEXT_USHORT( p ) ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gpos_lookup4_validate( OTL_Bytes table, |
||||
OTL_Valid valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch (format) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt mark_coverage, base_coverage, class_count; |
||||
OTL_UInt mark_array, base_array; |
||||
|
||||
OTL_CHECK( 10 ); |
||||
mark_coverage = OTL_NEXT_USHORT( p ); |
||||
base_coverage = OTL_NEXT_USHORT( p ); |
||||
class_count = OTL_NEXT_USHORT( p ); |
||||
mark_array = OTL_NEXT_USHORT( p ); |
||||
base_array = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + mark_coverage, valid ); |
||||
otl_coverage_validate( table + base_coverage, valid ); |
||||
|
||||
otl_mark_array_validate( table + mark_array, valid ); |
||||
otl_base_array_validate( table, class_count, valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS LOOKUP TYPE 5 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_liga_attach_validate( OTL_Bytes table, |
||||
OTL_UInt class_count, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count, count2; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*class_count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
for ( count2 = class_count; class_count > 0; class_count-- ) |
||||
otl_anchor_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_liga_array_validate( OTL_Bytes table, |
||||
OTL_UInt class_count, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count, count2; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_liga_attach_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gpos_lookup5_validate( OTL_Bytes table, |
||||
OTL_Valid valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch (format) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt mark_coverage, lig_coverage, class_count; |
||||
OTL_UInt mar_array, lig_array; |
||||
|
||||
OTL_CHECK( 10 ); |
||||
mark_coverage = OTL_NEXT_USHORT( p ); |
||||
liga_coverage = OTL_NEXT_USHORT( p ); |
||||
class_count = OTL_NEXT_USHORT( p ); |
||||
mark_array = OTL_NEXT_USHORT( p ); |
||||
liga_array = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + mark_coverage, valid ); |
||||
otl_coverage_validate( table + liga_coverage, valid ); |
||||
|
||||
otl_mark_array_validate( table + mark_array, valid ); |
||||
otl_liga_array_validate( table + liga_array, class_count, valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS LOOKUP TYPE 6 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
|
||||
static void |
||||
otl_mark2_array_validate( OTL_Bytes table, |
||||
OTL_UInt class_count, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count, count2; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*class_count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
for ( count2 = class_count; class_count > 0; class_count-- ) |
||||
otl_anchor_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gpos_lookup6_validate( OTL_Bytes table, |
||||
OTL_Valid valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch (format) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage1, coverage2, class_count, array1, array2; |
||||
|
||||
OTL_CHECK( 10 ); |
||||
coverage1 = OTL_NEXT_USHORT( p ); |
||||
coverage2 = OTL_NEXT_USHORT( p ); |
||||
class_count = OTL_NEXT_USHORT( p ); |
||||
array1 = OTL_NEXT_USHORT( p ); |
||||
array2 = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage1, valid ); |
||||
otl_coverage_validate( table + coverage2, valid ); |
||||
|
||||
otl_mark_array_validate( table + array1, valid ); |
||||
otl_mark2_array_validate( table + array2, valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS LOOKUP TYPE 7 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_pos_rule_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt glyph_count, pos_count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
glyph_count = OTL_NEXT_USHORT( p ); |
||||
pos_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( glyph_count == 0 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
OTL_CHECK( (glyph_count-1)*2 + pos_count*4 ); |
||||
|
||||
/* XXX: check glyph indices and pos lookups */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_pos_rule_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_pos_rule_validate( table + OTL_NEXT_USHORT(p), valid ); |
||||
} |
||||
|
||||
|
||||
|
||||
static void |
||||
otl_pos_class_rule_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt glyph_count, pos_count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
glyph_count = OTL_NEXT_USHORT( p ); |
||||
pos_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( glyph_count == 0 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
OTL_CHECK( (glyph_count-1)*2 + pos_count*4 ); |
||||
|
||||
/* XXX: check glyph indices and pos lookups */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_pos_class_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_pos_rule_validate( table + OTL_NEXT_USHORT(p), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gpos_lookup7_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch (format) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage, count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
break; |
||||
|
||||
case 2: |
||||
{ |
||||
OTL_UInt coverage, class_def, count; |
||||
|
||||
OTL_CHECK( 6 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
class_def = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate ( table + coverage, valid ); |
||||
otl_class_definition_validate( table + class_def, valid ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_ |
||||
} |
||||
break; |
||||
|
||||
case 3: |
||||
{ |
||||
OTL_UInt glyph_count, pos_count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
glyph_count = OTL_NEXT_USHORT( p ); |
||||
pos_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( glyph_count*2 + pos_count*4 ); |
||||
for ( ; glyph_count > 0; glyph_count ) |
||||
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
|
||||
/* XXX: check pos lookups */ |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS LOOKUP TYPE 8 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_chain_pos_rule_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt back_count, input_count, ahead_count, pos_count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
back_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( back_count*2 + 2 ); |
||||
p += back_count*2; |
||||
|
||||
input_count = OTL_NEXT_USHORT( p ); |
||||
if ( input_count == 0 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
OTL_CHECK( input_count*2 ); |
||||
p += (input_count-1)*2; |
||||
|
||||
ahead_count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( ahead_count*2 + 2 ); |
||||
p += ahead_count*2; |
||||
|
||||
pos_count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( pos_count*4 ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_chain_pos_rule_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_chain_pos_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
|
||||
static void |
||||
otl_chain_pos_class_rule_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt back_count, input_count, ahead_count, pos_count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
back_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( back_count*2 + 2 ); |
||||
p += back_count*2; |
||||
|
||||
input_count = OTL_NEXT_USHORT( p ); |
||||
if ( input_count == 0 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
OTL_CHECK( input_count*2 ); |
||||
p += (input_count-1)*2; |
||||
|
||||
ahead_count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( ahead_count*2 + 2 ); |
||||
p += ahead_count*2; |
||||
|
||||
pos_count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( pos_count*4 ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_chain_pos_class_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_chain_pos_class_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gpos_lookup8_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch (format) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage, count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_chain_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ), |
||||
valid ); |
||||
} |
||||
break; |
||||
|
||||
case 2: |
||||
{ |
||||
OTL_UInt coverage, back_class, input_class, ahead_class, count; |
||||
|
||||
OTL_CHECK( 10 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
back_class = OTL_NEXT_USHORT( p ); |
||||
input_class = OTL_NEXT_USHORT( p ); |
||||
ahead_class = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
otl_class_definition_validate( table + back_class, valid ); |
||||
otl_class_definition_validate( table + input_class, valid ); |
||||
otl_class_definition_validate( table + ahead_class, valid ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_chain_pos_class_set_validate( table + OTL_NEXT_USHORT( p ), |
||||
valid ); |
||||
} |
||||
break; |
||||
|
||||
case 3: |
||||
{ |
||||
OTL_UInt back_count, input_count, ahead_count, pos_count, count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
back_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*back_count+2 ); |
||||
for ( count = back_count; count > 0; count-- ) |
||||
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
|
||||
input_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*input_count+2 ); |
||||
for ( count = input_count; count > 0; count-- ) |
||||
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
|
||||
ahead_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*ahead_count+2 ); |
||||
for ( count = ahead_count; count > 0; count-- ) |
||||
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
|
||||
pos_count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( pos_count*4 ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS LOOKUP TYPE 9 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_gpos_lookup9_validate( OTL_Bytes table, |
||||
OTL_Valid valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch (format) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt lookup_type, lookup_offset; |
||||
OTL_ValidateFunc validate; |
||||
|
||||
OTL_CHECK( 6 ); |
||||
lookup_type = OTL_NEXT_USHORT( p ); |
||||
lookup_offset = OTL_NEXT_ULONG( p ); |
||||
|
||||
if ( lookup_type == 0 || lookup_type >= 9 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
validate = otl_gpos_validate_funcs[ lookup_type-1 ]; |
||||
validate( table + lookup_offset, valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
static OTL_ValidateFunc otl_gpos_validate_funcs[ 9 ] = |
||||
{ |
||||
otl_gpos_lookup1_validate, |
||||
otl_gpos_lookup2_validate, |
||||
otl_gpos_lookup3_validate, |
||||
otl_gpos_lookup4_validate, |
||||
otl_gpos_lookup5_validate, |
||||
otl_gpos_lookup6_validate, |
||||
otl_gpos_lookup7_validate, |
||||
otl_gpos_lookup8_validate, |
||||
otl_gpos_lookup9_validate, |
||||
}; |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GPOS TABLE *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
|
||||
OTL_LOCALDEF( void ) |
||||
otl_gpos_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt scripts, features, lookups; |
||||
|
||||
OTL_CHECK( 10 ); |
||||
|
||||
if ( OTL_NEXT_USHORT( p ) != 0x10000UL ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
scripts = OTL_NEXT_USHORT( p ); |
||||
features = OTL_NEXT_USHORT( p ); |
||||
lookups = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_script_list_validate ( table + scripts, valid ); |
||||
otl_feature_list_validate( table + features, valid ); |
||||
|
||||
otl_lookup_list_validate( table + lookups, 9, otl_gpos_validate_funcs, |
||||
valid ); |
||||
} |
||||
|
@ -0,0 +1,14 @@ |
||||
#ifndef __OTL_GPOS_H__ |
||||
#define __OTL_GPOS_H__ |
||||
|
||||
#include "otlayout.h" |
||||
|
||||
OTL_BEGIN_HEADER |
||||
|
||||
OTL_LOCAL( void ) |
||||
otl_gpos_validate( OTL_Bytes table, |
||||
OTL_Validator valid ); |
||||
|
||||
OTL_END_HEADER |
||||
|
||||
#endif /* __OTL_GPOS_H__ */ |
@ -0,0 +1,654 @@ |
||||
#include "otlgsub.h" |
||||
#include "otlcommn.h" |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GSUB LOOKUP TYPE 1 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_gsub_lookup1_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
} |
||||
break; |
||||
|
||||
case 2: |
||||
{ |
||||
OTL_UInt coverage, count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GSUB LOOKUP TYPE 2 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_seq_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
/* check glyph indices */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gsub_lookup2_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format, coverage; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage, seq_count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
seq_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( seq_count*2 ); |
||||
for ( ; seq_count > 0; seq_count-- ) |
||||
otl_seq_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GSUB LOOKUP TYPE 3 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_alternate_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
/* XXX: check glyph indices */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gsub_lookup3_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format, coverage; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage, count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_alternate_set_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GSUB LOOKUP TYPE 4 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_ligature_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_UInt glyph_id, count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
glyph_id = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( count == 0 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
OTL_CHECK( 2*(count-1) ); |
||||
/* XXX: check glyph indices */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_ligature_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_ligature_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gsub_lookup4_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format, coverage; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage, count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_ligature_set_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GSUB LOOKUP TYPE 5 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
|
||||
static void |
||||
otl_sub_rule_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt glyph_count, subst_count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
glyph_count = OTL_NEXT_USHORT( p ); |
||||
subst_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( glyph_count == 0 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
OTL_CHECK( (glyph_count-1)*2 + substcount*4 ); |
||||
|
||||
/* XXX: check glyph indices and subst lookups */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_sub_rule_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_sub_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_sub_class_rule_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_UInt glyph_count, subst_count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
glyph_count = OTL_NEXT_USHORT( p ); |
||||
subst_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( glyph_count == 0 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
OTL_CHECK( (glyph_count-1)*2 + substcount*4 ); |
||||
|
||||
/* XXX: check glyph indices and subst lookups */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_sub_class_rule_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_sub_class_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gsub_lookup5_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format, coverage; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage, count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_sub_rule_set_validate( table + coverage, valid ); |
||||
} |
||||
break; |
||||
|
||||
case 2: |
||||
{ |
||||
OTL_UInt coverage, class_def, count; |
||||
|
||||
OTL_CHECK( 6 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
class_def = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate ( table + coverage, valid ); |
||||
otl_class_definition_validate( table + class_def, valid ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_sub_class_rule_set_validate( table + coveragen valid ); |
||||
} |
||||
break; |
||||
|
||||
case 3: |
||||
{ |
||||
OTL_UInt glyph_count, subst_count, count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
glyph_count = OTL_NEXT_USHORT( p ); |
||||
subst_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*glyph_count + 4*subst_count ); |
||||
for ( count = glyph_count; count > 0; count-- ) |
||||
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GSUB LOOKUP TYPE 6 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
|
||||
static void |
||||
otl_chain_sub_rule_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt back_count, input_count, ahead_count, subst_count, count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
back_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*back_count+2 ); |
||||
p += 2*back_count; |
||||
|
||||
input_count = OTL_NEXT_USHORT( p ); |
||||
if ( input_count == 0 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
OTL_CHECK( 2*input_count ); |
||||
p += 2*(input_count-1); |
||||
|
||||
ahead_count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( 2*ahead_count + 2 ); |
||||
p += 2*ahead_count; |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( 4*count ); |
||||
|
||||
/* XXX: check glyph indices and subst lookups */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_chain_sub_rule_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_chain_sub_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_chain_sub_class_rule_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt back_count, input_count, ahead_count, subst_count, count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
back_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*back_count+2 ); |
||||
p += 2*back_count; |
||||
|
||||
input_count = OTL_NEXT_USHORT( p ); |
||||
if ( input_count == 0 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
OTL_CHECK( 2*input_count ); |
||||
p += 2*(input_count-1); |
||||
|
||||
ahead_count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( 2*ahead_count + 2 ); |
||||
p += 2*ahead_count; |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( 4*count ); |
||||
|
||||
/* XXX: check class indices and subst lookups */ |
||||
} |
||||
|
||||
|
||||
|
||||
static void |
||||
otl_chain_sub_class_set_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_chain_sub_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_gsub_lookup6_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format, coverage; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt coverage, count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_chain_sub_rule_set_validate( table + coverage, valid ); |
||||
} |
||||
break; |
||||
|
||||
case 2: |
||||
{ |
||||
OTL_UInt coverage, back_class, input_class, ahead_class, count; |
||||
|
||||
OTL_CHECK( 10 ); |
||||
coverage = OTL_NEXT_USHORT( p ); |
||||
back_class = OTL_NEXT_USHORT( p ); |
||||
input_class = OTL_NEXT_USHORT( p ); |
||||
ahead_class = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_coverage_validate( table + coverage, valid ); |
||||
|
||||
otl_class_definition_validate( table + back_class, valid ); |
||||
otl_class_definition_validate( table + input_class, valid ); |
||||
otl_class_definition_validate( table + ahead_class, valid ); |
||||
|
||||
OTL_CHECK( 2*count ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_chain_sub_class_set( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
break; |
||||
|
||||
case 3: |
||||
{ |
||||
OTL_UInt back_count, input_count, ahead_count, subst_count, count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
back_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*back_count+2 ); |
||||
for ( count = back_count; count > 0; count-- ) |
||||
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
|
||||
input_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*input_count+2 ); |
||||
for ( count = input_count; count > 0; count-- ) |
||||
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
|
||||
ahead_count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( 2*ahead_count+2 ); |
||||
for ( count = ahead_count; count > 0; count-- ) |
||||
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
|
||||
subst_count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( subst_count*4 ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GSUB LOOKUP TYPE 6 *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
static void |
||||
otl_gsub_lookup7_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt format, coverage; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
format = OTL_NEXT_USHORT( p ); |
||||
switch ( format ) |
||||
{ |
||||
case 1: |
||||
{ |
||||
OTL_UInt lookup_type, lookup_offset; |
||||
OTL_ValidateFunc validate; |
||||
|
||||
OTL_CHECK( 6 ); |
||||
lookup_type = OTL_NEXT_USHORT( p ); |
||||
lookup_offset = OTL_NEXT_ULONG( p ); |
||||
|
||||
if ( lookup_type == 0 || lookup_type >= 7 ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
validate = otl_gsub_validate_funcs[ lookup_type-1 ]; |
||||
validate( table + lookup_offset, valid ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
OTL_INVALID_DATA; |
||||
} |
||||
} |
||||
|
||||
|
||||
static const OTL_ValidateFunc otl_gsub_validate_funcs[ 7 ] = |
||||
{ |
||||
otl_gsub_lookup1_validate, |
||||
otl_gsub_lookup2_validate, |
||||
otl_gsub_lookup3_validate, |
||||
otl_gsub_lookup4_validate, |
||||
otl_gsub_lookup5_validate, |
||||
otl_gsub_lookup6_validate |
||||
}; |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** GSUB TABLE *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
|
||||
OTL_LOCALDEF( void ) |
||||
otl_gsub_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt scripts, features, lookups; |
||||
|
||||
OTL_CHECK( 10 ); |
||||
|
||||
if ( OTL_NEXT_USHORT( p ) != 0x10000UL ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
scripts = OTL_NEXT_USHORT( p ); |
||||
features = OTL_NEXT_USHORT( p ); |
||||
lookups = OTL_NEXT_USHORT( p ); |
||||
|
||||
otl_script_list_validate ( table + scripts, valid ); |
||||
otl_feature_list_validate( table + features, valid ); |
||||
|
||||
otl_lookup_list_validate( table + lookups, 7, otl_gsub_validate_funcs, |
||||
valid ); |
||||
} |
@ -0,0 +1,14 @@ |
||||
#ifndef __OTL_GSUB_H__ |
||||
#define __OTL_GSUB_H__ |
||||
|
||||
#include "otlayout.h" |
||||
|
||||
OTL_BEGIN_HEADER |
||||
|
||||
OTL_LOCAL( void ) |
||||
otl_gsub_validate( OTL_Bytes table, |
||||
OTL_Validator valid ); |
||||
|
||||
OTL_END_HEADER |
||||
|
||||
#endif /* __OTL_GSUB_H__ */ |
@ -0,0 +1,189 @@ |
||||
#include "otljstf.h" |
||||
#include "otlcommn.h" |
||||
#include "otlgpos.h" |
||||
|
||||
static void |
||||
otl_jstf_extender_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_jstf_gsub_mods_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( count*2 ); |
||||
|
||||
/* XXX: check GSUB lookup indices */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_jstf_gpos_mods_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( count*2 ); |
||||
|
||||
/* XXX: check GPOS lookup indices */ |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_jstf_max_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_gpos_subtable_check( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_jstf_priority_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt offset; |
||||
|
||||
OTL_CHECK( 20 ); |
||||
|
||||
/* shrinkage GSUB enable/disable */ |
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_gsub_mods_validate( table + val, valid ); |
||||
|
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_gsub_mods_validate( table + val, valid ); |
||||
|
||||
/* shrinkage GPOS enable/disable */ |
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_gpos_mods_validate( table + val, valid ); |
||||
|
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_gpos_mods_validate( table + val, valid ); |
||||
|
||||
/* shrinkage JSTF max */ |
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_max_validate( table + val, valid ); |
||||
|
||||
/* extension GSUB enable/disable */ |
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_gsub_mods_validate( table + val, valid ); |
||||
|
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_gsub_mods_validate( table + val, valid ); |
||||
|
||||
/* extension GPOS enable/disable */ |
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_gpos_mods_validate( table + val, valid ); |
||||
|
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_gpos_mods_validate( table + val, valid ); |
||||
|
||||
/* extension JSTF max */ |
||||
val = OTL_NEXT_USHORT( p ); |
||||
if ( val ) |
||||
otl_jstf_max_validate( table + val, valid ); |
||||
} |
||||
|
||||
static void |
||||
otl_jstf_lang_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 2 ); |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
OTL_CHECK( count*2 ); |
||||
for ( ; count > 0; count-- ) |
||||
otl_jstf_priority_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
|
||||
|
||||
static void |
||||
otl_jstf_script_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count, extender, default_lang; |
||||
|
||||
OTL_CHECK( 6 ); |
||||
extender = OTL_NEXT_USHORT( p ); |
||||
default_lang = OTL_NEXT_USHORT( p ); |
||||
count = OTL_NEXT_USHORT( p ); |
||||
|
||||
if ( extender ) |
||||
otl_jstf_extender_validate( table + extender, valid ); |
||||
|
||||
if ( default_lang ) |
||||
otl_jstf_lang_validate( table + default_lang, valid ); |
||||
|
||||
OTL_CHECK( 6*count ); |
||||
|
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
p += 4; /* ignore tag */ |
||||
otl_jstf_lang_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
} |
||||
|
||||
|
||||
OTL_LOCALDEF( void ) |
||||
otl_jstf_validate( OTL_Bytes table, |
||||
OTL_Validator valid ) |
||||
{ |
||||
OTL_Bytes p = table; |
||||
OTL_UInt count; |
||||
|
||||
OTL_CHECK( 4 ); |
||||
|
||||
if ( OTL_NEXT_ULONG( p ) != 0x10000UL ) |
||||
OTL_INVALID_DATA; |
||||
|
||||
count = OTL_NEXT_USHORT( p ); |
||||
OTL_CHECK( count*6 ); |
||||
|
||||
for ( ; count > 0; count++ ) |
||||
{ |
||||
p += 4; /* ignore tag */ |
||||
otl_jstf_script_validate( table + OTL_NEXT_USHORT( p ), valid ); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,14 @@ |
||||
#ifndef __OTL_JSTF_H__ |
||||
#define __OTL_JSTF_H__ |
||||
|
||||
#include "otlayout.h" |
||||
|
||||
OTL_BEGIN_HEADER |
||||
|
||||
OTL_LOCAL( void ) |
||||
otl_jstf_validate( OTL_Bytes table, |
||||
OTL_Validator valid ); |
||||
|
||||
OTL_END_HEADER |
||||
|
||||
#endif /* __OTL_JSTF_H__ */ |
@ -0,0 +1,60 @@ |
||||
#ifndef __OTL_TABLE_H__ |
||||
#define __OTL_TABLE_H__ |
||||
|
||||
#include "otlayout.h" |
||||
|
||||
OTL_BEGIN_HEADER |
||||
|
||||
typedef struct OTL_TableRec_* OTL_Table; |
||||
|
||||
typedef enum |
||||
{ |
||||
OTL_TABLE_TYPE_GDEF = 1, |
||||
OTL_TABLE_TYPE_GSUB, |
||||
OTL_TABLE_TYPE_GPOS, |
||||
OTL_TABLE_TYPE_BASE, |
||||
OTL_TABLE_TYPE_JSTF |
||||
|
||||
} OTL_TableType; |
||||
|
||||
|
||||
/* this may become a private structure later */ |
||||
typedef struct OTL_TableRec_ |
||||
{ |
||||
OTL_TableType type; |
||||
OTL_Bytes base; |
||||
OTL_Bytes limit; |
||||
|
||||
OTL_Tag script_tag; |
||||
OTL_Tag lang_tag; |
||||
|
||||
OTL_UInt lookup_count; |
||||
OTL_Byte* lookup_flags; |
||||
|
||||
OTL_UInt feature_count; |
||||
OTL_Tag feature_tags; |
||||
OTL_Byte* feature_flags; |
||||
|
||||
} OTL_TableRec; |
||||
|
||||
|
||||
OTL_API( OTL_Error ) |
||||
otl_table_validate( OTL_Bytes table, |
||||
OTL_Size size, |
||||
OTL_TableType type, |
||||
OTL_Size *abyte_size ); |
||||
|
||||
OTL_API( void ) |
||||
otl_table_init( OTL_Table table, |
||||
OTL_TableType type, |
||||
OTL_Bytes base, |
||||
OTL_Size size ); |
||||
|
||||
OTL_API( void ) |
||||
otl_table_set_script( OTL_Table table, |
||||
OTL_ScriptTag script, |
||||
OTL_LangTag language ); |
||||
|
||||
OTL_END_HEADER |
||||
|
||||
#endif /* __OTL_TABLE_H__ */ |
@ -0,0 +1,86 @@ |
||||
/* this file may be included several times by other parts of */ |
||||
/* the OpenType Layout library.. don't add #ifdef .. #endif */ |
||||
/* delimiters to it... */ |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** SCRIPT TAGS *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
#ifndef OTL_SCRIPT_TAG |
||||
#define OTL_SCRIPT_TAG(c1,c2,c3,c4,s,n) /* void */ |
||||
#endif |
||||
|
||||
OTL_SCRIPT_TAG( 'a','r','a','b', "Arabic", ARABIC ) |
||||
OTL_SCRIPT_TAG( 'a','r','m','n', "Armenian", ARMENIAN ) |
||||
OTL_SCRIPT_TAG( 'b','e','n','g', "Bengali", BENGALI ) |
||||
OTL_SCRIPT_TAG( 'b','o','p','o', "Bopomofo", BOPOMOFO ) |
||||
OTL_SCRIPT_TAG( 'b','r','a','i', "Braille", BRAILLE ) |
||||
OTL_SCRIPT_TAG( 'c','a','n','s', "Canadian Syllabic", CANADIAN ) |
||||
OTL_SCRIPT_TAG( 'c','h','e','r', "Cherokee", CHEROKEE ) |
||||
OTL_SCRIPT_TAG( 'h','a','n','i', "CJK Ideographic", CJK ) |
||||
OTL_SCRIPT_TAG( 'c','y','r','l', "Cyrillic", CYRILLIC ) |
||||
OTL_SCRIPT_TAG( 'd','e','v','a', "Devanagari", DEVANAGARI ) |
||||
OTL_SCRIPT_TAG( 'e','t','h','i', "Ethiopic", ETHIOPIC ) |
||||
OTL_SCRIPT_TAG( 'g','e','o','r', "Georgian", GEORGIAN ) |
||||
OTL_SCRIPT_TAG( 'g','r','e','k', "Greek", GREEK ) |
||||
OTL_SCRIPT_TAG( 'g','u','j','r', "Gujarati", GUJARATI ) |
||||
OTL_SCRIPT_TAG( 'g','u','r','u', "Gurmukhi", GURMUKHI ) |
||||
OTL_SCRIPT_TAG( 'j','a','m','o', "Hangul Jamo", JAMO ) |
||||
OTL_SCRIPT_TAG( 'h','a','n','g', "Hangul", HANGUL ) |
||||
OTL_SCRIPT_TAG( 'h','e','b','r', "Hebrew", HEBREW ) |
||||
OTL_SCRIPT_TAG( 'h','i','r','a', "Hiragana", HIRAGANA ) |
||||
OTL_SCRIPT_TAG( 'k','n','d','a', "Kannada", KANNADA ) |
||||
OTL_SCRIPT_TAG( 'k','a','n','a', "Katakana", KATAKANA ) |
||||
OTL_SCRIPT_TAG( 'k','h','m','r', "Khmer", KHMER ) |
||||
OTL_SCRIPT_TAG( 'l','a','o',' ', "Lao", LAO ) |
||||
OTL_SCRIPT_TAG( 'l','a','t','n', "Latin", LATIN ) |
||||
OTL_SCRIPT_TAG( 'm','l','y','m', "Malayalam", MALAYALAM ) |
||||
OTL_SCRIPT_TAG( 'm','o','n','g', "Mongolian", MONGOLIAN ) |
||||
OTL_SCRIPT_TAG( 'm','y','m','r', "Myanmar", MYANMAR ) |
||||
OTL_SCRIPT_TAG( 'o','g','a','m', "Ogham", OGHAM ) |
||||
OTL_SCRIPT_TAG( 'o','r','y','a', "Oriya", ORIYA ) |
||||
OTL_SCRIPT_TAG( 'r','u','n','r', "Runic", RUNIC ) |
||||
OTL_SCRIPT_TAG( 's','i','n','h', "Sinhala", SINHALA ) |
||||
OTL_SCRIPT_TAG( 's','y','r','c', "Syriac", SYRIAC ) |
||||
OTL_SCRIPT_TAG( 't','a','m','l', "Tamil", TAMIL ) |
||||
OTL_SCRIPT_TAG( 't','e','l','u', "Telugu", TELUGU ) |
||||
OTL_SCRIPT_TAG( 't','h','a','a', "Thaana", THAANA ) |
||||
OTL_SCRIPT_TAG( 't','h','a','i', "Thai", THAI ) |
||||
OTL_SCRIPT_TAG( 't','i','b','t', "Tibetan", TIBETAN ) |
||||
OTL_SCRIPT_TAG( 'y','i',' ',' ', "Yi", YI ) |
||||
|
||||
#undef OTL_SCRIPT_TAG |
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** LANGUAGE TAGS *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
#ifndef OTL_LANG_TAG |
||||
#define OTL_LANG_TAG(c1,c2,c3,c4,s,n) /* void */ |
||||
#endif |
||||
|
||||
#undef OTL_LANG_TAG |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
/***** *****/ |
||||
/***** FEATURE TAGS *****/ |
||||
/***** *****/ |
||||
/************************************************************************/ |
||||
/************************************************************************/ |
||||
|
||||
#ifndef OTL_FEATURE_TAG |
||||
#define OTL_FEATURE_TAG(c1,c2,c3,c4,s,n) /* void */ |
||||
#endif |
||||
|
||||
#undef OTL_FEATURE_TAG |
||||
|
Loading…
Reference in new issue