* src/truetype/ttgload.c (TT_Load_Glyph): finally fixing the last

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 incomplete
This commit is contained in:
David Turner 2002-05-04 18:02:59 +00:00
parent 948ee807e1
commit 8cd8907311
18 changed files with 2870 additions and 90 deletions

View File

@ -1,3 +1,30 @@
2002-05-04 David Turner <david@freetype.org>
* src/truetype/ttgload.c (TT_Load_Glyph): finally fixing the last
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 incomplete
2002-05-02 Werner Lemberg <wl@gnu.org>
* src/sfnt/ttcmap0.c (tt_cmap4_char_index): Fix serious typo

168
src/otlayout/otlayout.h Normal file
View File

@ -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__ */

181
src/otlayout/otlbase.c Normal file
View File

@ -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 ) );
}

14
src/otlayout/otlbase.h Normal file
View File

@ -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__ */

View File

@ -38,12 +38,12 @@
if ( table + 4 > valid->limit )
OTL_INVALID_TOO_SHORT;
format = OTL_NEXT_UShort( p );
format = OTL_NEXT_USHORT( p );
switch ( format )
{
case 1:
{
OTL_UInt count = OTL_NEXT_UShort( p );
OTL_UInt count = OTL_NEXT_USHORT( p );
if ( p + count * 2 >= valid->limit )
@ -55,7 +55,7 @@
case 2:
{
OTL_UInt n, num_ranges = OTL_NEXT_UShort( p );
OTL_UInt n, num_ranges = OTL_NEXT_USHORT( p );
OTL_UInt start, end, start_cover, total = 0, last = 0;
@ -64,9 +64,9 @@
for ( n = 0; n < num_ranges; n++ )
{
start = OTL_NEXT_UShort( p );
end = OTL_NEXT_UShort( p );
start_cover = OTL_NEXT_UShort( p );
start = OTL_NEXT_USHORT( p );
end = OTL_NEXT_USHORT( p );
start_cover = OTL_NEXT_USHORT( p );
if ( start > end || start_cover != total )
OTL_INVALID_DATA;
@ -90,8 +90,8 @@
otl_coverage_get_count( OTL_Bytes table )
{
OTL_Bytes p = table;
OTL_UInt format = OTL_NEXT_UShort( p );
OTL_UInt count = OTL_NEXT_UShort( p );
OTL_UInt format = OTL_NEXT_USHORT( p );
OTL_UInt count = OTL_NEXT_USHORT( p );
OTL_UInt result = 0;
@ -107,8 +107,8 @@
for ( ; count > 0; count-- )
{
start = OTL_NEXT_UShort( p );
end = OTL_NEXT_UShort( p );
start = OTL_NEXT_USHORT( p );
end = OTL_NEXT_USHORT( p );
p += 2; /* skip start_index */
result += end - start + 1;
@ -129,8 +129,8 @@
OTL_UInt glyph_index )
{
OTL_Bytes p = table;
OTL_UInt format = OTL_NEXT_UShort( p );
OTL_UInt count = OTL_NEXT_UShort( p );
OTL_UInt format = OTL_NEXT_USHORT( p );
OTL_UInt count = OTL_NEXT_USHORT( p );
switch ( format )
@ -145,7 +145,7 @@
{
mid = ( min + max ) >> 1;
p = table + 2 * mid;
gindex = OTL_PEEK_UShort( p );
gindex = OTL_PEEK_USHORT( p );
if ( glyph_index == gindex )
return (OTL_Int)mid;
@ -169,15 +169,15 @@
{
mid = ( min + max ) >> 1;
p = table + 6 * mid;
start = OTL_NEXT_UShort( p );
end = OTL_NEXT_UShort( p );
start = OTL_NEXT_USHORT( p );
end = OTL_NEXT_USHORT( p );
if ( glyph_index < start )
max = mid;
else if ( glyph_index > end )
min = mid + 1;
else
return (OTL_Int)( glyph_index + OTL_NEXT_UShort( p ) - start );
return (OTL_Int)( glyph_index + OTL_NEXT_USHORT( p ) - start );
}
}
break;
@ -209,18 +209,18 @@
if ( p + 4 > valid->limit )
OTL_INVALID_TOO_SHORT;
format = OTL_NEXT_UShort( p );
format = OTL_NEXT_USHORT( p );
switch ( format )
{
case 1:
{
OTL_UInt count, start = OTL_NEXT_UShort( p );
OTL_UInt count, start = OTL_NEXT_USHORT( p );
if ( p + 2 > valid->limit )
OTL_INVALID_TOO_SHORT;
count = OTL_NEXT_UShort( p );
count = OTL_NEXT_USHORT( p );
if ( p + count * 2 > valid->limit )
OTL_INVALID_TOO_SHORT;
@ -231,7 +231,7 @@
case 2:
{
OTL_UInt n, num_ranges = OTL_NEXT_UShort( p );
OTL_UInt n, num_ranges = OTL_NEXT_USHORT( p );
OTL_UInt start, end, value, last = 0;
@ -240,9 +240,9 @@
for ( n = 0; n < num_ranges; n++ )
{
start = OTL_NEXT_UShort( p );
end = OTL_NEXT_UShort( p );
value = OTL_NEXT_UShort( p ); /* ignored */
start = OTL_NEXT_USHORT( p );
end = OTL_NEXT_USHORT( p );
value = OTL_NEXT_USHORT( p ); /* ignored */
if ( start > end || ( n > 0 && start <= last ) )
OTL_INVALID_DATA;
@ -263,29 +263,29 @@
OTL_UInt glyph_index )
{
OTL_Bytes p = table;
OTL_UInt format = OTL_NEXT_UShort( p );
OTL_UInt format = OTL_NEXT_USHORT( p );
switch ( format )
{
case 1:
{
OTL_UInt start = OTL_NEXT_UShort( p );
OTL_UInt count = OTL_NEXT_UShort( p );
OTL_UInt start = OTL_NEXT_USHORT( p );
OTL_UInt count = OTL_NEXT_USHORT( p );
OTL_UInt idx = (OTL_UInt)( glyph_index - start );
if ( idx < count )
{
p += 2 * idx;
return OTL_PEEK_UShort( p );
return OTL_PEEK_USHORT( p );
}
}
break;
case 2:
{
OTL_UInt count = OTL_NEXT_UShort( p );
OTL_UInt count = OTL_NEXT_USHORT( p );
OTL_UInt min = 0, max = count, mid, gindex;
@ -294,15 +294,15 @@
{
mid = ( min + max ) >> 1;
p = table + 6 * mid;
start = OTL_NEXT_UShort( p );
end = OTL_NEXT_UShort( p );
start = OTL_NEXT_USHORT( p );
end = OTL_NEXT_USHORT( p );
if ( glyph_index < start )
max = mid;
else if ( glyph_index > end )
min = mid + 1;
else
return OTL_PEEK_UShort( p );
return OTL_PEEK_USHORT( p );
}
}
break;
@ -334,9 +334,9 @@
if ( p + 8 > valid->limit )
OTL_INVALID_TOO_SHORT;
start = OTL_NEXT_UShort( p );
end = OTL_NEXT_UShort( p );
format = OTL_NEXT_UShort( p );
start = OTL_NEXT_USHORT( p );
end = OTL_NEXT_USHORT( p );
format = OTL_NEXT_USHORT( p );
if ( format < 1 || format > 3 || end < start )
OTL_INVALID_DATA;
@ -354,7 +354,7 @@
OTL_Bytes p = table;
return OTL_PEEK_UShort( p );
return OTL_PEEK_USHORT( p );
}
@ -364,7 +364,7 @@
OTL_Bytes p = table + 2;
return OTL_PEEK_UShort( p );
return OTL_PEEK_USHORT( p );
}
@ -377,9 +377,9 @@
OTL_UInt start, end, format, idx, value;
start = OTL_NEXT_UShort( p );
end = OTL_NEXT_UShort( p );
format = OTL_NEXT_UShort( p );
start = OTL_NEXT_USHORT( p );
end = OTL_NEXT_USHORT( p );
format = OTL_NEXT_USHORT( p );
if ( size >= start && size <= end )
{
@ -391,7 +391,7 @@
case 1:
idx = (OTL_UInt)( ( size - start ) * 2 );
p += idx / 16;
value = OTL_PEEK_UShort( p );
value = OTL_PEEK_USHORT( p );
shift = idx & 15;
result = (OTL_Short)( value << shift ) >> ( 14 - shift );
@ -400,7 +400,7 @@
case 2:
idx = (OTL_UInt)( ( size - start ) * 4 );
p += idx / 16;
value = OTL_PEEK_UShort( p );
value = OTL_PEEK_USHORT( p );
shift = idx & 15;
result = (OTL_Short)( value << shift ) >> ( 12 - shift );
@ -409,7 +409,7 @@
case 3:
idx = (OTL_UInt)( ( size - start ) * 8 );
p += idx / 16;
value = OTL_PEEK_UShort( p );
value = OTL_PEEK_USHORT( p );
shift = idx & 15;
result = (OTL_Short)( value << shift ) >> ( 8 - shift );
@ -444,14 +444,14 @@
OTL_INVALID_TOO_SHORT;
p += 4;
num_tables = OTL_NEXT_UShort( p );
num_tables = OTL_NEXT_USHORT( p );
if ( p + num_tables * 2 > valid->limit )
OTL_INVALID_TOO_SHORT;
for ( ; num_tables > 0; num_tables-- )
{
offset = OTL_NEXT_UShort( p );
offset = OTL_NEXT_USHORT( p );
if ( table + offset >= valid->limit )
OTL_INVALID_OFFSET;
@ -467,7 +467,7 @@
OTL_Bytes p = table + 4;
return OTL_PEEK_UShort( p );
return OTL_PEEK_USHORT( p );
}
@ -480,11 +480,11 @@
p = table + 4;
count = OTL_NEXT_UShort( p );
count = OTL_NEXT_USHORT( p );
if ( idx < count )
{
p += idx * 2;
result = table + OTL_PEEK_UShort( p );
result = table + OTL_PEEK_USHORT( p );
}
return result;
@ -510,14 +510,14 @@
if ( p + 2 > valid->limit )
OTL_INVALID_TOO_SHORT;
num_lookups = OTL_NEXT_UShort( p );
num_lookups = OTL_NEXT_USHORT( p );
if ( p + num_lookups * 2 > valid->limit )
OTL_INVALID_TOO_SHORT;
for ( ; num_lookups > 0; num_lookups-- )
{
offset = OTL_NEXT_UShort( p );
offset = OTL_NEXT_USHORT( p );
otl_lookup_validate( table + offset, valid );
}
@ -530,7 +530,7 @@
OTL_Bytes p = table;
return OTL_PEEK_UShort( p );
return OTL_PEEK_USHORT( p );
}
@ -543,11 +543,11 @@
p = table;
count = OTL_NEXT_UShort( p );
count = OTL_NEXT_USHORT( p );
if ( idx < count )
{
p += idx * 2;
result = table + OTL_PEEK_UShort( p );
result = table + OTL_PEEK_USHORT( p );
}
return result;
@ -576,7 +576,7 @@
OTL_Pointer func_data )
{
OTL_Bytes p = table;
OTL_UInt count = OTL_NEXT_UShort( p );
OTL_UInt count = OTL_NEXT_USHORT( p );
for ( ; count > 0; count-- )
@ -603,8 +603,8 @@
if ( p + 4 > valid->limit )
OTL_INVALID_TOO_SHORT;
feat_params = OTL_NEXT_UShort( p ); /* ignored */
num_lookups = OTL_NEXT_UShort( p );
feat_params = OTL_NEXT_USHORT( p ); /* ignored */
num_lookups = OTL_NEXT_USHORT( p );
if ( p + num_lookups * 2 > valid->limit )
OTL_INVALID_TOO_SHORT;
@ -619,7 +619,7 @@
OTL_Bytes p = table + 4;
return OTL_PEEK_UShort( p );
return OTL_PEEK_USHORT( p );
}
@ -634,13 +634,13 @@
p = table + 4;
num_features = OTL_NEXT_UShort( p );
num_features = OTL_NEXT_USHORT( p );
p += start * 2;
for ( ; count > 0 && start < num_features; count--, start++ )
{
lookups[0] = OTL_NEXT_UShort(p);
lookups[0] = OTL_NEXT_USHORT(p);
lookups++;
result++;
}
@ -668,7 +668,7 @@
if ( table + 2 > valid->limit )
OTL_INVALID_TOO_SHORT;
num_features = OTL_NEXT_UShort( p );
num_features = OTL_NEXT_USHORT( p );
if ( p + num_features * 2 > valid->limit )
OTL_INVALID_TOO_SHORT;
@ -676,7 +676,7 @@
for ( ; num_features > 0; num_features-- )
{
p += 4; /* skip tag */
offset = OTL_NEXT_UShort( p );
offset = OTL_NEXT_USHORT( p );
otl_feature_table_validate( table + offset, valid );
}
@ -689,7 +689,7 @@
OTL_Bytes p = table;
return OTL_PEEK_UShort( p );
return OTL_PEEK_USHORT( p );
}
@ -702,12 +702,12 @@
p = table;
count = OTL_NEXT_UShort( p );
count = OTL_NEXT_USHORT( p );
if ( idx < count )
{
p += idx * 2;
result = table + OTL_PEEK_UShort( p );
result = table + OTL_PEEK_USHORT( p );
}
return result;
@ -724,10 +724,10 @@
p = table;
count = OTL_NEXT_UShort( p );
count = OTL_NEXT_USHORT( p );
for ( ; count > 0; count-- )
func( table + OTL_NEXT_UShort( p ), func_data );
func( table + OTL_NEXT_USHORT( p ), func_data );
}
@ -753,9 +753,9 @@
if ( table + 6 >= valid->limit )
OTL_INVALID_TOO_SHORT;
lookup_order = OTL_NEXT_UShort( p );
req_feature = OTL_NEXT_UShort( p );
num_features = OTL_NEXT_UShort( p );
lookup_order = OTL_NEXT_USHORT( p );
req_feature = OTL_NEXT_USHORT( p );
num_features = OTL_NEXT_USHORT( p );
/* XXX: check req_feature if not 0xFFFFU */
@ -769,10 +769,19 @@
OTL_LOCALDEF( OTL_UInt )
otl_lang_get_count( OTL_Bytes table )
{
OTL_Bytes p = table + 4;
OTL_Bytes p = table + 4;
return OTL_PEEK_USHORT( p );
}
return OTL_PEEK_UShort( p );
OTL_LOCALDEF( OTL_UInt )
otl_lang_get_req_feature( OTL_Bytes table )
{
OTL_Bytes p = table + 2;
return OTL_PEEK_USHORT( p );
}
@ -783,7 +792,7 @@
OTL_UInt *features )
{
OTL_Bytes p = table + 4;
OTL_UInt num_features = OTL_NEXT_UShort( p );
OTL_UInt num_features = OTL_NEXT_USHORT( p );
OTL_UInt result = 0;
@ -791,7 +800,7 @@
for ( ; count > 0 && start < num_features; start++, count-- )
{
features[0] = OTL_NEXT_UShort( p );
features[0] = OTL_NEXT_USHORT( p );
features++;
result++;
}
@ -800,14 +809,6 @@
}
OTL_LOCALDEF( OTL_UInt )
otl_lang_get_req_feature( OTL_Bytes table )
{
OTL_Bytes p = table + 2;
return OTL_PEEK_UShort( p );
}
/*************************************************************************/
@ -820,8 +821,8 @@
OTL_LOCALDEF( void )
otl_script_table_validate( OTL_Bytes table,
OTL_Validator valid )
otl_script_validate( OTL_Bytes table,
OTL_Validator valid )
{
OTL_UInt default_lang;
OTL_Bytes p = table;
@ -830,8 +831,8 @@
if ( table + 4 > valid->limit )
OTL_INVALID_TOO_SHORT;
default_lang = OTL_NEXT_UShort( p );
num_langs = OTL_NEXT_UShort( p );
default_lang = OTL_NEXT_USHORT( p );
num_langs = OTL_NEXT_USHORT( p );
if ( default_lang != 0 )
{
@ -848,7 +849,7 @@
p += 4; /* skip tag */
offset = OTL_NEXT_UShort( p );
offset = OTL_NEXT_USHORT( p );
otl_lang_validate( table + offset, valid );
}
@ -866,7 +867,7 @@
if ( list + 2 > valid->limit )
OTL_INVALID_TOO_SHORT;
num_scripts = OTL_NEXT_UShort( p );
num_scripts = OTL_NEXT_USHORT( p );
if ( p + num_scripts * 6 > valid->limit )
OTL_INVALID_TOO_SHORT;
@ -877,11 +878,63 @@
p += 4; /* skip tag */
offset = OTL_NEXT_UShort( p );
offset = OTL_NEXT_USHORT( p );
otl_script_table_validate( list + offset, valid );
}
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** LOOKUP LISTS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static void
otl_lookup_table_validate( OTL_Bytes table,
OTL_UInt type_count,
OTL_ValidateFunc* type_funcs,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt lookup_type, lookup_flag, count;
OTL_ValidateFunc validate;
OTL_CHECK( 6 );
lookup_type = OTL_NEXT_USHORT( p );
lookup_flag = OTL_NEXT_USHORT( p );
count = OTL_NEXT_USHORT( p );
if ( lookup_type == 0 || lookup_type >= type_count )
OTL_INVALID_DATA;
validate = type_funcs[ lookup_type - 1 ];
OTL_CHECK( 2*count );
for ( ; count > 0; count-- )
validate( table + OTL_NEXT_USHORT( p ), valid );
}
OTL_LOCALDEF( void )
otl_lookup_list_validate( OTL_Bytes table,
OTL_UInt type_count,
OTL_ValidateFunc* type_funcs,
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_lookup_table_validate( table + OTL_NEXT_USHORT( p ),
type_count, type_funcs, valid );
}
/* END */

View File

@ -208,6 +208,65 @@ OTL_BEGIN_HEADER
OTL_ForeachFunc func,
OTL_Pointer func_data );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** LANGUAGE SYSTEM *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
OTL_LOCAL( void )
otl_lang_validate( OTL_Bytes table,
OTL_Validator valid );
OTL_LOCAL( OTL_UInt )
otl_lang_get_req_feature( OTL_Bytes table );
OTL_LOCAL( OTL_UInt )
otl_lang_get_count( OTL_Bytes table );
OTL_LOCAL( OTL_UInt )
otl_lang_get_features( OTL_Bytes table,
OTL_UInt start,
OTL_UInt count,
OTL_UInt *features );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** SCRIPTS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
OTL_LOCAL( void )
otl_script_list_validate( OTL_Bytes list,
OTL_Validator valid );
OTL_LOCAL( OTL_Bytes )
otl_script_list_get_script( OTL_Bytes table );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** LOOKUP LISTS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
OTL_LOCAL( void )
otl_lookup_list_validate( OTL_Bytes list,
OTL_UInt type_count,
OTL_ValidateFunc* type_funcs,
OTL_Validator valid );
/* */
OTL_END_HEADER

73
src/otlayout/otlconf.h Normal file
View File

@ -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__ */

175
src/otlayout/otlgdef.c Normal file
View File

@ -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 ) );
}

14
src/otlayout/otlgdef.h Normal file
View File

@ -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__ */

980
src/otlayout/otlgpos.c Normal file
View File

@ -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 );
}

14
src/otlayout/otlgpos.h Normal file
View File

@ -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__ */

654
src/otlayout/otlgsub.c Normal file
View File

@ -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 );
}

14
src/otlayout/otlgsub.h Normal file
View File

@ -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__ */

189
src/otlayout/otljstf.c Normal file
View File

@ -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 );
}
}

14
src/otlayout/otljstf.h Normal file
View File

@ -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__ */

60
src/otlayout/otltable.h Normal file
View File

@ -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__ */

86
src/otlayout/otltags.h Normal file
View File

@ -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

View File

@ -1543,9 +1543,6 @@
/* clear all outline flags, except the `owner' one */
glyph->outline.flags = 0;
if ( size && size->root.metrics.y_ppem < 24 )
glyph->outline.flags |= ft_outline_high_precision;
/* let's initialize the rest of our loader now */
loader.load_flags = load_flags;
@ -1581,6 +1578,14 @@
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
/* Don't forget to set the 'high precision' bit flag !! */
/* This is _critical_ to get correct output for monochrome */
/* TrueType glyphs at all sizes using the bytecode interpreter */
/* */
if ( size && size->root.metrics.y_ppem < 24 )
glyph->outline.flags |= ft_outline_high_precision;
Exit:
return error;
}