mirror of
git://git.sv.nongnu.org/freetype/freetype2.git
synced 2026-01-19 04:52:09 +00:00
[gxvar] Optimize loading of 'gvar' table.
* src/truetype/ttgxvar.c (tt_var_load_item_variation_store, tt_var_load_delta_set_index_mapping, ft_var_load_gvar): Use frames to reduce bounds checking. (TT_Vary_Apply_Glyph_Deltas): Better macro usage.
This commit is contained in:
committed by
Werner Lemberg
parent
42a649be49
commit
75b84313cf
@@ -489,8 +489,9 @@
|
||||
FT_UShort axis_count;
|
||||
FT_UInt region_count;
|
||||
|
||||
FT_UInt i, j;
|
||||
FT_Bool long_words;
|
||||
FT_UInt i, j;
|
||||
FT_Byte* bytes;
|
||||
FT_Bool long_words;
|
||||
|
||||
GX_Blend blend = ttface->blend;
|
||||
FT_ULong* dataOffsetArray = NULL;
|
||||
@@ -526,11 +527,15 @@
|
||||
if ( FT_QNEW_ARRAY( dataOffsetArray, data_count ) )
|
||||
goto Exit;
|
||||
|
||||
if ( FT_FRAME_ENTER( data_count * 4 ) )
|
||||
goto Exit;
|
||||
|
||||
bytes = stream->cursor;
|
||||
|
||||
for ( i = 0; i < data_count; i++ )
|
||||
{
|
||||
if ( FT_READ_ULONG( dataOffsetArray[i] ) )
|
||||
goto Exit;
|
||||
}
|
||||
dataOffsetArray[i] = FT_NEXT_ULONG( bytes );
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
/* parse array of region records (region list) */
|
||||
if ( FT_STREAM_SEEK( offset + region_offset ) )
|
||||
@@ -564,13 +569,26 @@
|
||||
goto Exit;
|
||||
itemStore->regionCount = region_count;
|
||||
|
||||
for ( i = 0; i < itemStore->regionCount; i++ )
|
||||
if ( FT_FRAME_ENTER( (FT_Long)region_count * axis_count * 6 ) )
|
||||
{
|
||||
FT_TRACE2(( "tt_var_load_item_variation_store:"
|
||||
" not enough data for variation regions\n" ));
|
||||
error = FT_THROW( Invalid_Table );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
bytes = stream->cursor;
|
||||
|
||||
for ( i = 0; i < region_count; i++ )
|
||||
{
|
||||
GX_AxisCoords axisCoords;
|
||||
|
||||
|
||||
if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, axis_count ) )
|
||||
{
|
||||
FT_FRAME_EXIT();
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
axisCoords = itemStore->varRegionList[i].axisList;
|
||||
|
||||
@@ -579,10 +597,9 @@
|
||||
FT_Int start, peak, end;
|
||||
|
||||
|
||||
if ( FT_READ_SHORT( start ) ||
|
||||
FT_READ_SHORT( peak ) ||
|
||||
FT_READ_SHORT( end ) )
|
||||
goto Exit;
|
||||
start = FT_NEXT_SHORT( bytes );
|
||||
peak = FT_NEXT_SHORT( bytes );
|
||||
end = FT_NEXT_SHORT( bytes );
|
||||
|
||||
/* immediately tag invalid ranges with special peak = 0 */
|
||||
if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
|
||||
@@ -594,6 +611,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
/* end of region list parse */
|
||||
|
||||
/* use dataOffsetArray now to parse varData items */
|
||||
@@ -648,20 +667,32 @@
|
||||
varData->wordDeltaCount = word_delta_count;
|
||||
varData->longWords = long_words;
|
||||
|
||||
if ( FT_FRAME_ENTER( region_idx_count * 2 ) )
|
||||
{
|
||||
FT_TRACE2(( "tt_var_load_item_variation_store:"
|
||||
" not enough data for region indices\n" ));
|
||||
error = FT_THROW( Invalid_Table );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
bytes = stream->cursor;
|
||||
|
||||
for ( j = 0; j < varData->regionIdxCount; j++ )
|
||||
{
|
||||
if ( FT_READ_USHORT( varData->regionIndices[j] ) )
|
||||
goto Exit;
|
||||
varData->regionIndices[j] = FT_NEXT_USHORT( bytes );
|
||||
|
||||
if ( varData->regionIndices[j] >= itemStore->regionCount )
|
||||
{
|
||||
FT_TRACE2(( "bad region index %d\n",
|
||||
varData->regionIndices[j] ));
|
||||
FT_FRAME_EXIT();
|
||||
error = FT_THROW( Invalid_Table );
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
per_region_size = word_delta_count + region_idx_count;
|
||||
if ( long_words )
|
||||
per_region_size *= 2;
|
||||
@@ -706,6 +737,7 @@
|
||||
FT_UInt innerIndexMask;
|
||||
FT_ULong i;
|
||||
FT_UInt j;
|
||||
FT_Byte* bytes;
|
||||
|
||||
|
||||
if ( FT_STREAM_SEEK( offset ) ||
|
||||
@@ -757,6 +789,16 @@
|
||||
if ( FT_NEW_ARRAY( map->outerIndex, map->mapCount ) )
|
||||
goto Exit;
|
||||
|
||||
if ( FT_FRAME_ENTER( map->mapCount * entrySize ) )
|
||||
{
|
||||
FT_TRACE2(( "tt_var_load_delta_set_index_mapping:"
|
||||
" invalid number of delta-set index mappings\n" ));
|
||||
error = FT_THROW( Invalid_Table );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
bytes = stream->cursor;
|
||||
|
||||
for ( i = 0; i < map->mapCount; i++ )
|
||||
{
|
||||
FT_UInt mapData = 0;
|
||||
@@ -769,9 +811,7 @@
|
||||
FT_Byte data;
|
||||
|
||||
|
||||
if ( FT_READ_BYTE( data ) )
|
||||
goto Exit;
|
||||
|
||||
data = FT_NEXT_BYTE( bytes );
|
||||
mapData = ( mapData << 8 ) | data;
|
||||
}
|
||||
|
||||
@@ -812,6 +852,8 @@
|
||||
map->innerIndex[i] = innerIndex;
|
||||
}
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
@@ -1643,6 +1685,7 @@
|
||||
GX_Blend blend = face->blend;
|
||||
FT_Error error;
|
||||
FT_UInt i, j;
|
||||
FT_Byte* bytes;
|
||||
FT_ULong table_len;
|
||||
FT_ULong gvar_start;
|
||||
FT_ULong offsetToData;
|
||||
@@ -1734,6 +1777,8 @@
|
||||
if ( FT_FRAME_ENTER( offsets_len ) )
|
||||
goto Exit;
|
||||
|
||||
bytes = stream->cursor;
|
||||
|
||||
/* offsets (one more offset than glyphs, to mark size of last) */
|
||||
if ( FT_QNEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) )
|
||||
goto Fail2;
|
||||
@@ -1744,9 +1789,17 @@
|
||||
FT_ULong max_offset = 0;
|
||||
|
||||
|
||||
if ( stream->limit - stream->cursor < gvar_head.glyphCount * 4 )
|
||||
{
|
||||
FT_TRACE2(( "ft_var_load_gvar:"
|
||||
" glyph variation data offset not enough\n" ));
|
||||
error = FT_THROW( Invalid_Table );
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
for ( i = 0; i <= gvar_head.glyphCount; i++ )
|
||||
{
|
||||
blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
|
||||
blend->glyphoffsets[i] = offsetToData + FT_NEXT_ULONG( bytes );
|
||||
|
||||
if ( max_offset <= blend->glyphoffsets[i] )
|
||||
max_offset = blend->glyphoffsets[i];
|
||||
@@ -1774,9 +1827,17 @@
|
||||
FT_ULong max_offset = 0;
|
||||
|
||||
|
||||
if ( stream->limit - stream->cursor < gvar_head.glyphCount * 2 )
|
||||
{
|
||||
FT_TRACE2(( "ft_var_load_gvar:"
|
||||
" glyph variation data offset not enough\n" ));
|
||||
error = FT_THROW( Invalid_Table );
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
for ( i = 0; i <= gvar_head.glyphCount; i++ )
|
||||
{
|
||||
blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
|
||||
blend->glyphoffsets[i] = offsetToData + FT_NEXT_USHORT( bytes ) * 2;
|
||||
|
||||
if ( max_offset <= blend->glyphoffsets[i] )
|
||||
max_offset = blend->glyphoffsets[i];
|
||||
@@ -1814,6 +1875,8 @@
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
bytes = stream->cursor;
|
||||
|
||||
if ( FT_QNEW_ARRAY( blend->tuplecoords,
|
||||
gvar_head.axisCount * gvar_head.globalCoordCount ) )
|
||||
goto Fail2;
|
||||
@@ -1824,7 +1887,7 @@
|
||||
for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ )
|
||||
{
|
||||
blend->tuplecoords[i * gvar_head.axisCount + j] =
|
||||
FT_fdot14ToFixed( FT_GET_SHORT() );
|
||||
FT_fdot14ToFixed( FT_NEXT_SHORT( bytes ) );
|
||||
FT_TRACE5(( "%.5f ",
|
||||
(double)blend->tuplecoords[i * gvar_head.axisCount + j] / 65536 ));
|
||||
}
|
||||
@@ -4213,8 +4276,8 @@
|
||||
error = FT_THROW( Invalid_Table );
|
||||
goto Exit;
|
||||
}
|
||||
tupleDataSize = FT_NEXT_USHORT( stream->cursor );
|
||||
tupleIndex = FT_NEXT_USHORT( stream->cursor );
|
||||
tupleDataSize = FT_GET_USHORT();
|
||||
tupleIndex = FT_GET_USHORT();
|
||||
|
||||
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user