adding several experimental sources:
- OpenType Layout validation and parsing (common tables) - Type 1 charmap processing
This commit is contained in:
parent
53b3fa1da5
commit
617a2e1c3c
@ -74,6 +74,159 @@ FT_BEGIN_HEADER
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/**** ****/
|
||||
/**** ****/
|
||||
/**** V A L I D A T I O N ****/
|
||||
/**** ****/
|
||||
/**** ****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* handle to a validation object */
|
||||
typedef struct FT_ValidatorRec_* FT_Validator;
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* there are three distinct validation levels defined here:
|
||||
*
|
||||
* FT_VALIDATE_DEFAULT ::
|
||||
* a table that passes this validation level can be used reliably by
|
||||
* FreeType. It generally means that all offsets have been checked to
|
||||
* prevent out-of-bound reads, array counts are correct, etc..
|
||||
*
|
||||
*
|
||||
* FT_VALIDATE_TIGHT ::
|
||||
* a table that passes this validation level can be used reliably and
|
||||
* doesn't contain invalid data. For example, a charmap table that
|
||||
* returns invalid glyph indices will not pass, even though it can
|
||||
* be used with FreeType in default mode (the library will simply
|
||||
* return an error later when trying to load the glyph)
|
||||
*
|
||||
* it also check that fields that must be a multiple of 2, 4 or 8 don't
|
||||
* have incorrect values, etc..
|
||||
*
|
||||
*
|
||||
* FT_VALIDATE_PARANOID ::
|
||||
* only for font facists. Checks that a table follows the specification
|
||||
* 100%. Very few fonts will be able to pass this level anyway but it
|
||||
* can be useful for certain tools like font editors/converters..
|
||||
*/
|
||||
typedef enum FT_ValidationLevel_
|
||||
{
|
||||
FT_VALIDATE_DEFAULT = 0,
|
||||
FT_VALIDATE_TIGHT,
|
||||
FT_VALIDATE_PARANOID
|
||||
|
||||
} FT_ValidationLevel;
|
||||
|
||||
|
||||
/* validator structure */
|
||||
typedef struct FT_ValidatorRec_
|
||||
{
|
||||
FT_Byte* base; /* address of table in memory */
|
||||
FT_Byte* limit; /* 'base' + sizeof(table) in memory */
|
||||
FT_ValidationLevel level; /* validation level */
|
||||
FT_Error error; /* error returned. 0 means success */
|
||||
|
||||
jmp_buf jump_buffer; /* used for exception handling */
|
||||
|
||||
} FT_ValidatorRec;
|
||||
|
||||
|
||||
/* sets the error field in a validator, then calls 'longjmp' to return */
|
||||
/* to high-level caller. Using 'setjmp/longjmp' avoids many stupid */
|
||||
/* error checks within the validation routines.. */
|
||||
/* */
|
||||
FT_BASE( void )
|
||||
ft_validate_error( FT_Valid valid,
|
||||
FT_Error error );
|
||||
|
||||
/* calls ft_validate_error. Assumes that the 'valid' local variable holds */
|
||||
/* a pointer to the current validator object.. */
|
||||
/* */
|
||||
#define FT_INVALID(_error) ft_validate_error( valid, _error )
|
||||
|
||||
/* called when a broken table is detected */
|
||||
#define FT_INVALID_TOO_SHORT FT_INVALID( FT_Err_Invalid_Format )
|
||||
|
||||
/* called when an invalid offset is detected */
|
||||
#define FT_INVALID_OFFSET FT_INVALID( FT_Err_Invalid_Offset )
|
||||
|
||||
/* called when an invalid format/value is detected */
|
||||
#define FT_INVALID_FORMAT FT_INVALID( FT_Err_Invalid_Format )
|
||||
|
||||
/* called when an invalid glyph index is detected */
|
||||
#define FT_INVALID_GLYPH_ID FT_INVALID( FT_Err_Invalid_Glyph_Id )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/**** ****/
|
||||
/**** ****/
|
||||
/**** C H A R M A P S ****/
|
||||
/**** ****/
|
||||
/**** ****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* handle to internal charmap object */
|
||||
typedef struct FT_CMapRec_* FT_CMap;
|
||||
|
||||
/* handle to charmap class structure */
|
||||
typedef const struct FT_CMap_ClassRec_* FT_CMap_Class;
|
||||
|
||||
/* internal charmap object structure */
|
||||
typedef struct FT_CMapRec_
|
||||
{
|
||||
FT_CharMapRec charmap;
|
||||
FT_CMap_Class clazz;
|
||||
FT_Pointer data;
|
||||
|
||||
} FT_CMapRec;
|
||||
|
||||
/* typecase any pointer to a charmap handle */
|
||||
#define FT_CMAP(x) ((FT_CMap)(x))
|
||||
|
||||
/* obvious macros */
|
||||
#define FT_CMAP_PLATFORM_ID(x) FT_CMAP(x)->charmap.platform_id
|
||||
#define FT_CMAP_ENCODING_ID(x) FT_CMAP(x)->charmap.encoding_id
|
||||
#define FT_CMAP_ENCODING(x) FT_CMAP(x)->charmap.encoding
|
||||
#define FT_CMAP_FACE(x) FT_CMAP(x)->charmap.face
|
||||
|
||||
|
||||
/* class method definitions */
|
||||
typedef FT_Error (*FT_CMap_InitFunc)( FT_CMap cmap,
|
||||
FT_Pointer data );
|
||||
|
||||
typedef void (*FT_CMap_DoneFunc)( FT_CMap cmap );
|
||||
|
||||
typedef FT_Error (*FT_CMap_ValidateFunc)( FT_Pointer cmap_data,
|
||||
FT_Validator valid );
|
||||
|
||||
typedef FT_UInt (*FT_CMap_CharIndexFunc)( FT_Pointer cmap_data,
|
||||
FT_ULong char_code );
|
||||
|
||||
typedef FT_UInt (*FT_CMap_CharNextFunc)( FT_Pointer cmap_data,
|
||||
FT_ULong *achar_code );
|
||||
|
||||
typedef struct FT_CMap_ClassRec_
|
||||
{
|
||||
FT_UInt size;
|
||||
FT_CMap_InitFunc init;
|
||||
FT_CMap_DoneFunc done;
|
||||
FT_CMap_ValidateFunc validate;
|
||||
FT_CMap_CharIndexFunc char_index;
|
||||
FT_CMap_CharNextFunc char_next;
|
||||
|
||||
} FT_CMap_ClassRec;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Struct> */
|
||||
@ -330,109 +483,6 @@ FT_BEGIN_HEADER
|
||||
FT_Done_GlyphSlot( FT_GlyphSlot slot );
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/**** ****/
|
||||
/**** ****/
|
||||
/**** G L Y P H L O A D E R ****/
|
||||
/**** ****/
|
||||
/**** ****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1
|
||||
#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2
|
||||
#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4
|
||||
#define FT_SUBGLYPH_FLAG_SCALE 8
|
||||
#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40
|
||||
#define FT_SUBGLYPH_FLAG_2X2 0x80
|
||||
#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
FT_GLYPH_OWN_BITMAP = 1
|
||||
};
|
||||
|
||||
|
||||
struct FT_SubGlyph_
|
||||
{
|
||||
FT_Int index;
|
||||
FT_UShort flags;
|
||||
FT_Int arg1;
|
||||
FT_Int arg2;
|
||||
FT_Matrix transform;
|
||||
};
|
||||
|
||||
|
||||
typedef struct FT_GlyphLoad_
|
||||
{
|
||||
FT_Outline outline; /* outline */
|
||||
FT_UInt num_subglyphs; /* number of subglyphs */
|
||||
FT_SubGlyph* subglyphs; /* subglyphs */
|
||||
FT_Vector* extra_points; /* extra points table */
|
||||
|
||||
} FT_GlyphLoad;
|
||||
|
||||
|
||||
struct FT_GlyphLoader_
|
||||
{
|
||||
FT_Memory memory;
|
||||
FT_UInt max_points;
|
||||
FT_UInt max_contours;
|
||||
FT_UInt max_subglyphs;
|
||||
FT_Bool use_extra;
|
||||
|
||||
FT_GlyphLoad base;
|
||||
FT_GlyphLoad current;
|
||||
|
||||
void* other; /* for possible future extension? */
|
||||
|
||||
};
|
||||
|
||||
|
||||
FT_BASE( FT_Error )
|
||||
FT_GlyphLoader_New( FT_Memory memory,
|
||||
FT_GlyphLoader* *aloader );
|
||||
|
||||
FT_BASE( FT_Error )
|
||||
FT_GlyphLoader_Create_Extra( FT_GlyphLoader* loader );
|
||||
|
||||
FT_BASE( void )
|
||||
FT_GlyphLoader_Done( FT_GlyphLoader* loader );
|
||||
|
||||
FT_BASE( void )
|
||||
FT_GlyphLoader_Reset( FT_GlyphLoader* loader );
|
||||
|
||||
FT_BASE( void )
|
||||
FT_GlyphLoader_Rewind( FT_GlyphLoader* loader );
|
||||
|
||||
FT_BASE( FT_Error )
|
||||
FT_GlyphLoader_Check_Points( FT_GlyphLoader* loader,
|
||||
FT_UInt n_points,
|
||||
FT_UInt n_contours );
|
||||
|
||||
FT_BASE( FT_Error )
|
||||
FT_GlyphLoader_Check_Subglyphs( FT_GlyphLoader* loader,
|
||||
FT_UInt n_subs );
|
||||
|
||||
FT_BASE( void )
|
||||
FT_GlyphLoader_Prepare( FT_GlyphLoader* loader );
|
||||
|
||||
FT_BASE( void )
|
||||
FT_GlyphLoader_Add( FT_GlyphLoader* loader );
|
||||
|
||||
FT_BASE( FT_Error )
|
||||
FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
|
||||
FT_GlyphLoader* source );
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
820
src/otlayout/otlcommn.c
Normal file
820
src/otlayout/otlcommn.c
Normal file
@ -0,0 +1,820 @@
|
||||
#include "otlayout.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** COVERAGE TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_coverage_validate( OTL_Bytes table,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_Bytes p;
|
||||
OTL_UInt format;
|
||||
|
||||
if ( table + 4 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
format = OTL_NEXT_UShort(p);
|
||||
switch (format)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
OTL_UInt count = OTL_NEXT_UShort(p);
|
||||
|
||||
if ( p + count*2 >= valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
/* XXX: check glyph indices */
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
OTL_UInt n, num_ranges = OTL_NEXT_UShort(p);
|
||||
OTL_UInt start, end, start_cover, total = 0, last = 0;
|
||||
|
||||
if ( p + num_ranges*6 >= valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
for ( n = 0; n < num_ranges; n++ )
|
||||
{
|
||||
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;
|
||||
|
||||
if ( n > 0 && start <= last )
|
||||
OTL_INVALID_DATA;
|
||||
|
||||
total += (end - start + 1);
|
||||
last = end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
OTL_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
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 result = 0;
|
||||
|
||||
switch ( format )
|
||||
{
|
||||
case 1:
|
||||
return count;
|
||||
|
||||
case 2:
|
||||
{
|
||||
OTL_UInt start, end;
|
||||
|
||||
for ( ; count > 0; count-- )
|
||||
{
|
||||
start = OTL_NEXT_UShort(p);
|
||||
end = OTL_NEXT_UShort(p);
|
||||
p += 2; /* skip start_index */
|
||||
|
||||
result += ( end - start + 1 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_Int )
|
||||
otl_coverage_get_index( OTL_Bytes table,
|
||||
OTL_UInt glyph_index )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
OTL_UInt format = OTL_NEXT_UShort(p);
|
||||
OTL_UInt count = OTL_NEXT_UShort(p);
|
||||
|
||||
switch ( format )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
OTL_UInt min = 0, max = count, mid, gindex;
|
||||
|
||||
table += 4;
|
||||
while ( min < max )
|
||||
{
|
||||
mid = ( min + max ) >> 1;
|
||||
p = table + 2*mid;
|
||||
gindex = OTL_PEEK_UShort(p);
|
||||
|
||||
if ( glyph_index == gindex )
|
||||
return (OTL_Int)mid;
|
||||
|
||||
if ( glyph_index < gindex )
|
||||
max = mid;
|
||||
else
|
||||
min = mid + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
OTL_UInt min = 0, max = count, mid;
|
||||
OTL_UInt start, end, delta, start_cover;
|
||||
|
||||
table += 4;
|
||||
while ( min < max )
|
||||
{
|
||||
mid = ( min + max ) >> 1;
|
||||
p = table + 6*mid;
|
||||
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 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CLASS DEFINITION TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_class_definition_validate( OTL_Bytes table,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
OTL_UInt format;
|
||||
|
||||
if ( p + 4 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
format = OTL_NEXT_UShort(p);
|
||||
switch ( format )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
OTL_UInt count, start = OTL_NEXT_UShort(p);
|
||||
|
||||
if ( p + 2 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
count = OTL_NEXT_UShort(p);
|
||||
|
||||
if ( p + count*2 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
/* XXX: check glyph indices */
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
OTL_UInt n, num_ranges = OTL_NEXT_UShort(p);
|
||||
OTL_UInt start, end, value, last = 0;
|
||||
|
||||
if ( p + num_ranges*6 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
for ( n = 0; n < num_ranges; n++ )
|
||||
{
|
||||
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;
|
||||
|
||||
last = end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
OTL_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_class_definition_get_value( OTL_Bytes table,
|
||||
OTL_UInt glyph_index )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
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 index = (OTL_UInt)( glyph_index - start );
|
||||
|
||||
if ( index < count )
|
||||
{
|
||||
p += 2*index;
|
||||
return OTL_PEEK_UShort(p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
OTL_UInt count = OTL_NEXT_UShort(p);
|
||||
OTL_UInt min = 0, max = count, mid, gindex;
|
||||
|
||||
table += 4;
|
||||
while ( min < max )
|
||||
{
|
||||
mid = ( min + max ) >> 1;
|
||||
p = table + 6*mid;
|
||||
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);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** DEVICE TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_device_table_validate( OTL_Bytes table,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
OTL_UInt start, end, count, format, count;
|
||||
|
||||
if ( p + 8 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
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;
|
||||
|
||||
count = (OTL_UInt)( end - start + 1 );
|
||||
|
||||
if ( p + ((1 << format)*count)/8> valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_device_table_get_start( OTL_Bytes table )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
|
||||
return OTL_PEEK_UShort(p);
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_device_table_get_end( OTL_Bytes table )
|
||||
{
|
||||
OTL_Bytes p = table + 2;
|
||||
|
||||
return OTL_PEEK_UShort(p);
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_Int )
|
||||
otl_device_table_get_delta( OTL_Bytes table,
|
||||
OTL_UInt size )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
OTL_Int result = 0;
|
||||
OTL_UInt start, end, format, index, value;
|
||||
|
||||
start = OTL_NEXT_UShort(p);
|
||||
end = OTL_NEXT_UShort(p);
|
||||
format = OTL_NEXT_UShort(p);
|
||||
|
||||
if ( size >= start && size <= end )
|
||||
{
|
||||
/* we could do that with clever bit operations, but a switch is simply */
|
||||
/* much simpler to understand and maintain !! */
|
||||
/* */
|
||||
switch ( format )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
index = (OTL_UInt)(( size - start )*2);
|
||||
p += (index/16);
|
||||
value = OTL_PEEK_UShort(p);
|
||||
shift = index & 15;
|
||||
result = (OTL_Short)(value << shift) >> (14-shift);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
index = (OTL_UInt)(( size - start )*4);
|
||||
p += (index/16);
|
||||
value = OTL_PEEK_UShort(p);
|
||||
shift = index & 15;
|
||||
result = (OTL_Short)(value << shift) >> (12-shift);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
index = (OTL_UInt)(( size - start )*8);
|
||||
p += (index/16);
|
||||
value = OTL_PEEK_UShort(p);
|
||||
shift = index & 15;
|
||||
result = (OTL_Short)(value << shift) >> (8-shift);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** LOOKUP LISTS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_lookup_validate( OTL_Bytes table,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
OTL_UInt num_tables;
|
||||
|
||||
if ( table + 6 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
p += 4;
|
||||
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);
|
||||
|
||||
if ( table + offset >= valid->limit )
|
||||
OTL_INVALID_OFFSET;
|
||||
}
|
||||
|
||||
/* XXX: check sub-tables ?? */
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_lookup_get_count( OTL_Bytes table )
|
||||
{
|
||||
OTL_Bytes p = table + 4;
|
||||
|
||||
return OTL_PEEK_UShort(p);
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_Bytes )
|
||||
otl_lookup_get_table( OTL_Bytes table,
|
||||
OTL_UInt index )
|
||||
{
|
||||
OTL_Bytes p, result = NULL;
|
||||
OTL_UInt count;
|
||||
|
||||
p = table + 4;
|
||||
count = OTL_NEXT_UShort(p);
|
||||
if ( index < count )
|
||||
{
|
||||
p += index*2;
|
||||
result = table + OTL_PEEK_UShort(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** LOOKUP LISTS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_lookup_list_validate( OTL_Bytes table,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_Bytes p = table, q;
|
||||
OTL_UInt num_lookups, offset;
|
||||
|
||||
if ( p + 2 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
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);
|
||||
|
||||
otl_lookup_validate( table + offset, valid );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_lookup_list_get_count( OTL_Bytes table )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
|
||||
return OTL_PEEK_UShort(p);
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_Bytes )
|
||||
otl_lookup_list_get_lookup( OTL_Bytes table,
|
||||
OTL_UInt index )
|
||||
{
|
||||
OTL_Bytes p, result = 0;
|
||||
OTL_UInt count;
|
||||
|
||||
p = table;
|
||||
count = OTL_NEXT_UShort(p);
|
||||
if ( index < count )
|
||||
{
|
||||
p += index*2;
|
||||
result = table + OTL_PEEK_UShort(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_Bytes )
|
||||
otl_lookup_list_get_table( OTL_Bytes table,
|
||||
OTL_UInt lookup_index,
|
||||
OTL_UInt table_index )
|
||||
{
|
||||
OTL_Bytes result = NULL;
|
||||
|
||||
result = otl_lookup_list_get_lookup( table, lookup_index );
|
||||
if ( result )
|
||||
result = otl_lookup_get_table( result, table_index );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_lookup_list_foreach( OTL_Bytes table,
|
||||
OTL_ForeachFunc func,
|
||||
OTL_Pointer func_data )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
OTL_UInt count = OTL_NEXT_UShort(p);
|
||||
|
||||
for ( ; count > 0; count-- )
|
||||
func( table + OTL_NEXT_USHORT(p), func_data );
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** FEATURES *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_feature_validate( OTL_Bytes table,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
OTL_UInt feat_params, num_lookups;
|
||||
|
||||
if ( p + 4 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
feat_params = OTL_NEXT_UShort(p); /* ignored */
|
||||
num_lookups = OTL_NEXT_UShort(p);
|
||||
|
||||
if ( p + num_lookups*2 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
/* XXX: check lookup indices */
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_feature_get_count( OTL_Bytes table )
|
||||
{
|
||||
OTL_Bytes p = table + 4;
|
||||
|
||||
return OTL_PEEK_UShort(p);
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_feature_get_lookups( OTL_Bytes table,
|
||||
OTL_UInt start,
|
||||
OTL_UInt count,
|
||||
OTL_UInt *lookups )
|
||||
{
|
||||
OTL_Bytes p;
|
||||
OTL_UInt num_features, result = 0;
|
||||
|
||||
p = table + 4;
|
||||
num_features = OTL_NEXT_UShort(p);
|
||||
|
||||
p += start*2;
|
||||
|
||||
for ( ; count > 0 && start < num_features; count--, start++ )
|
||||
{
|
||||
lookups[0] = OTL_NEXT_UShort(p);
|
||||
lookups++;
|
||||
result++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** FEATURE LIST *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_feature_list_validate( OTL_Bytes table,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
OTL_UInt num_features, offset;
|
||||
|
||||
if ( table + 2 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
num_features = OTL_NEXT_UShort(p);
|
||||
|
||||
if ( p + num_features*2 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
for ( ; num_features > 0; num_features-- )
|
||||
{
|
||||
p += 4; /* skip tag */
|
||||
offset = OTL_NEXT_UShort(p);
|
||||
|
||||
otl_feature_table_validate( table + offset, valid );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_feature_list_get_count( OTL_Bytes table )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
|
||||
return OTL_PEEK_UShort(p);
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_Bytes )
|
||||
otl_feature_list_get_feature( OTL_Bytes table,
|
||||
OTL_UInt index )
|
||||
{
|
||||
OTL_Bytes p, result = NULL;
|
||||
OTL_UInt count;
|
||||
|
||||
p = table;
|
||||
count = OTL_NEXT_UShort(p);
|
||||
|
||||
if ( index < count )
|
||||
{
|
||||
p += index*2;
|
||||
result = table + OTL_PEEK_UShort(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_feature_list_foreach( OTL_Bytes table,
|
||||
OTL_ForeachFunc func,
|
||||
OTL_Pointer func_data )
|
||||
{
|
||||
OTL_Bytes p;
|
||||
OTL_UInt count;
|
||||
|
||||
p = table;
|
||||
count = OTL_NEXT_UShort(p);
|
||||
|
||||
for ( ; count > 0; count-- )
|
||||
func( table + OTL_NEXT_UShort(p), func_data );
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_lang_validate( OTL_Bytes table,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_Bytes p = table;
|
||||
OTL_UInt lookup_order;
|
||||
OTL_UInt req_feature;
|
||||
OTL_UInt num_features;
|
||||
|
||||
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);
|
||||
|
||||
/* XXX: check req_feature if not 0xFFFFU */
|
||||
|
||||
if ( p + 2*num_features >= valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
/* XXX: check features indices !! */
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_lang_get_count( OTL_Bytes table )
|
||||
{
|
||||
OTL_Bytes p = table + 4;
|
||||
|
||||
return OTL_PEEK_UShort(p);
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_lang_get_features( OTL_Bytes table,
|
||||
OTL_UInt start,
|
||||
OTL_UInt count,
|
||||
OTL_UInt *features )
|
||||
{
|
||||
OTL_Bytes p = table + 4;
|
||||
OTL_UInt num_features = OTL_NEXT_UShort(p);
|
||||
OTL_UInt result = 0;
|
||||
|
||||
p += start*2;
|
||||
|
||||
for ( ; count > 0 && start < num_features; start++, count-- )
|
||||
{
|
||||
features[0] = OTL_NEXT_UShort(p);
|
||||
features++;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_lang_get_req_feature( OTL_Bytes table )
|
||||
{
|
||||
OTL_Bytes p = table + 2;
|
||||
|
||||
return OTL_PEEK_UShort(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_script_table_validate( OTL_Bytes table,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_UInt default_lang;
|
||||
OTL_Bytes p = table;
|
||||
|
||||
if ( table + 4 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
default_lang = OTL_NEXT_UShort(p);
|
||||
num_langs = OTL_NEXT_UShort(p);
|
||||
|
||||
if ( default_lang != 0 )
|
||||
{
|
||||
if ( table + default_lang >= valid->limit )
|
||||
OTL_INVALID_OFFSET;
|
||||
}
|
||||
|
||||
if ( p + num_langs*6 >= valid->limit )
|
||||
OTL_INVALID_OFFSET;
|
||||
|
||||
for ( ; num_langs > 0; num_langs-- )
|
||||
{
|
||||
OTL_UInt offset;
|
||||
|
||||
p += 4; /* skip tag */
|
||||
offset = OTL_NEXT_UShort(p);
|
||||
|
||||
otl_lang_validate( table + offset, valid );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OTL_LOCALDEF( void )
|
||||
otl_script_list_validate( OTL_Bytes list,
|
||||
OTL_Validator valid )
|
||||
{
|
||||
OTL_UInt num_scripts;
|
||||
OTL_Bytes p = list;
|
||||
|
||||
if ( list + 2 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
num_scripts = OTL_NEXT_UShort(p);
|
||||
|
||||
if ( p + num_scripts*6 > valid->limit )
|
||||
OTL_INVALID_TOO_SHORT;
|
||||
|
||||
for ( ; num_scripts > 0; num_scripts-- )
|
||||
{
|
||||
OTL_UInt offset;
|
||||
|
||||
p += 4; /* skip tag */
|
||||
offset = OTL_NEXT_UShort(p);
|
||||
|
||||
otl_script_table_validate( list + offset, valid );
|
||||
}
|
||||
}
|
||||
|
||||
|
211
src/otlayout/otlcommn.h
Normal file
211
src/otlayout/otlcommn.h
Normal file
@ -0,0 +1,211 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* otlcommn.h
|
||||
*
|
||||
* OpenType Layout common tables processing
|
||||
*
|
||||
* this header provides several routines used to process common table
|
||||
* found in various OpenType Layout tables..
|
||||
*/
|
||||
#ifndef __OTLAYOUT_COMMON_H__
|
||||
#define __OTLAYOUT_COMMON_H__
|
||||
|
||||
#include "otlayout.h"
|
||||
|
||||
OTL_BEGIN_HEADER
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** COVERAGE TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* validate coverage table */
|
||||
OTL_LOCALDEF( void )
|
||||
otl_coverage_validate( OTL_Bytes base,
|
||||
OTL_Validator valid );
|
||||
|
||||
/* return number of covered glyphs */
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_coverage_get_count( OTL_Bytes base );
|
||||
|
||||
|
||||
/* return the coverage index corresponding to a glyph glyph index. */
|
||||
/* returns -1 if the glyph isn't covered.. */
|
||||
OTL_LOCALDEF( OTL_Int )
|
||||
otl_coverage_get_index( OTL_Bytes base,
|
||||
OTL_UInt glyph_index );
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CLASS DEFINITION TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* validate class definition table */
|
||||
OTL_LOCALDEF( void )
|
||||
otl_class_definition_validate( OTL_Bytes table,
|
||||
OTL_Validator valid );
|
||||
|
||||
/* return class value for a given glyph index */
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_class_definition_get_value( OTL_Bytes table,
|
||||
OTL_UInt glyph_index );
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** DEVICE TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* validate a device table */
|
||||
OTL_LOCALDEF( void )
|
||||
otl_device_table_validate( OTL_Bytes table,
|
||||
OTL_Validator valid );
|
||||
|
||||
|
||||
/* return a device table's first size */
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_device_table_get_start( OTL_Bytes table );
|
||||
|
||||
|
||||
/* return a device table's last size */
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_device_table_get_end( OTL_Bytes table );
|
||||
|
||||
|
||||
/* return pixel adjustment for a given size */
|
||||
OTL_LOCALDEF( OTL_Int )
|
||||
otl_device_table_get_delta( OTL_Bytes table,
|
||||
OTL_UInt size );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** LOOKUPS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* validate lookup table */
|
||||
OTL_LOCALDEF( void )
|
||||
otl_lookup_validate( OTL_Bytes table,
|
||||
OTL_Validator valid );
|
||||
|
||||
/* return number of sub-tables in a lookup */
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_lookup_get_count( OTL_Bytes table );
|
||||
|
||||
|
||||
/* return lookup sub-table */
|
||||
OTL_LOCALDEF( OTL_Bytes )
|
||||
otl_lookup_get_table( OTL_Bytes table,
|
||||
OTL_UInt index );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** LOOKUP LISTS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* validate lookup list */
|
||||
OTL_LOCALDEF( void )
|
||||
otl_lookup_list_validate( OTL_Bytes table,
|
||||
OTL_Validator valid );
|
||||
|
||||
/* return number of lookups in list */
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_lookup_list_get_count( OTL_Bytes table );
|
||||
|
||||
|
||||
/* return a given lookup from a list */
|
||||
OTL_LOCALDEF( OTL_Bytes )
|
||||
otl_lookup_list_get_lookup( OTL_Bytes table,
|
||||
OTL_UInt index );
|
||||
|
||||
|
||||
/* return lookup sub-table from a list */
|
||||
OTL_LOCALDEF( OTL_Bytes )
|
||||
otl_lookup_list_get_table( OTL_Bytes table,
|
||||
OTL_UInt lookup_index,
|
||||
OTL_UInt table_index );
|
||||
|
||||
/* iterate over lookup list */
|
||||
OTL_LOCALDEF( void )
|
||||
otl_lookup_list_foreach( OTL_Bytes table,
|
||||
OTL_ForeachFunc func,
|
||||
OTL_Pointer func_data );
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** FEATURES *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* validate feature table */
|
||||
OTL_LOCALDEF( void )
|
||||
otl_feature_validate( OTL_Bytes table,
|
||||
OTL_Validator valid );
|
||||
|
||||
/* return feature's lookup count */
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_feature_get_count( OTL_Bytes table );
|
||||
|
||||
/* get several lookups from a feature. returns the number of lookups grabbed */
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_feature_get_lookups( OTL_Bytes table,
|
||||
OTL_UInt start,
|
||||
OTL_UInt count,
|
||||
OTL_UInt *lookups );
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** FEATURE LIST *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* validate a feature list */
|
||||
OTL_LOCALDEF( void )
|
||||
otl_feature_list_validate( OTL_Bytes table,
|
||||
OTL_Validator valid );
|
||||
|
||||
/* return number of features in list */
|
||||
OTL_LOCALDEF( OTL_UInt )
|
||||
otl_feature_list_get_count( OTL_Bytes table );
|
||||
|
||||
|
||||
/* return a given feature from a list */
|
||||
OTL_LOCALDEF( OTL_Bytes )
|
||||
otl_feature_list_get_feature( OTL_Bytes table,
|
||||
OTL_UInt index );
|
||||
|
||||
/* iterate over all features in a list */
|
||||
OTL_LOCALDEF( void )
|
||||
otl_feature_list_foreach( OTL_Bytes table,
|
||||
OTL_ForeachFunc func,
|
||||
OTL_Pointer func_data );
|
||||
|
||||
/* */
|
||||
|
||||
OTL_END_HEADER
|
||||
|
||||
#endif /* __OTLAYOUT_COMMON_H__ */
|
@ -300,6 +300,7 @@
|
||||
/* fonts within PDF documents, so don't check for them. */
|
||||
(void)LOAD_( max_profile );
|
||||
(void)LOAD_( charmaps );
|
||||
|
||||
|
||||
/* the following tables are optional in PCL fonts -- */
|
||||
/* don't check for errors */
|
||||
|
@ -34,8 +34,8 @@
|
||||
|
||||
|
||||
|
||||
#define TT_PEEK_Short FT_PEEK_SHORT
|
||||
#define TT_PEEK_UShort FT_PEEK16_UBE
|
||||
#define TT_PEEK_SHORT FT_PEEK_SHORT
|
||||
#define TT_PEEK_USHORT FT_PEEK16_UBE
|
||||
#define TT_PEEK_Long FT_PEEK32_BE
|
||||
#define TT_PEEK_ULong FT_PEEK32_UBE
|
||||
|
||||
@ -72,7 +72,7 @@
|
||||
tt_cmap0_validate( FT_Byte* table,
|
||||
FT_Validator valid )
|
||||
{
|
||||
FT_Byte* p = table + 2; /* skip format */
|
||||
FT_Byte* p = table + 2;
|
||||
FT_UInt length = TT_NEXT_USHORT(p);
|
||||
|
||||
if ( table + length > valid->limit || length < 262 )
|
||||
@ -83,6 +83,7 @@
|
||||
{
|
||||
FT_UInt n, index;
|
||||
|
||||
p = table + 6;
|
||||
for ( n = 0; n < 256; n++ )
|
||||
{
|
||||
index = *p++;
|
||||
@ -183,7 +184,7 @@
|
||||
* keys 6 USHORT[256] sub-header keys
|
||||
* subs 518 SUBHEAD[NSUBS] sub-headers array
|
||||
* glyph_ids 518+NSUB*8 USHORT[] glyph id array
|
||||
*
|
||||
*
|
||||
* the 'keys' table is used to map charcode high-bytes to sub-headers.
|
||||
* the value of 'NSUBS' is the number of sub-headers defined in the
|
||||
* table and is computed by finding the maximum of the 'keys' table.
|
||||
@ -228,7 +229,7 @@
|
||||
FT_Validator valid )
|
||||
{
|
||||
FT_Byte* p = table + 2; /* skip format */
|
||||
FT_UInt length = PEEK_UShort(p);
|
||||
FT_UInt length = TT_PEEK_USHORT(p);
|
||||
FT_UInt n, max_subs;
|
||||
FT_Byte* keys; /* keys table */
|
||||
FT_Byte* subs; /* sub-headers */
|
||||
@ -256,6 +257,8 @@
|
||||
max_subs = index;
|
||||
}
|
||||
|
||||
FT_ASSERT( p == table + 518 );
|
||||
|
||||
subs = p;
|
||||
glyph_ids = subs + (max_subs + 1)*8;
|
||||
if ( glyph_ids > valid->limit )
|
||||
@ -322,8 +325,8 @@
|
||||
{
|
||||
FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
|
||||
FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
|
||||
FT_Byte* p = table + 6; /* keys table */
|
||||
FT_Byte* subs = p + 512; /* subheaders table */
|
||||
FT_Byte* p = table + 6; /* keys table */
|
||||
FT_Byte* subs = table + 518; /* subheaders table */
|
||||
FT_Byte* sub;
|
||||
|
||||
|
||||
@ -339,14 +342,14 @@
|
||||
/* Otherwise, return 0 */
|
||||
/* */
|
||||
p += char_lo*2;
|
||||
if ( PEEK_UShort(p) != 0 )
|
||||
if ( TT_PEEK_USHORT(p) != 0 )
|
||||
goto Exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* a 16-bit character code */
|
||||
p += char_hi*2; /* jump to key entry */
|
||||
sub = subs + PEEK_UShort(p); /* jump to sub-header */
|
||||
p += char_hi*2; /* jump to key entry */
|
||||
sub = subs + ( TT_PEEK_USHORT(p) & -8 ); /* jump to sub-header */
|
||||
|
||||
/* check that the hi byte isn't a valid one-byte value */
|
||||
if ( sub == subs )
|
||||
@ -378,75 +381,22 @@
|
||||
start = TT_NEXT_USHORT(p);
|
||||
count = TT_NEXT_USHORT(p);
|
||||
delta = TT_NEXT_SHORT(p);
|
||||
offset = PEEK_UShort(p);
|
||||
offset = TT_PEEK_USHORT(p);
|
||||
|
||||
index -= start;
|
||||
if ( index < count && offset != 0 )
|
||||
{
|
||||
p += offset + 2*index;
|
||||
index = PEEK_UShort(p);
|
||||
index = TT_PEEK_USHORT(p);
|
||||
|
||||
if ( index == 0 )
|
||||
goto Exit;
|
||||
|
||||
result = (FT_UInt)( index + delta ) & 0xFFFFU;
|
||||
if ( index != 0 )
|
||||
result = (FT_UInt)( index + delta ) & 0xFFFFU;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* return first valid charcode in a format 2 sub-header */
|
||||
static FT_ULong
|
||||
tt_cmap2_subheader_first( FT_Byte* subheader,
|
||||
FT_UInt char_hi,
|
||||
FT_UInt *agindex )
|
||||
{
|
||||
FT_ULong result = 0;
|
||||
FT_UInt n, gindex = 0;
|
||||
FT_Byte* p = subheader;
|
||||
|
||||
FT_UInt start = TT_NEXT_USHORT(p);
|
||||
FT_UInt count = TT_NEXT_USHORT(p);
|
||||
|
||||
if ( count > 0 )
|
||||
{
|
||||
FT_Int delta = TT_NEXT_SHORT(p);
|
||||
FT_UInt offset = TT_NEXT_USHORT(p);
|
||||
|
||||
if ( offset == 0 )
|
||||
{
|
||||
/* simple difference, compute directly */
|
||||
result = char_hi*256 + start;
|
||||
gindex = (FT_UInt)( start + delta ) & 0xFFFFU;
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_UInt i, index;
|
||||
|
||||
/* parse glyph id table for non-0 indices */
|
||||
p += offset - 2;
|
||||
for (; i < count; i++ )
|
||||
{
|
||||
index = TT_NEXT_USHORT(p);
|
||||
if ( index != 0 )
|
||||
{
|
||||
result = char_hi*256 + start + i;
|
||||
gindex = (FT_UInt)(index + delta) & 0xFFFFU;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( agindex )
|
||||
*agindex = gindex;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static FT_UInt
|
||||
tt_cmap2_char_next( FT_Byte* table,
|
||||
@ -459,7 +409,7 @@
|
||||
FT_Byte* p;
|
||||
|
||||
++char_code;
|
||||
for (;;)
|
||||
while ( char_code < 0x10000U )
|
||||
{
|
||||
subheader = tt_cmap2_get_subheader( table, char_code );
|
||||
if ( subheader )
|
||||
@ -468,7 +418,7 @@
|
||||
FT_UInt start = TT_NEXT_USHORT(p);
|
||||
FT_UInt count = TT_NEXT_USHORT(p);
|
||||
FT_Int delta = TT_NEXT_SHORT(p);
|
||||
FT_UInt offset = PEEK_UShort(p);
|
||||
FT_UInt offset = TT_PEEK_USHORT(p);
|
||||
FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
|
||||
FT_UInt pos, index;
|
||||
|
||||
@ -505,8 +455,6 @@
|
||||
/* jump to next sub-header, i.e. higher byte value */
|
||||
Next_SubHeader:
|
||||
char_code = (char_code & -256) + 256;
|
||||
if ( char_code >= 0x10000U )
|
||||
break;
|
||||
}
|
||||
|
||||
Exit:
|
||||
@ -534,6 +482,58 @@
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* TABLE OVERVIEW:
|
||||
* ---------------
|
||||
*
|
||||
* NAME OFFSET TYPE DESCRIPTION
|
||||
*
|
||||
* format 0 USHORT must be 4
|
||||
* length 2 USHORT table length in bytes
|
||||
* language 4 USHORT Mac language code
|
||||
*
|
||||
* segCountX2 6 USHORT 2*NUM_SEGS
|
||||
* searchRange 8 USHORT 2*(1 << LOG_SEGS)
|
||||
* entrySelector 10 USHORT LOG_SEGS
|
||||
* rangeShift 12 USHORT segCountX2 - searchRange
|
||||
*
|
||||
* endCount 14 USHORT[NUM_SEGS] end charcode for each
|
||||
* segment. last is 0xFFFF
|
||||
*
|
||||
* pad 14+NUM_SEGS*2 USHORT padding
|
||||
*
|
||||
* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for each
|
||||
* segment
|
||||
*
|
||||
* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each segment
|
||||
*
|
||||
* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for each
|
||||
* segment. can be 0
|
||||
*
|
||||
* glyphIds 16+NUM_SEGS*8 USHORT[] array og glyph id ranges
|
||||
*
|
||||
*
|
||||
* Charcodes are modelled by a series of ordered (increasing) intervals
|
||||
* called segments. Each segment has start and end codes, provided by
|
||||
* the 'startCount' and 'endCount' arrays. Segments must not be over-lapping
|
||||
* and the last segment should always contain the '0xFFFF' endCount.
|
||||
*
|
||||
* The fields 'searchRange', 'entrySelector' and 'rangeShift' are better
|
||||
* ignored (they're traces of over-engineering in the TT specification)
|
||||
*
|
||||
* Each segment also has a signed 'delta', as well as an optional offset
|
||||
* within the 'glyphIds' table.
|
||||
*
|
||||
* if a segment's idOffset is 0, then the glyph index corresponding to
|
||||
* any charcode within the segment is obtained by adding the value of
|
||||
* 'idDelta' directly to the charcode, modulo 65536
|
||||
*
|
||||
* otherwise, a glyph index is taken from the glyph ids sub-array for the
|
||||
* segment, and the value of 'idDelta' is added to it..
|
||||
*/
|
||||
|
||||
|
||||
#ifdef TT_CONFIG_CMAP_FORMAT_4
|
||||
|
||||
static void
|
||||
@ -542,14 +542,13 @@
|
||||
{
|
||||
FT_Byte* p = table + 2; /* skip format */
|
||||
FT_UInt length = TT_NEXT_USHORT(p);
|
||||
FT_Byte *ends, *starts, *offsets, *glyph_ids;
|
||||
FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
|
||||
FT_UInt n, num_segs;
|
||||
|
||||
if ( table + length > valid->limit || length < 16 )
|
||||
TOO_SHORT;
|
||||
|
||||
p += 2; /* skip language */
|
||||
|
||||
p = table + 6;
|
||||
num_segs = TT_NEXT_USHORT(p); /* read segCountX2 */
|
||||
|
||||
if ( valid->level >= FT_VALIDATE_PARANOID )
|
||||
@ -584,12 +583,11 @@
|
||||
search_range != (1 << entry_selector) )
|
||||
INVALID_DATA;
|
||||
}
|
||||
else
|
||||
p += 6;
|
||||
|
||||
ends = p;
|
||||
starts = ends + num_segs*2 + 2;
|
||||
offsets = starts + num_segs*4;
|
||||
ends = table + 14;
|
||||
starts = table + 16 + num_segs*2;
|
||||
deltas = starts + num_segs*2;
|
||||
offsets = deltas + num_segs*2;
|
||||
glyph_ids = offsets + num_segs*2;
|
||||
|
||||
if ( glyph_ids >= table + length )
|
||||
@ -599,7 +597,7 @@
|
||||
if ( valid->level >= FT_VALIDATE_PARANOID )
|
||||
{
|
||||
p = ends + (num_segs-1)*2;
|
||||
if ( PEEK_UShort(p) != 0xFFFFU )
|
||||
if ( TT_PEEK_USHORT(p) != 0xFFFFU )
|
||||
INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -607,12 +605,14 @@
|
||||
/* check also the offsets.. */
|
||||
{
|
||||
FT_UInt start, end, last = 0,offset, n;
|
||||
FT_Int delta;
|
||||
|
||||
for ( n = 0; n < num_segs; n++ )
|
||||
{
|
||||
p = starts + n*2; start = PEEK_UShort(p);
|
||||
p = ends + n*2; end = PEEK_UShort(p);
|
||||
p = offsets + n*2; offset = PEEK_UShort(p);
|
||||
p = starts + n*2; start = TT_PEEK_USHORT(p);
|
||||
p = ends + n*2; end = TT_PEEK_USHORT(p);
|
||||
p = deltas + n*2; delta = TT_PEEK_SHORT(p);
|
||||
p = offsets + n*2; offset = TT_PEEK_USHORT(p);
|
||||
|
||||
if ( end > start )
|
||||
INVALID_DATA;
|
||||
@ -625,10 +625,26 @@
|
||||
p += offset; /* start of glyph id array */
|
||||
|
||||
/* check that we point within the glyph ids table only */
|
||||
if ( p < glyph_ids || p + (end - start + 1) > table + length )
|
||||
if ( p < glyph_ids || p + (end - start + 1)*2 > table + length )
|
||||
INVALID_DATA;
|
||||
|
||||
/* XXXX: check glyph ids !! */
|
||||
/* check glyph indices within the segment range */
|
||||
if ( valid->level >= FT_VALIDATE_TIGHT )
|
||||
{
|
||||
FT_UInt index;
|
||||
|
||||
for ( ; start < end; )
|
||||
{
|
||||
index = NEXT_USHORT(p);
|
||||
if ( index != 0 )
|
||||
{
|
||||
index = (FT_UInt)(index + delta) & 0xFFFFU;
|
||||
|
||||
if ( index >= valid->num_glyphs )
|
||||
INVALID_GLYPH_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
last = end;
|
||||
}
|
||||
@ -651,7 +667,7 @@
|
||||
FT_UInt code = (FT_UInt)char_code;
|
||||
|
||||
p = table + 6;
|
||||
num_segs2 = PEEK_UShort(p);
|
||||
num_segs2 = TT_PEEK_USHORT(p) & -2; /* be paranoid !! */
|
||||
|
||||
p = table + 14; /* ends table */
|
||||
q = table + 16 + num_segs2; /* starts table */
|
||||
@ -668,13 +684,13 @@
|
||||
{
|
||||
index = (FT_UInt)( char_code - start );
|
||||
|
||||
p = q + num_segs2 - 2; delta = PEEK_Short(p);
|
||||
p += num_segs2; offset = PEEK_UShort(p);
|
||||
p = q + num_segs2 - 2; delta = TT_PEEK_SHORT(p);
|
||||
p += num_segs2; offset = TT_PEEK_USHORT(p);
|
||||
|
||||
if ( offset != 0 )
|
||||
{
|
||||
p += offset + 2*index;
|
||||
index = PEEK_UShort(p);
|
||||
index = TT_PEEK_USHORT(p);
|
||||
}
|
||||
|
||||
if ( index != 0 )
|
||||
@ -703,7 +719,7 @@
|
||||
|
||||
code = (FT_UInt)char_code;
|
||||
p = table + 6;
|
||||
num_segs2 = PEEK_UShort(p) & -2; /* ensure even-ness */
|
||||
num_segs2 = TT_PEEK_USHORT(p) & -2; /* ensure even-ness */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -723,8 +739,8 @@
|
||||
|
||||
if ( code <= end )
|
||||
{
|
||||
p = q + num_segs2 - 2; delta = PEEK_Short(p);
|
||||
p += num_segs2; offset = PEEK_UShort(p);
|
||||
p = q + num_segs2 - 2; delta = TT_PEEK_SHORT(p);
|
||||
p += num_segs2; offset = TT_PEEK_USHORT(p);
|
||||
|
||||
if ( offset != 0 )
|
||||
{
|
||||
@ -785,20 +801,41 @@
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* TABLE OVERVIEW:
|
||||
* ---------------
|
||||
*
|
||||
* NAME OFFSET TYPE DESCRIPTION
|
||||
*
|
||||
* format 0 USHORT must be 4
|
||||
* length 2 USHORT table length in bytes
|
||||
* language 4 USHORT Mac language code
|
||||
*
|
||||
* first 6 USHORT first segment code
|
||||
* count 8 USHORT segment size in chars
|
||||
* glyphIds 10 USHORT[count] glyph ids
|
||||
*
|
||||
*
|
||||
* A very simplified segment mapping
|
||||
*/
|
||||
|
||||
#ifdef TT_CONFIG_CMAP_FORMAT_6
|
||||
|
||||
static void
|
||||
tt_cmap6_validate( FT_Byte* table,
|
||||
FT_Validator valid )
|
||||
{
|
||||
FT_Byte* p = table + 2;
|
||||
FT_Byte* p;
|
||||
FT_UInt length, start, count;
|
||||
|
||||
if ( table + 10 > valid->limit )
|
||||
INVALID_TOO_SHORT;
|
||||
|
||||
p = table + 2;
|
||||
length = TT_NEXT_USHORT(p);
|
||||
p += 2; /* skip language */
|
||||
|
||||
p = table + 6; /* skip language */
|
||||
start = TT_NEXT_USHORT(p);
|
||||
count = TT_NEXT_USHORT(p);
|
||||
|
||||
@ -833,7 +870,7 @@
|
||||
if ( index < count )
|
||||
{
|
||||
p += 2*index;
|
||||
result = PEEK_UShort(p);
|
||||
result = TT_PEEK_USHORT(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -924,6 +961,28 @@
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* TABLE OVERVIEW:
|
||||
* ---------------
|
||||
*
|
||||
* NAME OFFSET TYPE DESCRIPTION
|
||||
*
|
||||
* format 0 USHORT must be 8
|
||||
* reseved 2 USHORT reserved
|
||||
* length 4 ULONG length in bytes
|
||||
* language 8 ULONG Mac language code
|
||||
* is32 12 BYTE[8192] 32-bitness bitmap
|
||||
* count 8204 ULONG number of groups
|
||||
*
|
||||
* this header is followed by 'count' groups of the following format:
|
||||
*
|
||||
* start 0 ULONG first charcode
|
||||
* end 4 ULONG last charcode
|
||||
* startId 8 ULONG start glyph id for
|
||||
* the group
|
||||
*/
|
||||
|
||||
#ifdef TT_CONFIG_CMAP_FORMAT_8
|
||||
|
||||
static void
|
||||
@ -939,11 +998,11 @@
|
||||
INVALID_TOO_SHORT;
|
||||
|
||||
length = TT_NEXT_ULONG(p);
|
||||
if ( table + length > valid->limit || length < 16 + 8192 )
|
||||
if ( table + length > valid->limit || length < 8208 )
|
||||
INVALID_TOO_SHORT;
|
||||
|
||||
is32 = p + 4; /* skip language */
|
||||
p = is32 + 8192; /* skip 'is32' array */
|
||||
is32 = table + 12;
|
||||
p = is32 + 8192; /* skip 'is32' array */
|
||||
num_groups = TT_NEXT_ULONG(p);
|
||||
|
||||
if ( p + num_groups*12 > valid->limit )
|
||||
@ -983,10 +1042,10 @@
|
||||
{
|
||||
hi = (FT_UInt)(start >> 16);
|
||||
lo = (FT_UInt)(start & 0xFFFFU);
|
||||
|
||||
|
||||
if ( is32[ hi >> 3 ] & (0x80 >> (hi & 7)) == 0 )
|
||||
INVALID_DATA;
|
||||
|
||||
|
||||
if ( is32[ lo >> 3 ] & (0x80 >> (lo & 7)) == 0 )
|
||||
INVALID_DATA;
|
||||
}
|
||||
@ -995,20 +1054,22 @@
|
||||
{
|
||||
/* start_hi == 0, check that is32[i] is 0 for each i in */
|
||||
/* the range [start..end] */
|
||||
|
||||
|
||||
/* end_hi cannot be != 0 !! */
|
||||
if ( end & ~0xFFFFU )
|
||||
INVALID_DATA;
|
||||
|
||||
|
||||
for ( ; count > 0; count--, start++ )
|
||||
{
|
||||
lo = (FT_UInt)(start & 0xFFFFU);
|
||||
|
||||
|
||||
if ( is32[ lo >> 3 ] & (0x80 >> (lo & 7)) != 0 )
|
||||
INVALID_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1019,19 +1080,19 @@
|
||||
FT_ULong char_code )
|
||||
{
|
||||
FT_UInt result = 0;
|
||||
FT_Byte* p = table + 12 + 8192;
|
||||
FT_Byte* p = table + 8204;
|
||||
FT_ULong num_groups = TT_NEXT_ULONG(p);
|
||||
FT_ULong n, start, end, start_id;
|
||||
|
||||
|
||||
for ( ; num_groups > 0; num_groups-- )
|
||||
{
|
||||
start = TT_NEXT_ULONG(p);
|
||||
end = TT_NEXT_ULONG(p);
|
||||
start_id = TT_NEXT_ULONG(p);
|
||||
|
||||
|
||||
if ( char_code < start )
|
||||
break;
|
||||
|
||||
|
||||
if ( char_code <= end )
|
||||
{
|
||||
result = start_id + char_code - start;
|
||||
@ -1049,22 +1110,22 @@
|
||||
{
|
||||
FT_ULong result = 0;
|
||||
FT_UInt gindex = 0;
|
||||
FT_Byte* p = table + 12 + 8192;
|
||||
FT_ULong num_groups = TT_NEXT_USHORT(p);
|
||||
FT_Byte* p = table + 8204;
|
||||
FT_ULong num_groups = TT_NEXT_ULONG(p);
|
||||
FT_ULong n, start, end, start_id;
|
||||
|
||||
|
||||
++char_code;
|
||||
p = table + 16 + 8192;
|
||||
|
||||
p = table + 8208;
|
||||
|
||||
for ( n = 0; n < num_groups++; n++ )
|
||||
{
|
||||
start = TT_NEXT_ULONG(p);
|
||||
end = TT_NEXT_ULONG(p);
|
||||
start_id = TT_NEXT_ULONG(p);
|
||||
|
||||
|
||||
if ( char_code < start )
|
||||
char_code = start;
|
||||
|
||||
|
||||
if ( char_code <= end )
|
||||
{
|
||||
gindex = (FT_UInt)(char_code - start + start_id);
|
||||
@ -1075,13 +1136,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Exit:
|
||||
if ( agindex )
|
||||
*agindex = gindex;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const TT_Cmap_ClassRec tt_cmap8_class_rec =
|
||||
@ -1101,20 +1162,37 @@
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* TABLE OVERVIEW:
|
||||
* ---------------
|
||||
*
|
||||
* NAME OFFSET TYPE DESCRIPTION
|
||||
*
|
||||
* format 0 USHORT must be 10
|
||||
* reseved 2 USHORT reserved
|
||||
* length 4 ULONG length in bytes
|
||||
* language 8 ULONG Mac language code
|
||||
*
|
||||
* start 12 ULONG first char in range
|
||||
* count 16 ULONG number of chars in range
|
||||
* glyphIds 20 USHORT[count] glyph indices covered
|
||||
*/
|
||||
|
||||
#ifdef TT_CONFIG_CMAP_FORMAT_10
|
||||
|
||||
static void
|
||||
tt_cmap10_validate( FT_Byte* table,
|
||||
FT_Validator valid )
|
||||
{
|
||||
FT_Byte* p = table + 2;
|
||||
FT_Byte* p = table + 4;
|
||||
FT_ULong length, start, count;
|
||||
|
||||
if ( table + 20 > valid->limit )
|
||||
INVALID_TOO_SHORT;
|
||||
|
||||
length = TT_NEXT_USHORT(p);
|
||||
p += 4; /* skip language */
|
||||
length = TT_NEXT_ULONG(p);
|
||||
p = table + 12;
|
||||
start = TT_NEXT_ULONG(p);
|
||||
count = TT_NEXT_ULONG(p);
|
||||
|
||||
@ -1148,8 +1226,8 @@
|
||||
|
||||
if ( index < count )
|
||||
{
|
||||
p += 2*index;
|
||||
result = PEEK_UShort(p);
|
||||
p += 2*index;
|
||||
result = TT_PEEK_USHORT(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -1168,9 +1246,6 @@
|
||||
FT_ULong index;
|
||||
|
||||
char_code++;
|
||||
if ( char_code >= 0x10000U )
|
||||
goto Exit;
|
||||
|
||||
if ( char_code < start )
|
||||
char_code = start;
|
||||
|
||||
@ -1213,20 +1288,108 @@
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* TABLE OVERVIEW:
|
||||
* ---------------
|
||||
*
|
||||
* NAME OFFSET TYPE DESCRIPTION
|
||||
*
|
||||
* format 0 USHORT must be 12
|
||||
* reseved 2 USHORT reserved
|
||||
* length 4 ULONG length in bytes
|
||||
* language 8 ULONG Mac language code
|
||||
* count 12 ULONG number of groups
|
||||
* 16
|
||||
*
|
||||
* this header is followed by 'count' groups of the following format:
|
||||
*
|
||||
* start 0 ULONG first charcode
|
||||
* end 4 ULONG last charcode
|
||||
* startId 8 ULONG start glyph id for
|
||||
* the group
|
||||
*/
|
||||
|
||||
#ifdef TT_CONFIG_CMAP_FORMAT_12
|
||||
|
||||
static void
|
||||
tt_cmap12_validate( FT_Byte* table,
|
||||
FT_Validator valid )
|
||||
{
|
||||
}
|
||||
FT_Byte* p;
|
||||
FT_ULong length;
|
||||
FT_ULong num_groups;
|
||||
|
||||
if ( table + 16 > valid->limit )
|
||||
INVALID_TOO_SHORT;
|
||||
|
||||
p = table + 4;
|
||||
length = TT_NEXT_ULONG(p);
|
||||
|
||||
p = table + 12;
|
||||
num_groups = TT_NEXT_ULONG(p);
|
||||
|
||||
if ( table + length > valid->limit || length < 16 + 12*num_groups )
|
||||
INVALID_TOO_SHORT;
|
||||
|
||||
/* check groups, they must be in increasing order */
|
||||
{
|
||||
FT_ULong n, start, end, start_id, count, last = 0;
|
||||
|
||||
for ( n = 0; n < num_groups; n++ )
|
||||
{
|
||||
FT_Bytes* q;
|
||||
FT_UInt hi, lo;
|
||||
|
||||
start = TT_NEXT_ULONG(p);
|
||||
end = TT_NEXT_ULONG(p);
|
||||
start_id = TT_NEXT_ULONG(p);
|
||||
|
||||
if ( start > end )
|
||||
INVALID_DATA;
|
||||
|
||||
if ( n > 0 && start <= last )
|
||||
INVALID_DATA;
|
||||
|
||||
if ( valid->level >= FT_VALIDATE_TIGHT )
|
||||
{
|
||||
if ( start_id + end - start >= valid->num_glyphs )
|
||||
INVALID_GLYPH_ID;
|
||||
}
|
||||
|
||||
last = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static FT_UInt
|
||||
tt_cmap12_char_index( FT_Byte* table,
|
||||
FT_ULong char_code )
|
||||
{
|
||||
}
|
||||
FT_UInt result = 0;
|
||||
FT_Byte* p = table + 12;
|
||||
FT_ULong num_groups = TT_NEXT_ULONG(p);
|
||||
FT_ULong n, start, end, start_id;
|
||||
|
||||
for ( ; num_groups > 0; num_groups-- )
|
||||
{
|
||||
start = TT_NEXT_ULONG(p);
|
||||
end = TT_NEXT_ULONG(p);
|
||||
start_id = TT_NEXT_ULONG(p);
|
||||
|
||||
if ( char_code < start )
|
||||
break;
|
||||
|
||||
if ( char_code <= end )
|
||||
{
|
||||
result = start_id + char_code - start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static FT_ULong
|
||||
@ -1234,7 +1397,41 @@
|
||||
FT_ULong char_code,
|
||||
FT_UInt *agindex )
|
||||
{
|
||||
}
|
||||
FT_ULong result = 0;
|
||||
FT_UInt gindex = 0;
|
||||
FT_Byte* p = table + 12;
|
||||
FT_ULong num_groups = TT_NEXT_ULONG(p);
|
||||
FT_ULong n, start, end, start_id;
|
||||
|
||||
++char_code;
|
||||
p = table + 8208;
|
||||
|
||||
for ( n = 0; n < num_groups++; n++ )
|
||||
{
|
||||
start = TT_NEXT_ULONG(p);
|
||||
end = TT_NEXT_ULONG(p);
|
||||
start_id = TT_NEXT_ULONG(p);
|
||||
|
||||
if ( char_code < start )
|
||||
char_code = start;
|
||||
|
||||
if ( char_code <= end )
|
||||
{
|
||||
gindex = (FT_UInt)(char_code - start + start_id);
|
||||
if ( gindex != 0 )
|
||||
{
|
||||
result = char_code;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
if ( agindex )
|
||||
*agindex = gindex;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static const TT_Cmap_ClassRec tt_cmap12_class_rec =
|
||||
@ -1246,3 +1443,4 @@
|
||||
|
||||
#endif /* TT_CONFIG_CMAP_FORMAT_12 */
|
||||
|
||||
/* END */
|
||||
|
414
src/type1/t1cmap.c
Normal file
414
src/type1/t1cmap.c
Normal file
@ -0,0 +1,414 @@
|
||||
#include "t1cmap.h"
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***** *****/
|
||||
/***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/
|
||||
/***** *****/
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
static( void )
|
||||
t1_cmap_std_init( T1_CMapStd cmap,
|
||||
FT_Int is_expert )
|
||||
{
|
||||
T1_Face face = (T1_Face) FT_CMAP_FACE(cmap);
|
||||
PSNames_Interface* psnames = face->psnames;
|
||||
|
||||
cmap->num_glyphs = face->type1.num_glyphs;
|
||||
cmap->glyph_names = face->type1.glyph_names;
|
||||
cmap->sid_strings = sid_strings;
|
||||
cmap->code_to_sid = is_expert ? psnames->adobe_expert_encoding
|
||||
: psnames->adobe_std_encoding;
|
||||
|
||||
FT_ASSERT( cmap->code_to_sid != NULL );
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
t1_cmap_std_done( T1_CMapStd cmap )
|
||||
{
|
||||
cmap->num_glyphs = 0;
|
||||
cmap->glyph_names = NULL;
|
||||
cmap->sid_strings = NULL;
|
||||
cmap->code_to_sid = NULL;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_UInt )
|
||||
t1_cmap_std_char_index( T1_CMapStd cmap,
|
||||
FT_UInt32 char_code )
|
||||
{
|
||||
FT_UInt result = 0;
|
||||
|
||||
if ( char_code < 256 )
|
||||
{
|
||||
FT_UInt code;
|
||||
const char* glyph_name;
|
||||
FT_Int n;
|
||||
|
||||
/* conver character code to Adobe SID string */
|
||||
code = cmap->code_to_sid[ char_code ];
|
||||
glyph_name = cmap->adobe_sid_strings[ code ];
|
||||
|
||||
/* look for the corresponding glyph name */
|
||||
for ( n = 0; n < cmap->num_glyphs; n++ )
|
||||
{
|
||||
const char* gname = cmap->glyph_names[n];
|
||||
|
||||
if ( gname && gname[0] == glyph_name[0] &&
|
||||
strcmp( gname, glyph_name ) == 0 )
|
||||
{
|
||||
result = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_UInt )
|
||||
t1_cmap_std_char_next( T1_CMapStd cmap,
|
||||
FT_UInt32 *pchar_code )
|
||||
{
|
||||
FT_UInt result = 0;
|
||||
FT_UInt32 char_code = *pchar_code;
|
||||
|
||||
++char_code;
|
||||
while ( char_code < 256 )
|
||||
{
|
||||
result = t1_cmap_standard_char_index( cmap, char_code );
|
||||
if ( result != 0 )
|
||||
goto Exit;
|
||||
|
||||
char_code++;
|
||||
}
|
||||
char_code = 0;
|
||||
|
||||
Exit:
|
||||
*pchar_code = char_code;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
t1_cmap_standard_init( T1_CMapStd cmap )
|
||||
{
|
||||
t1_cmap_std_init( cmap, 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE const T1_CMap_ClassRec
|
||||
t1_cmap_standard_class_rec =
|
||||
{
|
||||
sizeof( T1_CMapStdRec ),
|
||||
|
||||
t1_cmap_standard_init,
|
||||
t1_cmap_std_done,
|
||||
t1_cmap_std_char_index,
|
||||
t1_cmap_std_char_next
|
||||
};
|
||||
|
||||
|
||||
FT_LOCAL_DEF T1_CMap_Class
|
||||
t1_cmap_standard_class = &t1_cmap_standard_class_rec;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
t1_cmap_expert_init( T1_CMapStd cmap )
|
||||
{
|
||||
t1_cmap_std_init( cmap, 1 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
FT_CALLBACK_TABLE const T1_CMap_ClassRec
|
||||
t1_cmap_expert_class_rec =
|
||||
{
|
||||
sizeof( T1_CMapStdRec ),
|
||||
|
||||
t1_cmap_expert_init,
|
||||
t1_cmap_std_done,
|
||||
t1_cmap_std_char_index,
|
||||
t1_cmap_std_char_next
|
||||
};
|
||||
|
||||
|
||||
FT_LOCAL_DEF T1_CMap_Class
|
||||
t1_cmap_expert_class = &t1_cmap_expert_class_rec;
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***** *****/
|
||||
/***** TYPE1 CUSTOM ENCODING CMAP *****/
|
||||
/***** *****/
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
t1_cmap_custom_init( T1_CMapCustom cmap )
|
||||
{
|
||||
T1_Face face = (T1_Face) FT_CMAP_FACE(cmap);
|
||||
T1_Encoding* encoding = face->type1.encoding;
|
||||
|
||||
cmap->first = encoding->code_first;
|
||||
cmap->count = (FT_UInt)(encoding->code_last - cmap->first + 1);
|
||||
cmap->indices = encoding->char_index;
|
||||
|
||||
FT_ASSERT( cmap->indices != NULL );
|
||||
FT_ASSERT( encoding->code_first <= encoding->code_last );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
t1_cmap_custom_done( T1_CMapCustom cmap )
|
||||
{
|
||||
cmap->indices = NULL;
|
||||
cmap->first = 0;
|
||||
cmap->count = 0;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_UInt )
|
||||
t1_cmap_custom_char_index( T1_CMapCustom cmap,
|
||||
FT_UInt32 char_code )
|
||||
{
|
||||
FT_UInt result = 0;
|
||||
FT_UInt32 index;
|
||||
|
||||
index = (FT_UInt32)( char_code - cmap->first );
|
||||
if ( index < cmap->count )
|
||||
result = cmap->indices[ index ];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_UInt )
|
||||
t1_cmap_custom_char_next( T1_CMapCustion cmap,
|
||||
FT_UInt32 *pchar_code )
|
||||
{
|
||||
FT_UInt result = 0;
|
||||
FT_UInt32 char_code = *pchar_code;
|
||||
FT_UInt32 index;
|
||||
|
||||
++char_code;
|
||||
|
||||
if ( char_code < cmap->first )
|
||||
char_code = cmap->first;
|
||||
|
||||
index = (FT_UInt32)( char_code - cmap->first );
|
||||
while ( index < cmap->count; index++, char_code++ )
|
||||
{
|
||||
result = cmap->indices[index];
|
||||
if ( result != 0 )
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
char_code = 0;
|
||||
|
||||
Exit:
|
||||
*pchar_code = char_code;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE const FT_CMap_ClassRec
|
||||
t1_cmap_custom_class_rec =
|
||||
{
|
||||
sizeof( T1_CMapCustomRec ),
|
||||
t1_cmap_custom_init,
|
||||
t1_cmap_custom_done,
|
||||
t1_cmap_custom_char_index,
|
||||
t1_cmap_custom_char_next
|
||||
};
|
||||
|
||||
|
||||
FT_LOCAL_DEF FT_CMap_Class
|
||||
t1_cmap_custom_class = &t1_cmap_custom_class_rec;
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***** *****/
|
||||
/***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/
|
||||
/***** *****/
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
t1_cmap_unicode_init( T1_CMapUnicode cmap )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_UInt count;
|
||||
T1_Face face = (T1_Face) FT_CMAP_FACE(cmap);
|
||||
FT_Memory memory = FT_FACE_MEMORY(face);
|
||||
|
||||
cmap->num_pairs = 0;
|
||||
cmap->pairs = NULL;
|
||||
|
||||
count = face->type1.num_glyphs;
|
||||
|
||||
if ( !ALLOC_ARRAY( cmap->pairs, count, T1_CMapUniPairRec ) )
|
||||
{
|
||||
FT_UInt n, new_count;
|
||||
T1_CMapUniPair pair;
|
||||
FT_UInt32 uni_code;
|
||||
|
||||
|
||||
pair = cmap->pairs;
|
||||
for ( n = 0; n < count; n++ )
|
||||
{
|
||||
const char* gname = face->type1.glyph_names[n];
|
||||
|
||||
/* build unsorted pair table by matching glyph names */
|
||||
if ( gname )
|
||||
{
|
||||
uni_code = PS_Unicode_Value( gname );
|
||||
|
||||
if ( uni_code != 0 )
|
||||
{
|
||||
pair->unicode = uni_code;
|
||||
pair->gindex = n;
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( new_count == 0 )
|
||||
{
|
||||
/* there are no unicode characters in here !! */
|
||||
FREE( cmap->pairs );
|
||||
error = FT_Err_Invalid_Argument;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* re-allocate if the new array is much smaller than the original */
|
||||
/* one.. */
|
||||
if ( new_count != count && new_count < count/2 )
|
||||
REALLOC_ARRAY( cmap->pairs, count, new_count, T1_CMapUniPairRec )
|
||||
|
||||
/* sort the pairs table to allow efficient binary searches */
|
||||
qsort( cmap->pairs,
|
||||
new_count,
|
||||
sizeof(T1_CMapUniPairRec),
|
||||
t1_cmap_uni_pair_compare );
|
||||
|
||||
cmap->num_pairs = new_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
t1_cmap_unicode_done( T1_CMapUnicode cmap )
|
||||
{
|
||||
FT_Face face = FT_CMAP_FACE(cmap);
|
||||
FT_Memory memory = FT_FACE_MEMORY(face);
|
||||
|
||||
FREE( cmap->pairs );
|
||||
cmap->num_pairs = 0;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_UInt )
|
||||
t1_cmap_unicode_char_index( T1_CMapUnicode cmap,
|
||||
FT_UInt32 char_code )
|
||||
{
|
||||
FT_UInt min = 0;
|
||||
FT_UInt max = cmap->num_pairs;
|
||||
FT_UInt mid;
|
||||
T1_CMapUniPair pair;
|
||||
|
||||
while ( min < max )
|
||||
{
|
||||
mid = min + (max - min)/2;
|
||||
pair = cmap->pairs + mid;
|
||||
|
||||
if ( pair->unicode == char_code )
|
||||
return pair->gindex;
|
||||
|
||||
if ( pair->unicode < char_code )
|
||||
min = mid+1;
|
||||
else
|
||||
max = mid;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_UInt )
|
||||
t1_cmap_unicode_char_next( T1_CMapUnicode cmap,
|
||||
FT_UInt32 *pchar_code )
|
||||
{
|
||||
FT_UInt32 char_code = *pchar_code + 1;
|
||||
|
||||
Restart:
|
||||
{
|
||||
FT_UInt min = 0;
|
||||
FT_UInt max = cmap->num_pairs;
|
||||
FT_UInt mid;
|
||||
T1_CMapUniPair pair;
|
||||
|
||||
while ( min < max )
|
||||
{
|
||||
mid = min + (max - min)/2;
|
||||
pair = cmap->pairs + mid;
|
||||
|
||||
if ( pair->unicode == char_code )
|
||||
{
|
||||
result = pair->gindex;
|
||||
if ( result != 0 )
|
||||
goto Exit;
|
||||
|
||||
char_code++;
|
||||
goto Restart;
|
||||
}
|
||||
|
||||
if ( pair->unicode < char_code )
|
||||
min = mid+1;
|
||||
else
|
||||
max = mid;
|
||||
}
|
||||
|
||||
/* we didn't find it, but we have a pair just above it */
|
||||
char_code = 0;
|
||||
|
||||
if ( min < cmap->num_pairs )
|
||||
{
|
||||
pair = cmap->num_pairs + min;
|
||||
result = pair->gindex;
|
||||
if ( result != 0 )
|
||||
char_code = pair->unicode;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
*pchar_code = char_code;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE const FT_CMap_ClassRec
|
||||
t1_cmap_unicode_class_rec =
|
||||
{
|
||||
sizeof( T1_CMapUnicodeRec ),
|
||||
t1_cmap_unicode_init,
|
||||
t1_cmap_unicode_done,
|
||||
t1_cmap_unicode_char_index,
|
||||
t1_cmap_unicode_char_next
|
||||
};
|
||||
|
||||
|
||||
|
92
src/type1/t1cmap.h
Normal file
92
src/type1/t1cmap.h
Normal file
@ -0,0 +1,92 @@
|
||||
#ifndef __FT_TYPE1_CMAP_H__
|
||||
#define __FT_TYPE1_CMAP_H__
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***** *****/
|
||||
/***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/
|
||||
/***** *****/
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct T1_CMapStrRec_* T1_CMapStd;
|
||||
|
||||
typedef struct T1_CMapUnicodeRec_* T1_CMapUnicode;
|
||||
|
||||
|
||||
typedef struct T1_CMapStdRec_
|
||||
{
|
||||
FT_CMapRec cmap;
|
||||
|
||||
const FT_UShort* charcode_to_sid;
|
||||
const char* const* adobe_sid_strings;
|
||||
|
||||
FT_UInt num_glyphs;
|
||||
const char** glyph_names;
|
||||
|
||||
|
||||
} T1_CMapStdRec;
|
||||
|
||||
|
||||
FT_LOCAL( FT_CMap_Class ) t1_cmap_standard_class;
|
||||
|
||||
FT_LOCAL( FT_CMap_Class ) t1_cmap_expert_class;
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***** *****/
|
||||
/***** TYPE1 CUSTOM ENCODING CMAP *****/
|
||||
/***** *****/
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct T1_CMapCustomRec_* T1_CMapCustom;
|
||||
|
||||
typedef struct T1_CMapCustomRec_
|
||||
{
|
||||
FT_CMapRec cmap;
|
||||
FT_UInt first;
|
||||
FT_UInt count;
|
||||
FT_UInt* indices;
|
||||
|
||||
} T1_CMapCustomRec;
|
||||
|
||||
|
||||
FT_LOCAL( FT_CMap_Class ) t1_cmap_custom_class;
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***** *****/
|
||||
/***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/
|
||||
/***** *****/
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct T1_CMapUniPairRec_* T1_CMapUniPair;
|
||||
|
||||
typedef struct T1_CMapUniPairRec_
|
||||
{
|
||||
FT_UInt32 unicode;
|
||||
FT_UInt gindex;
|
||||
|
||||
} T1_CMapUniPairRec;
|
||||
|
||||
|
||||
typedef struct T1_CMapUnicodeRec_
|
||||
{
|
||||
FT_CMapRec cmap;
|
||||
FT_UInt num_pairs;
|
||||
T1_CMapUniPair pairs;
|
||||
|
||||
} T1_CMapUnicodeRec;
|
||||
|
||||
|
||||
FT_LOCAL( FT_CMap_Class ) t1_cmap_unicode_class;
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* __FT_TYPE1_CMAP_H__ */
|
Loading…
Reference in New Issue
Block a user