[sfnt] Handle fonts without layer list in 'COLR' v1.

'COLR' v1 fonts do not necessarily need to have a layer list; for
this reason, 'fontTools' recently started generating fonts in a way
that drops the layer list if there are no layers in it.  This
results in the layer list offset becoming zero, which FreeType
treated as an invalid table.  Fix that and handle the case for layer
list offset being 0.  This slightly changes how we need to calculate
the starting offset for paints.

* src/sfnt/ttcolr.c (tt_face_load_colr): Handle case of layer list
offset being zero without outright rejecting table.
This commit is contained in:
Dominik Röttsches 2021-06-29 20:51:32 +03:00 committed by Werner Lemberg
parent f27b4834b7
commit 0348c627b1
2 changed files with 39 additions and 13 deletions

View File

@ -1,3 +1,18 @@
2021-06-30 Dominik Röttsches <drott@chromium.org>
[sfnt] Handle fonts without layer list in 'COLR' v1.
'COLR' v1 fonts do not necessarily need to have a layer list; for
this reason, 'fontTools' recently started generating fonts in a way
that drops the layer list if there are no layers in it. This
results in the layer list offset becoming zero, which FreeType
treated as an invalid table. Fix that and handle the case for layer
list offset being 0. This slightly changes how we need to calculate
the starting offset for paints.
* src/sfnt/ttcolr.c (tt_face_load_colr): Handle case of layer list
offset being zero without outright rejecting table.
2021-06-30 Alexei Podtelezhnikov <apodtele@gmail.com>
* src/raster/ftraster.c (Render_Single_Pass): Simplify `band_stack'.

View File

@ -186,24 +186,35 @@
layer_offset_v1 = FT_NEXT_ULONG( p );
if ( !layer_offset_v1 || layer_offset_v1 >= table_size )
if ( layer_offset_v1 >= table_size )
goto InvalidTable;
p1 = (FT_Byte*)( table + layer_offset_v1 );
num_layers_v1 = FT_PEEK_ULONG( p1 );
if ( layer_offset_v1 )
{
p1 = (FT_Byte*)( table + layer_offset_v1 );
num_layers_v1 = FT_PEEK_ULONG( p1 );
if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE >
table_size - layer_offset_v1 )
goto InvalidTable;
if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE >
table_size - layer_offset_v1 )
goto InvalidTable;
colr->num_layers_v1 = num_layers_v1;
colr->layers_v1 = p1;
colr->num_layers_v1 = num_layers_v1;
colr->layers_v1 = p1;
colr->paints_start_v1 =
FT_MIN( colr->base_glyphs_v1 +
colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE,
colr->layers_v1 +
colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE );
colr->paints_start_v1 =
FT_MIN( colr->base_glyphs_v1 +
colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE,
colr->layers_v1 +
colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE );
}
else
{
colr->num_layers_v1 = 0;
colr->layers_v1 = 0;
colr->paints_start_v1 =
colr->base_glyphs_v1 +
colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE;
}
}
colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset );