From c612b2637fd952285c5a2efb6095787edc397249 Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Mon, 13 Jun 2022 16:50:01 +0100 Subject: [PATCH] colorLib.unbuilder: ensure unbuildColrV1 flattens nested PaintColrLayers --- Lib/fontTools/colorLib/unbuilder.py | 12 ++++++------ Tests/colorLib/unbuilder_test.py | 24 ++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Lib/fontTools/colorLib/unbuilder.py b/Lib/fontTools/colorLib/unbuilder.py index 034589071..ac243550b 100644 --- a/Lib/fontTools/colorLib/unbuilder.py +++ b/Lib/fontTools/colorLib/unbuilder.py @@ -13,12 +13,12 @@ def unbuildColrV1(layerList, baseGlyphList): } -def _flatten(lst): - for el in lst: - if isinstance(el, list): - yield from _flatten(el) +def _flatten_layers(lst): + for paint in lst: + if paint["Format"] == ot.PaintFormat.PaintColrLayers: + yield from _flatten_layers(paint["Layers"]) else: - yield el + yield paint class LayerListUnbuilder: @@ -41,7 +41,7 @@ class LayerListUnbuilder: assert source["Format"] == ot.PaintFormat.PaintColrLayers layers = list( - _flatten( + _flatten_layers( [ self.unbuildPaint(childPaint) for childPaint in self.layers[ diff --git a/Tests/colorLib/unbuilder_test.py b/Tests/colorLib/unbuilder_test.py index 354896805..fe5dc7d58 100644 --- a/Tests/colorLib/unbuilder_test.py +++ b/Tests/colorLib/unbuilder_test.py @@ -221,7 +221,26 @@ TEST_COLOR_GLYPHS = { "Glyph": "glyph00012", }, ], - } + }, + # When PaintColrLayers contains more than 255 layers, we build a tree + # of nested PaintColrLayers of max 255 items (NumLayers field is a uint8). + # Below we test that unbuildColrV1 restores a flat list of layers without + # nested PaintColrLayers. + "glyph00017": { + "Format": int(ot.PaintFormat.PaintColrLayers), + "Layers": [ + { + "Format": int(ot.PaintFormat.PaintGlyph), + "Paint": { + "Format": int(ot.PaintFormat.PaintSolid), + "PaletteIndex": i, + "Alpha": 1.0, + }, + "Glyph": "glyph{str(18 + i).zfill(5)}", + } + for i in range(256) + ], + }, } @@ -230,7 +249,8 @@ def test_unbuildColrV1(): colorGlyphs = unbuildColrV1(layers, baseGlyphs) assert colorGlyphs == TEST_COLOR_GLYPHS + def test_unbuildColrV1_noLayers(): _, baseGlyphsV1 = buildColrV1(TEST_COLOR_GLYPHS) # Just looking to see we don't crash - unbuildColrV1(None, baseGlyphsV1) \ No newline at end of file + unbuildColrV1(None, baseGlyphsV1)