[truetype] Updates for the forthcoming OpenType 1.9 standard (1/2).

This is in preparation for implementing `DeltaSetIndexMap` format 1, which
is used by `COLR` v1 tables, and which allows 32bit indices.

  https://docs.microsoft.com/en-us/typography/opentype/otspec190/delta/otvarcommonformats_delta.html

* src/truetype/ttgxvar.h (GX_DeltaSetIdxMapRec): Change type of `mapCount`
to `FT_ULong`.

* src/truetype/ttgxvar.c (ft_var_load_delta_set_index_mapping): Add argument
for passing the table size; update caller.
Implement new format.
This commit is contained in:
Werner Lemberg 2021-11-13 14:41:40 +01:00
parent d31bafcb9c
commit 93e6b3e8e9
2 changed files with 49 additions and 19 deletions

View File

@ -664,37 +664,66 @@
ft_var_load_delta_set_index_mapping( TT_Face face, ft_var_load_delta_set_index_mapping( TT_Face face,
FT_ULong offset, FT_ULong offset,
GX_DeltaSetIdxMap map, GX_DeltaSetIdxMap map,
GX_ItemVarStore itemStore ) GX_ItemVarStore itemStore,
FT_ULong table_len )
{ {
FT_Stream stream = FT_FACE_STREAM( face ); FT_Stream stream = FT_FACE_STREAM( face );
FT_Memory memory = stream->memory; FT_Memory memory = stream->memory;
FT_Error error; FT_Error error;
FT_UShort format; FT_Byte format;
FT_UInt entrySize; FT_Byte entryFormat;
FT_UInt innerBitCount; FT_UInt entrySize;
FT_UInt innerIndexMask; FT_UInt innerBitCount;
FT_UInt i, j; FT_UInt innerIndexMask;
FT_ULong i;
FT_UInt j;
if ( FT_STREAM_SEEK( offset ) || if ( FT_STREAM_SEEK( offset ) ||
FT_READ_USHORT( format ) || FT_READ_BYTE( format ) ||
FT_READ_USHORT( map->mapCount ) ) FT_READ_BYTE( entryFormat ) )
goto Exit; goto Exit;
if ( format & 0xFFC0 ) if ( format == 0 )
{
if ( FT_READ_USHORT( map->mapCount ) )
goto Exit;
}
else if ( format == 1 ) /* new in OpenType 1.9 */
{
if ( FT_READ_ULONG( map->mapCount ) )
goto Exit;
}
else
{ {
FT_TRACE2(( "bad map format %d\n", format )); FT_TRACE2(( "bad map format %d\n", format ));
error = FT_THROW( Invalid_Table ); error = FT_THROW( Invalid_Table );
goto Exit; goto Exit;
} }
if ( entryFormat & 0xC0 )
{
FT_TRACE2(( "bad entry format %d\n", format ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
/* bytes per entry: 1, 2, 3, or 4 */ /* bytes per entry: 1, 2, 3, or 4 */
entrySize = ( ( format & 0x0030 ) >> 4 ) + 1; entrySize = ( ( entryFormat & 0x30 ) >> 4 ) + 1;
innerBitCount = ( format & 0x000F ) + 1; innerBitCount = ( entryFormat & 0x0F ) + 1;
innerIndexMask = ( 1 << innerBitCount ) - 1; innerIndexMask = ( 1 << innerBitCount ) - 1;
/* rough sanity check */
if ( map->mapCount * entrySize > table_len )
{
FT_TRACE1(( "ft_var_load_delta_set_index_mapping:"
" invalid number of delta-set index mappings\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
if ( FT_NEW_ARRAY( map->innerIndex, map->mapCount ) ) if ( FT_NEW_ARRAY( map->innerIndex, map->mapCount ) )
goto Exit; goto Exit;
@ -723,7 +752,7 @@
if ( outerIndex >= itemStore->dataCount ) if ( outerIndex >= itemStore->dataCount )
{ {
FT_TRACE2(( "outerIndex[%d] == %d out of range\n", FT_TRACE2(( "outerIndex[%ld] == %d out of range\n",
i, i,
outerIndex )); outerIndex ));
error = FT_THROW( Invalid_Table ); error = FT_THROW( Invalid_Table );
@ -736,7 +765,7 @@
if ( innerIndex >= itemStore->varData[outerIndex].itemCount ) if ( innerIndex >= itemStore->varData[outerIndex].itemCount )
{ {
FT_TRACE2(( "innerIndex[%d] == %d out of range\n", FT_TRACE2(( "innerIndex[%ld] == %d out of range\n",
i, i,
innerIndex )); innerIndex ));
error = FT_THROW( Invalid_Table ); error = FT_THROW( Invalid_Table );
@ -861,7 +890,8 @@
face, face,
table_offset + widthMap_offset, table_offset + widthMap_offset,
&table->widthMap, &table->widthMap,
&table->itemStore ); &table->itemStore,
table_len );
if ( error ) if ( error )
goto Exit; goto Exit;
} }

View File

@ -106,9 +106,9 @@ FT_BEGIN_HEADER
typedef struct GX_DeltaSetIdxMapRec_ typedef struct GX_DeltaSetIdxMapRec_
{ {
FT_UInt mapCount; FT_ULong mapCount;
FT_UInt* outerIndex; /* indices to item var data */ FT_UInt* outerIndex; /* indices to item var data */
FT_UInt* innerIndex; /* indices to delta set */ FT_UInt* innerIndex; /* indices to delta set */
} GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap; } GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap;