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
|
#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> */
|
/* <Struct> */
|
||||||
|
@ -330,109 +483,6 @@ FT_BEGIN_HEADER
|
||||||
FT_Done_GlyphSlot( FT_GlyphSlot slot );
|
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
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
|
@ -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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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__ */
|
|
@ -301,6 +301,7 @@
|
||||||
(void)LOAD_( max_profile );
|
(void)LOAD_( max_profile );
|
||||||
(void)LOAD_( charmaps );
|
(void)LOAD_( charmaps );
|
||||||
|
|
||||||
|
|
||||||
/* the following tables are optional in PCL fonts -- */
|
/* the following tables are optional in PCL fonts -- */
|
||||||
/* don't check for errors */
|
/* don't check for errors */
|
||||||
(void)LOAD_( names );
|
(void)LOAD_( names );
|
||||||
|
|
|
@ -34,8 +34,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define TT_PEEK_Short FT_PEEK_SHORT
|
#define TT_PEEK_SHORT FT_PEEK_SHORT
|
||||||
#define TT_PEEK_UShort FT_PEEK16_UBE
|
#define TT_PEEK_USHORT FT_PEEK16_UBE
|
||||||
#define TT_PEEK_Long FT_PEEK32_BE
|
#define TT_PEEK_Long FT_PEEK32_BE
|
||||||
#define TT_PEEK_ULong FT_PEEK32_UBE
|
#define TT_PEEK_ULong FT_PEEK32_UBE
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
tt_cmap0_validate( FT_Byte* table,
|
tt_cmap0_validate( FT_Byte* table,
|
||||||
FT_Validator valid )
|
FT_Validator valid )
|
||||||
{
|
{
|
||||||
FT_Byte* p = table + 2; /* skip format */
|
FT_Byte* p = table + 2;
|
||||||
FT_UInt length = TT_NEXT_USHORT(p);
|
FT_UInt length = TT_NEXT_USHORT(p);
|
||||||
|
|
||||||
if ( table + length > valid->limit || length < 262 )
|
if ( table + length > valid->limit || length < 262 )
|
||||||
|
@ -83,6 +83,7 @@
|
||||||
{
|
{
|
||||||
FT_UInt n, index;
|
FT_UInt n, index;
|
||||||
|
|
||||||
|
p = table + 6;
|
||||||
for ( n = 0; n < 256; n++ )
|
for ( n = 0; n < 256; n++ )
|
||||||
{
|
{
|
||||||
index = *p++;
|
index = *p++;
|
||||||
|
@ -228,7 +229,7 @@
|
||||||
FT_Validator valid )
|
FT_Validator valid )
|
||||||
{
|
{
|
||||||
FT_Byte* p = table + 2; /* skip format */
|
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_UInt n, max_subs;
|
||||||
FT_Byte* keys; /* keys table */
|
FT_Byte* keys; /* keys table */
|
||||||
FT_Byte* subs; /* sub-headers */
|
FT_Byte* subs; /* sub-headers */
|
||||||
|
@ -256,6 +257,8 @@
|
||||||
max_subs = index;
|
max_subs = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FT_ASSERT( p == table + 518 );
|
||||||
|
|
||||||
subs = p;
|
subs = p;
|
||||||
glyph_ids = subs + (max_subs + 1)*8;
|
glyph_ids = subs + (max_subs + 1)*8;
|
||||||
if ( glyph_ids > valid->limit )
|
if ( glyph_ids > valid->limit )
|
||||||
|
@ -322,8 +325,8 @@
|
||||||
{
|
{
|
||||||
FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
|
FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
|
||||||
FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
|
FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
|
||||||
FT_Byte* p = table + 6; /* keys table */
|
FT_Byte* p = table + 6; /* keys table */
|
||||||
FT_Byte* subs = p + 512; /* subheaders table */
|
FT_Byte* subs = table + 518; /* subheaders table */
|
||||||
FT_Byte* sub;
|
FT_Byte* sub;
|
||||||
|
|
||||||
|
|
||||||
|
@ -339,14 +342,14 @@
|
||||||
/* Otherwise, return 0 */
|
/* Otherwise, return 0 */
|
||||||
/* */
|
/* */
|
||||||
p += char_lo*2;
|
p += char_lo*2;
|
||||||
if ( PEEK_UShort(p) != 0 )
|
if ( TT_PEEK_USHORT(p) != 0 )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* a 16-bit character code */
|
/* a 16-bit character code */
|
||||||
p += char_hi*2; /* jump to key entry */
|
p += char_hi*2; /* jump to key entry */
|
||||||
sub = subs + PEEK_UShort(p); /* jump to sub-header */
|
sub = subs + ( TT_PEEK_USHORT(p) & -8 ); /* jump to sub-header */
|
||||||
|
|
||||||
/* check that the hi byte isn't a valid one-byte value */
|
/* check that the hi byte isn't a valid one-byte value */
|
||||||
if ( sub == subs )
|
if ( sub == subs )
|
||||||
|
@ -378,75 +381,22 @@
|
||||||
start = TT_NEXT_USHORT(p);
|
start = TT_NEXT_USHORT(p);
|
||||||
count = TT_NEXT_USHORT(p);
|
count = TT_NEXT_USHORT(p);
|
||||||
delta = TT_NEXT_SHORT(p);
|
delta = TT_NEXT_SHORT(p);
|
||||||
offset = PEEK_UShort(p);
|
offset = TT_PEEK_USHORT(p);
|
||||||
|
|
||||||
index -= start;
|
index -= start;
|
||||||
if ( index < count && offset != 0 )
|
if ( index < count && offset != 0 )
|
||||||
{
|
{
|
||||||
p += offset + 2*index;
|
p += offset + 2*index;
|
||||||
index = PEEK_UShort(p);
|
index = TT_PEEK_USHORT(p);
|
||||||
|
|
||||||
if ( index == 0 )
|
if ( index != 0 )
|
||||||
goto Exit;
|
result = (FT_UInt)( index + delta ) & 0xFFFFU;
|
||||||
|
|
||||||
result = (FT_UInt)( index + delta ) & 0xFFFFU;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Exit:
|
|
||||||
return result;
|
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
|
static FT_UInt
|
||||||
tt_cmap2_char_next( FT_Byte* table,
|
tt_cmap2_char_next( FT_Byte* table,
|
||||||
|
@ -459,7 +409,7 @@
|
||||||
FT_Byte* p;
|
FT_Byte* p;
|
||||||
|
|
||||||
++char_code;
|
++char_code;
|
||||||
for (;;)
|
while ( char_code < 0x10000U )
|
||||||
{
|
{
|
||||||
subheader = tt_cmap2_get_subheader( table, char_code );
|
subheader = tt_cmap2_get_subheader( table, char_code );
|
||||||
if ( subheader )
|
if ( subheader )
|
||||||
|
@ -468,7 +418,7 @@
|
||||||
FT_UInt start = TT_NEXT_USHORT(p);
|
FT_UInt start = TT_NEXT_USHORT(p);
|
||||||
FT_UInt count = TT_NEXT_USHORT(p);
|
FT_UInt count = TT_NEXT_USHORT(p);
|
||||||
FT_Int delta = TT_NEXT_SHORT(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 char_lo = (FT_UInt)( char_code & 0xFF );
|
||||||
FT_UInt pos, index;
|
FT_UInt pos, index;
|
||||||
|
|
||||||
|
@ -505,8 +455,6 @@
|
||||||
/* jump to next sub-header, i.e. higher byte value */
|
/* jump to next sub-header, i.e. higher byte value */
|
||||||
Next_SubHeader:
|
Next_SubHeader:
|
||||||
char_code = (char_code & -256) + 256;
|
char_code = (char_code & -256) + 256;
|
||||||
if ( char_code >= 0x10000U )
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Exit:
|
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
|
#ifdef TT_CONFIG_CMAP_FORMAT_4
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -542,14 +542,13 @@
|
||||||
{
|
{
|
||||||
FT_Byte* p = table + 2; /* skip format */
|
FT_Byte* p = table + 2; /* skip format */
|
||||||
FT_UInt length = TT_NEXT_USHORT(p);
|
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;
|
FT_UInt n, num_segs;
|
||||||
|
|
||||||
if ( table + length > valid->limit || length < 16 )
|
if ( table + length > valid->limit || length < 16 )
|
||||||
TOO_SHORT;
|
TOO_SHORT;
|
||||||
|
|
||||||
p += 2; /* skip language */
|
p = table + 6;
|
||||||
|
|
||||||
num_segs = TT_NEXT_USHORT(p); /* read segCountX2 */
|
num_segs = TT_NEXT_USHORT(p); /* read segCountX2 */
|
||||||
|
|
||||||
if ( valid->level >= FT_VALIDATE_PARANOID )
|
if ( valid->level >= FT_VALIDATE_PARANOID )
|
||||||
|
@ -584,12 +583,11 @@
|
||||||
search_range != (1 << entry_selector) )
|
search_range != (1 << entry_selector) )
|
||||||
INVALID_DATA;
|
INVALID_DATA;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
p += 6;
|
|
||||||
|
|
||||||
ends = p;
|
ends = table + 14;
|
||||||
starts = ends + num_segs*2 + 2;
|
starts = table + 16 + num_segs*2;
|
||||||
offsets = starts + num_segs*4;
|
deltas = starts + num_segs*2;
|
||||||
|
offsets = deltas + num_segs*2;
|
||||||
glyph_ids = offsets + num_segs*2;
|
glyph_ids = offsets + num_segs*2;
|
||||||
|
|
||||||
if ( glyph_ids >= table + length )
|
if ( glyph_ids >= table + length )
|
||||||
|
@ -599,7 +597,7 @@
|
||||||
if ( valid->level >= FT_VALIDATE_PARANOID )
|
if ( valid->level >= FT_VALIDATE_PARANOID )
|
||||||
{
|
{
|
||||||
p = ends + (num_segs-1)*2;
|
p = ends + (num_segs-1)*2;
|
||||||
if ( PEEK_UShort(p) != 0xFFFFU )
|
if ( TT_PEEK_USHORT(p) != 0xFFFFU )
|
||||||
INVALID_DATA;
|
INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,12 +605,14 @@
|
||||||
/* check also the offsets.. */
|
/* check also the offsets.. */
|
||||||
{
|
{
|
||||||
FT_UInt start, end, last = 0,offset, n;
|
FT_UInt start, end, last = 0,offset, n;
|
||||||
|
FT_Int delta;
|
||||||
|
|
||||||
for ( n = 0; n < num_segs; n++ )
|
for ( n = 0; n < num_segs; n++ )
|
||||||
{
|
{
|
||||||
p = starts + n*2; start = PEEK_UShort(p);
|
p = starts + n*2; start = TT_PEEK_USHORT(p);
|
||||||
p = ends + n*2; end = PEEK_UShort(p);
|
p = ends + n*2; end = TT_PEEK_USHORT(p);
|
||||||
p = offsets + n*2; offset = PEEK_UShort(p);
|
p = deltas + n*2; delta = TT_PEEK_SHORT(p);
|
||||||
|
p = offsets + n*2; offset = TT_PEEK_USHORT(p);
|
||||||
|
|
||||||
if ( end > start )
|
if ( end > start )
|
||||||
INVALID_DATA;
|
INVALID_DATA;
|
||||||
|
@ -625,10 +625,26 @@
|
||||||
p += offset; /* start of glyph id array */
|
p += offset; /* start of glyph id array */
|
||||||
|
|
||||||
/* check that we point within the glyph ids table only */
|
/* 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;
|
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;
|
last = end;
|
||||||
}
|
}
|
||||||
|
@ -651,7 +667,7 @@
|
||||||
FT_UInt code = (FT_UInt)char_code;
|
FT_UInt code = (FT_UInt)char_code;
|
||||||
|
|
||||||
p = table + 6;
|
p = table + 6;
|
||||||
num_segs2 = PEEK_UShort(p);
|
num_segs2 = TT_PEEK_USHORT(p) & -2; /* be paranoid !! */
|
||||||
|
|
||||||
p = table + 14; /* ends table */
|
p = table + 14; /* ends table */
|
||||||
q = table + 16 + num_segs2; /* starts table */
|
q = table + 16 + num_segs2; /* starts table */
|
||||||
|
@ -668,13 +684,13 @@
|
||||||
{
|
{
|
||||||
index = (FT_UInt)( char_code - start );
|
index = (FT_UInt)( char_code - start );
|
||||||
|
|
||||||
p = q + num_segs2 - 2; delta = PEEK_Short(p);
|
p = q + num_segs2 - 2; delta = TT_PEEK_SHORT(p);
|
||||||
p += num_segs2; offset = PEEK_UShort(p);
|
p += num_segs2; offset = TT_PEEK_USHORT(p);
|
||||||
|
|
||||||
if ( offset != 0 )
|
if ( offset != 0 )
|
||||||
{
|
{
|
||||||
p += offset + 2*index;
|
p += offset + 2*index;
|
||||||
index = PEEK_UShort(p);
|
index = TT_PEEK_USHORT(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( index != 0 )
|
if ( index != 0 )
|
||||||
|
@ -703,7 +719,7 @@
|
||||||
|
|
||||||
code = (FT_UInt)char_code;
|
code = (FT_UInt)char_code;
|
||||||
p = table + 6;
|
p = table + 6;
|
||||||
num_segs2 = PEEK_UShort(p) & -2; /* ensure even-ness */
|
num_segs2 = TT_PEEK_USHORT(p) & -2; /* ensure even-ness */
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -723,8 +739,8 @@
|
||||||
|
|
||||||
if ( code <= end )
|
if ( code <= end )
|
||||||
{
|
{
|
||||||
p = q + num_segs2 - 2; delta = PEEK_Short(p);
|
p = q + num_segs2 - 2; delta = TT_PEEK_SHORT(p);
|
||||||
p += num_segs2; offset = PEEK_UShort(p);
|
p += num_segs2; offset = TT_PEEK_USHORT(p);
|
||||||
|
|
||||||
if ( offset != 0 )
|
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
|
#ifdef TT_CONFIG_CMAP_FORMAT_6
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tt_cmap6_validate( FT_Byte* table,
|
tt_cmap6_validate( FT_Byte* table,
|
||||||
FT_Validator valid )
|
FT_Validator valid )
|
||||||
{
|
{
|
||||||
FT_Byte* p = table + 2;
|
FT_Byte* p;
|
||||||
FT_UInt length, start, count;
|
FT_UInt length, start, count;
|
||||||
|
|
||||||
if ( table + 10 > valid->limit )
|
if ( table + 10 > valid->limit )
|
||||||
INVALID_TOO_SHORT;
|
INVALID_TOO_SHORT;
|
||||||
|
|
||||||
|
p = table + 2;
|
||||||
length = TT_NEXT_USHORT(p);
|
length = TT_NEXT_USHORT(p);
|
||||||
p += 2; /* skip language */
|
|
||||||
|
p = table + 6; /* skip language */
|
||||||
start = TT_NEXT_USHORT(p);
|
start = TT_NEXT_USHORT(p);
|
||||||
count = TT_NEXT_USHORT(p);
|
count = TT_NEXT_USHORT(p);
|
||||||
|
|
||||||
|
@ -833,7 +870,7 @@
|
||||||
if ( index < count )
|
if ( index < count )
|
||||||
{
|
{
|
||||||
p += 2*index;
|
p += 2*index;
|
||||||
result = PEEK_UShort(p);
|
result = TT_PEEK_USHORT(p);
|
||||||
}
|
}
|
||||||
return result;
|
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
|
#ifdef TT_CONFIG_CMAP_FORMAT_8
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -939,11 +998,11 @@
|
||||||
INVALID_TOO_SHORT;
|
INVALID_TOO_SHORT;
|
||||||
|
|
||||||
length = TT_NEXT_ULONG(p);
|
length = TT_NEXT_ULONG(p);
|
||||||
if ( table + length > valid->limit || length < 16 + 8192 )
|
if ( table + length > valid->limit || length < 8208 )
|
||||||
INVALID_TOO_SHORT;
|
INVALID_TOO_SHORT;
|
||||||
|
|
||||||
is32 = p + 4; /* skip language */
|
is32 = table + 12;
|
||||||
p = is32 + 8192; /* skip 'is32' array */
|
p = is32 + 8192; /* skip 'is32' array */
|
||||||
num_groups = TT_NEXT_ULONG(p);
|
num_groups = TT_NEXT_ULONG(p);
|
||||||
|
|
||||||
if ( p + num_groups*12 > valid->limit )
|
if ( p + num_groups*12 > valid->limit )
|
||||||
|
@ -1009,6 +1068,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last = end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1019,7 +1080,7 @@
|
||||||
FT_ULong char_code )
|
FT_ULong char_code )
|
||||||
{
|
{
|
||||||
FT_UInt result = 0;
|
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 num_groups = TT_NEXT_ULONG(p);
|
||||||
FT_ULong n, start, end, start_id;
|
FT_ULong n, start, end, start_id;
|
||||||
|
|
||||||
|
@ -1049,12 +1110,12 @@
|
||||||
{
|
{
|
||||||
FT_ULong result = 0;
|
FT_ULong result = 0;
|
||||||
FT_UInt gindex = 0;
|
FT_UInt gindex = 0;
|
||||||
FT_Byte* p = table + 12 + 8192;
|
FT_Byte* p = table + 8204;
|
||||||
FT_ULong num_groups = TT_NEXT_USHORT(p);
|
FT_ULong num_groups = TT_NEXT_ULONG(p);
|
||||||
FT_ULong n, start, end, start_id;
|
FT_ULong n, start, end, start_id;
|
||||||
|
|
||||||
++char_code;
|
++char_code;
|
||||||
p = table + 16 + 8192;
|
p = table + 8208;
|
||||||
|
|
||||||
for ( n = 0; n < num_groups++; n++ )
|
for ( n = 0; n < num_groups++; n++ )
|
||||||
{
|
{
|
||||||
|
@ -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
|
#ifdef TT_CONFIG_CMAP_FORMAT_10
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tt_cmap10_validate( FT_Byte* table,
|
tt_cmap10_validate( FT_Byte* table,
|
||||||
FT_Validator valid )
|
FT_Validator valid )
|
||||||
{
|
{
|
||||||
FT_Byte* p = table + 2;
|
FT_Byte* p = table + 4;
|
||||||
FT_ULong length, start, count;
|
FT_ULong length, start, count;
|
||||||
|
|
||||||
if ( table + 20 > valid->limit )
|
if ( table + 20 > valid->limit )
|
||||||
INVALID_TOO_SHORT;
|
INVALID_TOO_SHORT;
|
||||||
|
|
||||||
length = TT_NEXT_USHORT(p);
|
length = TT_NEXT_ULONG(p);
|
||||||
p += 4; /* skip language */
|
p = table + 12;
|
||||||
start = TT_NEXT_ULONG(p);
|
start = TT_NEXT_ULONG(p);
|
||||||
count = TT_NEXT_ULONG(p);
|
count = TT_NEXT_ULONG(p);
|
||||||
|
|
||||||
|
@ -1148,8 +1226,8 @@
|
||||||
|
|
||||||
if ( index < count )
|
if ( index < count )
|
||||||
{
|
{
|
||||||
p += 2*index;
|
p += 2*index;
|
||||||
result = PEEK_UShort(p);
|
result = TT_PEEK_USHORT(p);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1168,9 +1246,6 @@
|
||||||
FT_ULong index;
|
FT_ULong index;
|
||||||
|
|
||||||
char_code++;
|
char_code++;
|
||||||
if ( char_code >= 0x10000U )
|
|
||||||
goto Exit;
|
|
||||||
|
|
||||||
if ( char_code < start )
|
if ( char_code < start )
|
||||||
char_code = start;
|
char_code = start;
|
||||||
|
|
||||||
|
@ -1213,19 +1288,107 @@
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* 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
|
#ifdef TT_CONFIG_CMAP_FORMAT_12
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tt_cmap12_validate( FT_Byte* table,
|
tt_cmap12_validate( FT_Byte* table,
|
||||||
FT_Validator valid )
|
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
|
static FT_UInt
|
||||||
tt_cmap12_char_index( FT_Byte* table,
|
tt_cmap12_char_index( FT_Byte* table,
|
||||||
FT_ULong char_code )
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1234,6 +1397,40 @@
|
||||||
FT_ULong char_code,
|
FT_ULong char_code,
|
||||||
FT_UInt *agindex )
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1246,3 +1443,4 @@
|
||||||
|
|
||||||
#endif /* TT_CONFIG_CMAP_FORMAT_12 */
|
#endif /* TT_CONFIG_CMAP_FORMAT_12 */
|
||||||
|
|
||||||
|
/* END */
|
||||||
|
|
|
@ -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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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