static void gxv_lcar_LookupValue_validate( FT_UShort glyph, GXV_LookupValueDesc value, GXV_Validator valid ) { FT_Bytes p = valid->root->base + value.u; FT_Bytes limit = valid->root->limit; FT_UShort count; FT_Short partial; FT_UShort i; GXV_NAME_ENTER( "element in lookupTable" ); GXV_LIMIT_CHECK( 2 ); count = FT_NEXT_USHORT( p ); GXV_LIMIT_CHECK( 2 * count ); for ( i = 0; i < count; i++ ) { partial = FT_NEXT_SHORT( p ); gxv_lcar_partial_validate( partial, glyph, valid ); } GXV_EXIT; }
static void gxv_opbd_LookupValue_validate( FT_UShort glyph, GXV_LookupValueCPtr value_p, GXV_Validator gxvalid ) { /* offset in LookupTable is measured from the head of opbd table */ FT_Bytes p = gxvalid->root->base + value_p->u; FT_Bytes limit = gxvalid->root->limit; FT_Short delta_value; int i; if ( value_p->u < GXV_OPBD_DATA( valueOffset_min ) ) GXV_OPBD_DATA( valueOffset_min ) = value_p->u; for ( i = 0; i < 4; i++ ) { GXV_LIMIT_CHECK( 2 ); delta_value = FT_NEXT_SHORT( p ); if ( GXV_OPBD_DATA( format ) ) /* format 1, value is ctrl pt. */ { if ( delta_value == -1 ) continue; gxv_ctlPoint_validate( glyph, (FT_UShort)delta_value, gxvalid ); } else /* format 0, value is distance */ continue; } }
static void gxv_kern_subtable_fmt0_pairs_validate( FT_Bytes table, FT_Bytes limit, FT_UShort nPairs, GXV_Validator valid ) { FT_Bytes p = table; FT_UShort i; FT_UShort last_gid_left = 0; FT_UShort last_gid_right = 0; FT_UNUSED( limit ); GXV_NAME_ENTER( "kern format 0 pairs" ); for ( i = 0; i < nPairs; i++ ) { FT_UShort gid_left; FT_UShort gid_right; FT_Short kernValue; /* left */ gid_left = FT_NEXT_USHORT( p ); gxv_glyphid_validate( gid_left, valid ); /* right */ gid_right = FT_NEXT_USHORT( p ); gxv_glyphid_validate( gid_right, valid ); /* Pairs of left and right GIDs must be unique and sorted. */ GXV_TRACE(( "left gid = %u, right gid = %u\n", gid_left, gid_right )); if ( gid_left == last_gid_left ) { if ( last_gid_right < gid_right ) last_gid_right = gid_right; else FT_INVALID_DATA; } else if ( last_gid_left < gid_left ) { last_gid_left = gid_left; last_gid_right = gid_right; } else FT_INVALID_DATA; /* skip the kern value */ kernValue = FT_NEXT_SHORT( p ); } GXV_EXIT; }
FT_Stream_GetShort( FT_Stream stream ) { FT_Byte* p; FT_Short result; FT_ASSERT( stream && stream->cursor ); result = 0; p = stream->cursor; if ( p + 1 < stream->limit ) result = FT_NEXT_SHORT( p ); stream->cursor = p; return result; }
FT_Stream_ReadShort( FT_Stream stream, FT_Error* error ) { FT_Byte reads[2]; FT_Byte* p = 0; FT_Short result = 0; FT_ASSERT( stream ); *error = FT_Err_Ok; if ( stream->pos + 1 < stream->size ) { if ( stream->read ) { if ( stream->read( stream, stream->pos, reads, 2L ) != 2L ) goto Fail; p = reads; } else { p = stream->base + stream->pos; } if ( p ) result = FT_NEXT_SHORT( p ); } else goto Fail; stream->pos += 2; return result; Fail: *error = FT_Err_Invalid_Stream_Operation; FT_ERROR(( "FT_Stream_ReadShort:" )); FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", stream->pos, stream->size )); return 0; }
pfr_extra_item_load_stem_snaps( FT_Byte* p, FT_Byte* limit, PFR_PhyFont phy_font ) { FT_UInt count, num_vert, num_horz; FT_Int* snaps = NULL; FT_Error error = FT_Err_Ok; FT_Memory memory = phy_font->memory; if ( phy_font->vertical.stem_snaps ) goto Exit; PFR_CHECK( 1 ); count = PFR_NEXT_BYTE( p ); num_vert = count & 15; num_horz = count >> 4; count = num_vert + num_horz; PFR_CHECK( count * 2 ); if ( FT_NEW_ARRAY( snaps, count ) ) goto Exit; phy_font->vertical.stem_snaps = snaps; phy_font->horizontal.stem_snaps = snaps + num_vert; for ( ; count > 0; count--, snaps++ ) *snaps = FT_NEXT_SHORT( p ); Exit: return error; Too_Short: error = FT_THROW( Invalid_Table ); FT_ERROR(( "pfr_extra_item_load_stem_snaps:" " invalid stem snaps table\n" )); goto Exit; }
static void gxv_feat_name_index_validate( FT_Bytes table, FT_Bytes limit, GXV_Validator gxvalid ) { FT_Bytes p = table; FT_Short nameIndex; GXV_NAME_ENTER( "nameIndex" ); GXV_LIMIT_CHECK( 2 ); nameIndex = FT_NEXT_SHORT ( p ); GXV_TRACE(( " (nameIndex = %d)\n", nameIndex )); gxv_sfntName_validate( (FT_UShort)nameIndex, 255, 32768U, gxvalid ); GXV_EXIT; }
tt_face_load_hmtx( TT_Face face, FT_Stream stream, FT_Bool vertical ) { FT_Error error; FT_Memory memory = stream->memory; FT_ULong table_len; FT_Long num_shorts, num_longs, num_shorts_checked; TT_LongMetrics* longs; TT_ShortMetrics** shorts; FT_Byte* p; if ( vertical ) { void* lm = &face->vertical.long_metrics; void** sm = &face->vertical.short_metrics; error = face->goto_table( face, TTAG_vmtx, stream, &table_len ); if ( error ) goto Fail; num_longs = face->vertical.number_Of_VMetrics; if ( (FT_ULong)num_longs > table_len / 4 ) num_longs = (FT_Long)( table_len / 4 ); face->vertical.number_Of_VMetrics = 0; longs = (TT_LongMetrics*)lm; shorts = (TT_ShortMetrics**)sm; } else { void* lm = &face->horizontal.long_metrics; void** sm = &face->horizontal.short_metrics; error = face->goto_table( face, TTAG_hmtx, stream, &table_len ); if ( error ) goto Fail; num_longs = face->horizontal.number_Of_HMetrics; if ( (FT_ULong)num_longs > table_len / 4 ) num_longs = (FT_Long)( table_len / 4 ); face->horizontal.number_Of_HMetrics = 0; longs = (TT_LongMetrics*)lm; shorts = (TT_ShortMetrics**)sm; } /* never trust derived values */ num_shorts = face->max_profile.numGlyphs - num_longs; num_shorts_checked = ( table_len - num_longs * 4L ) / 2; if ( num_shorts < 0 ) { FT_ERROR(( "%cmtx has more metrics than glyphs.\n" )); /* Adobe simply ignores this problem. So we shall do the same. */ #if 0 error = vertical ? SFNT_Err_Invalid_Vert_Metrics : SFNT_Err_Invalid_Horiz_Metrics; goto Exit; #else num_shorts = 0; #endif } if ( FT_QNEW_ARRAY( *longs, num_longs ) || FT_QNEW_ARRAY( *shorts, num_shorts ) ) goto Fail; if ( FT_FRAME_ENTER( table_len ) ) goto Fail; p = stream->cursor; { TT_LongMetrics cur = *longs; TT_LongMetrics limit = cur + num_longs; for ( ; cur < limit; cur++ ) { cur->advance = FT_NEXT_USHORT( p ); cur->bearing = FT_NEXT_SHORT( p ); } } /* do we have an inconsistent number of metric values? */ { TT_ShortMetrics* cur = *shorts; TT_ShortMetrics* limit = cur + FT_MIN( num_shorts, num_shorts_checked ); for ( ; cur < limit; cur++ ) *cur = FT_NEXT_SHORT( p ); /* We fill up the missing left side bearings with the */ /* last valid value. Since this will occur for buggy CJK */ /* fonts usually only, nothing serious will happen. */ if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 ) { FT_Short val = (*shorts)[num_shorts_checked - 1]; limit = *shorts + num_shorts; for ( ; cur < limit; cur++ ) *cur = val; } } FT_FRAME_EXIT(); if ( vertical ) face->vertical.number_Of_VMetrics = (FT_UShort)num_longs; else face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs; Fail: return error; }
pfr_face_get_kerning( PFR_Face face, FT_UInt glyph1, FT_UInt glyph2, FT_Vector* kerning ) { FT_Error error; PFR_PhyFont phy_font = &face->phy_font; PFR_KernItem item = phy_font->kern_items; FT_UInt32 idx = PFR_KERN_INDEX( glyph1, glyph2 ); kerning->x = 0; kerning->y = 0; /* find the kerning item containing our pair */ while ( item ) { if ( item->pair1 <= idx && idx <= item->pair2 ) goto Found_Item; item = item->next; } /* not found */ goto Exit; Found_Item: { /* perform simply binary search within the item */ FT_UInt min, mid, max; FT_Stream stream = face->root.stream; FT_Byte* p; if ( FT_STREAM_SEEK( item->offset ) || FT_FRAME_ENTER( item->pair_count * item->pair_size ) ) goto Exit; min = 0; max = item->pair_count; while ( min < max ) { FT_UInt char1, char2, charcode; mid = ( min + max ) >> 1; p = stream->cursor + mid*item->pair_size; if ( item->flags & PFR_KERN_2BYTE_CHAR ) { char1 = FT_NEXT_USHORT( p ); char2 = FT_NEXT_USHORT( p ); } else { char1 = FT_NEXT_USHORT( p ); char2 = FT_NEXT_USHORT( p ); } charcode = PFR_KERN_INDEX( char1, char2 ); if ( idx == charcode ) { if ( item->flags & PFR_KERN_2BYTE_ADJ ) kerning->x = item->base_adj + FT_NEXT_SHORT( p ); else kerning->x = item->base_adj + FT_NEXT_CHAR( p ); break; } if ( idx > charcode ) min = mid + 1; else max = mid; } FT_FRAME_EXIT(); } Exit: return 0; }
tt_face_get_metrics( TT_Face face, FT_Bool vertical, FT_UInt gindex, FT_Short *abearing, FT_UShort *aadvance ) { TT_HoriHeader* header; FT_Byte* p; FT_Byte* limit; FT_UShort k; if ( vertical ) { header = (TT_HoriHeader*)&face->vertical; p = face->vert_metrics; limit = p + face->vert_metrics_size; } else { header = &face->horizontal; p = face->horz_metrics; limit = p + face->horz_metrics_size; } k = header->number_Of_HMetrics; if ( k > 0 ) { if ( gindex < (FT_UInt)k ) { p += 4 * gindex; if ( p + 4 > limit ) goto NoData; *aadvance = FT_NEXT_USHORT( p ); *abearing = FT_NEXT_SHORT( p ); } else { p += 4 * ( k - 1 ); if ( p + 4 > limit ) goto NoData; *aadvance = FT_NEXT_USHORT( p ); p += 2 + 2 * ( gindex - k ); if ( p + 2 > limit ) *abearing = 0; else *abearing = FT_PEEK_SHORT( p ); } } else { NoData: *abearing = 0; *aadvance = 0; } return SFNT_Err_Ok; }
static FT_Error pfr_sort_kerning_pairs( FT_Stream stream, PFR_PhyFont phy_font ) { FT_Error error; FT_Memory memory = stream->memory; PFR_KernPair pairs; PFR_KernItem item; PFR_Char chars = phy_font->chars; FT_UInt num_chars = phy_font->num_chars; FT_UInt count; /* create kerning pairs array */ if ( FT_NEW_ARRAY( phy_font->kern_pairs, phy_font->num_kern_pairs ) ) goto Exit; /* load all kerning items into the array, * converting character codes into glyph indices */ pairs = phy_font->kern_pairs; item = phy_font->kern_items; count = 0; for ( ; item; item = item->next ) { FT_UInt limit = count + item->pair_count; FT_Byte* p; if ( limit > phy_font->num_kern_pairs ) { error = PFR_Err_Invalid_Table; goto Exit; } if ( FT_STREAM_SEEK( item->offset ) || FT_FRAME_ENTER( item->pair_count * item->pair_size ) ) goto Exit; p = stream->cursor; for ( ; count < limit; count++ ) { PFR_KernPair pair = pairs + count; FT_UInt char1, char2; FT_Int kerning; if ( item->flags & PFR_KERN_2BYTE_CHAR ) { char1 = FT_NEXT_USHORT( p ); char2 = FT_NEXT_USHORT( p ); } else { char1 = FT_NEXT_BYTE( p ); char2 = FT_NEXT_BYTE( p ); } if ( item->flags & PFR_KERN_2BYTE_ADJ ) kerning = item->base_adj + FT_NEXT_SHORT( p ); else kerning = item->base_adj + FT_NEXT_CHAR( p ); pair->glyph1 = pfr_get_gindex( chars, num_chars, char1 ); pair->glyph2 = pfr_get_gindex( chars, num_chars, char2 ); pair->kerning = kerning; } FT_FRAME_EXIT(); } /* sort the resulting array */ ft_qsort( pairs, count, sizeof ( PFR_KernPairRec ), pfr_compare_kern_pairs ); Exit: if ( error ) { /* disable kerning data in case of error */ phy_font->num_kern_pairs = 0; } return error; }
static void otv_SingleSubst_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt SubstFormat; OTV_NAME_ENTER( "SingleSubst" ); OTV_LIMIT_CHECK( 2 ); SubstFormat = FT_NEXT_USHORT( p ); OTV_TRACE(( " (format %d)\n", SubstFormat )); switch ( SubstFormat ) { case 1: /* SingleSubstFormat1 */ { FT_Bytes Coverage; FT_Int DeltaGlyphID; FT_Long idx; OTV_LIMIT_CHECK( 4 ); Coverage = table + FT_NEXT_USHORT( p ); DeltaGlyphID = FT_NEXT_SHORT( p ); otv_Coverage_validate( Coverage, otvalid, -1 ); idx = (FT_Long)otv_Coverage_get_first( Coverage ) + DeltaGlyphID; if ( idx < 0 ) FT_INVALID_DATA; idx = (FT_Long)otv_Coverage_get_last( Coverage ) + DeltaGlyphID; if ( (FT_UInt)idx >= otvalid->glyph_count ) FT_INVALID_DATA; } break; case 2: /* SingleSubstFormat2 */ { FT_UInt Coverage, GlyphCount; OTV_LIMIT_CHECK( 4 ); Coverage = FT_NEXT_USHORT( p ); GlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount )); otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)GlyphCount ); OTV_LIMIT_CHECK( GlyphCount * 2 ); /* Substitute */ for ( ; GlyphCount > 0; GlyphCount-- ) if ( FT_NEXT_USHORT( p ) >= otvalid->glyph_count ) FT_INVALID_GLYPH_ID; } break; default: FT_INVALID_FORMAT; } OTV_EXIT; }