ref: 617a2e1c3c8176e8ae31313a784829f278b1766e
parent: 53b3fa1da5e3397388f3483ccc95910eca4a419d
author: David Turner <[email protected]>
date: Wed Feb 27 16:25:47 EST 2002
adding several experimental sources: - OpenType Layout validation and parsing (common tables) - Type 1 charmap processing
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -75,6 +75,159 @@
/*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** 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> */
/* FT_Face_InternalRec */
@@ -329,109 +482,6 @@
FT_BASE( void )
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
/*************************************************************************/
/*************************************************************************/
--- /dev/null
+++ b/src/otlayout/otlcommn.c
@@ -1,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 );
+ }
+ }
+
+
--- /dev/null
+++ b/src/otlayout/otlcommn.h
@@ -1,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__ */
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -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 */
--- a/src/sfnt/ttcmap0.c
+++ b/src/sfnt/ttcmap0.c
@@ -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,76 +381,23 @@
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,
FT_ULong char_code,
@@ -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,6 +801,25 @@
/************************************************************************/
/************************************************************************/
+ /*************************************************************************
+ *
+ * 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
@@ -791,14 +826,16 @@
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,6 +1162,23 @@
/************************************************************************/
/************************************************************************/
+ /*************************************************************************
+ *
+ * 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
@@ -1107,14 +1185,14 @@
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,6 +1288,28 @@
/************************************************************************/
/************************************************************************/
+ /*************************************************************************
+ *
+ * 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
@@ -1219,24 +1316,124 @@
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
tt_cmap12_char_next( FT_Byte* table,
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 =
{
(TT_CMap_ValidateFunc) tt_cmap12_validate,
@@ -1246,3 +1443,4 @@
#endif /* TT_CONFIG_CMAP_FORMAT_12 */
+/* END */
--- /dev/null
+++ b/src/type1/t1cmap.c
@@ -1,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
+ };
+
+
+
\ No newline at end of file
--- /dev/null
+++ b/src/type1/t1cmap.h
@@ -1,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__ */