From 304f0383ef6a3d242d4978274e9799163013e311 Mon Sep 17 00:00:00 2001 From: Dave Arnold Date: Wed, 2 Nov 2016 14:49:51 -0700 Subject: [PATCH] [truetype] Fix HVAR bugs with more than one data item * src/truetype/ttgxvar.c (ft_var_load_hvar, tt_adjust_advance): rename regionCount to regionIdxCount. Clean up some comments. --- src/truetype/ttgxvar.c | 68 ++++++++++++++++++++++-------------------- src/truetype/ttgxvar.h | 30 +++++++++---------- 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 718f34c57..e5ed512a3 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -432,6 +432,8 @@ FT_ULong table_offset; FT_ULong store_offset; FT_ULong map_offset; + FT_ULong * dataOffsetArray = NULL; + FT_TRACE2(( "HVAR " )); @@ -465,8 +467,6 @@ /* parse item variation store */ { FT_UShort format; - FT_ULong data_offset_array_offset; - FT_ULong data_offset; FT_ULong region_offset; GX_HVStore itemStore; FT_UInt i, j, k; @@ -490,13 +490,20 @@ hvarTable = blend->hvar_table; itemStore = &hvarTable->itemStore; + /* read top level fields */ if ( FT_READ_ULONG( region_offset ) || FT_READ_USHORT( itemStore->dataCount ) ) goto Exit; - /* save position of item variation data offsets */ - /* we'll parse region list first, then come back */ - data_offset_array_offset = FT_STREAM_POS(); + /* make temporary copy of item variation data offsets */ + /* we'll parse region list first, then come back */ + if ( FT_NEW_ARRAY( dataOffsetArray, itemStore->dataCount ) ) + goto Exit; + for ( i=0; idataCount; i++ ) + { + if ( FT_READ_ULONG( dataOffsetArray[i] ) ) + goto Exit; + } /* parse array of region records (region list) */ if ( FT_STREAM_SEEK( table_offset + store_offset + region_offset ) ) @@ -533,50 +540,47 @@ } /* end of region list parse */ - /* parse array of item variation data subtables */ - if ( FT_STREAM_SEEK( data_offset_array_offset ) ) - goto Exit; - + /* use dataOffsetArray now to parse varData items */ if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) ) - goto Exit; + goto Exit; - hvarData = itemStore->varData; for ( i=0; idataCount; i++ ) { - if ( FT_READ_ULONG( data_offset ) ) + hvarData = &itemStore->varData[i]; + + if ( FT_STREAM_SEEK( table_offset + store_offset + dataOffsetArray[i] ) ) goto Exit; - if ( FT_STREAM_SEEK( table_offset + store_offset + data_offset ) || - FT_READ_USHORT( hvarData->itemCount ) || + if ( FT_READ_USHORT( hvarData->itemCount ) || FT_READ_USHORT( shortDeltaCount ) || - FT_READ_USHORT( hvarData->regionCount ) ) + FT_READ_USHORT( hvarData->regionIdxCount ) ) goto Exit; /* check some data consistency */ - if ( shortDeltaCount > hvarData->regionCount ) + if ( shortDeltaCount > hvarData->regionIdxCount ) { FT_TRACE2(( "bad short count %d or region count %d\n", - shortDeltaCount, hvarData->regionCount )); + shortDeltaCount, hvarData->regionIdxCount )); error = FT_THROW( Invalid_File_Format ); goto Exit; } - if ( hvarData->regionCount > itemStore->regionCount ) + if ( hvarData->regionIdxCount > itemStore->regionCount ) { FT_TRACE2(( "inconsistent regionCount %d in varData[ %d ]\n", - hvarData->regionCount, i )); + hvarData->regionIdxCount, i )); error = FT_THROW( Invalid_File_Format ); goto Exit; } /* parse region indices */ - if ( FT_NEW_ARRAY( hvarData->regionIndices, hvarData->regionCount ) ) + if ( FT_NEW_ARRAY( hvarData->regionIndices, hvarData->regionIdxCount ) ) goto Exit; - for ( j=0; jregionCount; j++ ) + for ( j=0; jregionIdxCount; j++ ) { if ( FT_READ_USHORT( hvarData->regionIndices[j] ) ) goto Exit; - if ( hvarData->regionIndices[j] >= hvarData->regionCount ) + if ( hvarData->regionIndices[j] >= itemStore->regionCount ) { FT_TRACE2(( "bad region index %d\n", hvarData->regionIndices[j] )); error = FT_THROW( Invalid_File_Format ); @@ -584,15 +588,15 @@ } } - /* parse delta set */ - /* on input, deltas are ( shortDeltaCount + regionCount ) bytes each */ - /* on output, deltas are expanded to regionCount shorts each */ - if ( FT_NEW_ARRAY( hvarData->deltaSet, hvarData->regionCount * hvarData->itemCount ) ) + /* parse delta set */ + /* on input, deltas are ( shortDeltaCount + regionIdxCount ) bytes each */ + /* on output, deltas are expanded to regionIdxCount shorts each */ + if ( FT_NEW_ARRAY( hvarData->deltaSet, hvarData->regionIdxCount * hvarData->itemCount ) ) goto Exit; /* the delta set is stored as a 2-dimensional array of shorts */ /* sign-extend signed bytes to signed shorts */ - for ( j=0; jitemCount * hvarData->regionCount; ) + for ( j=0; jitemCount * hvarData->regionIdxCount; ) { for ( k=0; kdeltaSet[j] = delta; } - for ( ; kregionCount; k++,j++ ) + for ( ; kregionIdxCount; k++,j++ ) { /* read the (signed) byte deltas */ FT_Char delta; @@ -690,6 +694,7 @@ error = FT_Err_Ok; Exit: + FT_FREE( dataOffsetArray ); if ( error == FT_Err_Ok ) blend->hvar_checked = TRUE; } @@ -742,11 +747,11 @@ outerIndex = face->blend->hvar_table->widthMap.outerIndex[ gindex ]; innerIndex = face->blend->hvar_table->widthMap.innerIndex[ gindex ]; varData = &face->blend->hvar_table->itemStore.varData[ outerIndex ]; - deltaSet = &varData->deltaSet[ face->blend->hvar_table->itemStore.regionCount * innerIndex ]; + deltaSet = &varData->deltaSet[ varData->regionIdxCount * innerIndex ]; - /* see pseudo code from Font Variations Overview */ + /* see pseudo code from Font Variations Overview */ /* outer loop steps through master designs to be blended */ - for ( master=0; masterregionCount; master++ ) + for ( master=0; masterregionIdxCount; master++ ) { FT_UInt regionIndex = varData->regionIndices[ master ]; GX_AxisCoords axis = face->blend->hvar_table->itemStore.varRegionList[ regionIndex ].axisList; @@ -797,7 +802,6 @@ FT_TRACE4(( "]\n" )); /* apply the accumulated adjustment to the default to derive the interpolated value */ - /* TODO check rounding: *aadvance is short */ *aadvance += FT_fixedToInt( netAdjustment ); Exit: diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h index 956000c76..94300d962 100644 --- a/src/truetype/ttgxvar.h +++ b/src/truetype/ttgxvar.h @@ -74,32 +74,32 @@ FT_BEGIN_HEADER typedef struct GX_HVarData_ { FT_UInt itemCount; /* # delta sets per item */ - FT_UInt regionCount; /* # regions in this var data */ + FT_UInt regionIdxCount; /* # region indices in this data */ FT_UInt* regionIndices; /* array of regionCount indices */ /* these index the varRegionList */ FT_Short* deltaSet; /* array of itemCount deltas */ - /* use innerIndex for this array */ + /* use innerIndex for this array */ } GX_HVarDataRec, *GX_HVarData; - typedef struct GX_AxisCoords_ /* contribution of one axis to a region */ + typedef struct GX_AxisCoords_ /* contribution of one axis to a region */ { FT_Fixed startCoord; - FT_Fixed peakCoord; /* zero means no effect (factor = 1) */ + FT_Fixed peakCoord; /* zero means no effect (factor = 1) */ FT_Fixed endCoord; } GX_AxisCoordsRec, *GX_AxisCoords; typedef struct GX_HVarRegion_ { - GX_AxisCoords axisList; /* array of axisCount records */ + GX_AxisCoords axisList; /* array of axisCount records */ } GX_HVarRegionRec, *GX_HVarRegion; - typedef struct GX_HVStoreRec_ /* HVAR item variation store */ + typedef struct GX_HVStoreRec_ /* HVAR item variation store */ { FT_UInt dataCount; - GX_HVarData varData; /* array of dataCount records */ - /* use outerIndex for this array */ + GX_HVarData varData; /* array of dataCount records */ + /* use outerIndex for this array */ FT_UShort axisCount; - FT_UInt regionCount; /* total # regions defined */ + FT_UInt regionCount; /* total # regions defined */ GX_HVarRegion varRegionList; } GX_HVStoreRec, *GX_HVStore; @@ -107,16 +107,16 @@ FT_BEGIN_HEADER typedef struct GX_WidthMapRec_ { FT_UInt mapCount; - FT_UInt* outerIndex; /* indices to item var data */ - FT_UInt* innerIndex; /* indices to delta set */ + FT_UInt* outerIndex; /* indices to item var data */ + FT_UInt* innerIndex; /* indices to delta set */ } GX_WidthMapRec, *GX_WidthMap; typedef struct GX_HVarRec_ { - GX_HVStoreRec itemStore; /* Item Variation Store */ - GX_WidthMapRec widthMap; /* Advance Width Mapping */ - /* GX_LSBMap LsbMap; Not implemented */ - /* GX_RSBMap RsbMap; Not implemented */ + GX_HVStoreRec itemStore; /* Item Variation Store */ + GX_WidthMapRec widthMap; /* Advance Width Mapping */ + /* GX_LSBMap LsbMap; Not implemented */ + /* GX_RSBMap RsbMap; Not implemented */ } GX_HVarTableRec, *GX_HVarTable; /*************************************************************************/