From f98c860ff2e3109f32c7c65dc9e2a28a6e44a5da Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Fri, 24 Jun 2022 18:16:28 +0100 Subject: [PATCH] Start adding Tests/varLib/merger_test.py for COLRVariationMerger --- Tests/varLib/merger_test.py | 556 ++++++++++++++++++++++++++++++++++++ 1 file changed, 556 insertions(+) create mode 100644 Tests/varLib/merger_test.py diff --git a/Tests/varLib/merger_test.py b/Tests/varLib/merger_test.py new file mode 100644 index 000000000..2c57b510c --- /dev/null +++ b/Tests/varLib/merger_test.py @@ -0,0 +1,556 @@ +from copy import deepcopy +import string +from fontTools.colorLib.builder import LayerListBuilder +from fontTools.misc.testTools import getXML +from fontTools.varLib.merger import COLRVariationMerger +from fontTools.varLib.models import VariationModel +from fontTools.ttLib import TTFont +from fontTools.ttLib.tables import otTables as ot +from fontTools.ttLib.tables.otBase import OTTableReader, OTTableWriter +import pytest + + +NO_VARIATION_INDEX = ot.NO_VARIATION_INDEX + + +def dump_xml(table, ttFont=None): + xml = getXML(table.toXML, ttFont) + print("[") + for line in xml: + print(f" {line!r},") + print("]") + return xml + + +def compile_decompile(table, ttFont): + writer = OTTableWriter(tableTag="COLR") + table.compile(writer, ttFont) + data = writer.getAllData() + + reader = OTTableReader(data, tableTag="COLR") + table2 = table.__class__() + table2.decompile(reader, ttFont) + + return table2 + + +@pytest.fixture +def ttFont(): + font = TTFont() + font.setGlyphOrder([".notdef"] + list(string.ascii_letters)) + return font + + +def build_paint(data): + return LayerListBuilder().buildPaint(data) + + +class COLRVariationMergerTest: + @pytest.mark.parametrize( + "paints, expected_xml, expected_varIdxes", + [ + pytest.param( + [ + { + "Format": int(ot.PaintFormat.PaintSolid), + "PaletteIndex": 0, + "Alpha": 1.0, + }, + { + "Format": int(ot.PaintFormat.PaintSolid), + "PaletteIndex": 0, + "Alpha": 1.0, + }, + ], + [ + '', + ' ', + ' ', + "", + ], + [], + id="solid-same", + ), + pytest.param( + [ + { + "Format": int(ot.PaintFormat.PaintSolid), + "PaletteIndex": 0, + "Alpha": 1.0, + }, + { + "Format": int(ot.PaintFormat.PaintSolid), + "PaletteIndex": 0, + "Alpha": 0.5, + }, + ], + [ + '', + ' ', + ' ', + ' ', + "", + ], + [0], + id="solid-alpha", + ), + pytest.param( + [ + { + "Format": int(ot.PaintFormat.PaintLinearGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + {"StopOffset": 0.0, "PaletteIndex": 0, "Alpha": 1.0}, + {"StopOffset": 1.0, "PaletteIndex": 1, "Alpha": 1.0}, + ], + }, + "x0": 0, + "y0": 0, + "x1": 1, + "y1": 1, + "x2": 2, + "y2": 2, + }, + { + "Format": int(ot.PaintFormat.PaintLinearGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + {"StopOffset": 0.1, "PaletteIndex": 0, "Alpha": 1.0}, + {"StopOffset": 0.9, "PaletteIndex": 1, "Alpha": 1.0}, + ], + }, + "x0": 0, + "y0": 0, + "x1": 1, + "y1": 1, + "x2": 2, + "y2": 2, + }, + ], + [ + '', + " ", + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + "", + ], + [0, NO_VARIATION_INDEX, 1, NO_VARIATION_INDEX], + id="linear_grad-stop-offsets", + ), + pytest.param( + [ + { + "Format": int(ot.PaintFormat.PaintLinearGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + {"StopOffset": 0.0, "PaletteIndex": 0, "Alpha": 1.0}, + {"StopOffset": 1.0, "PaletteIndex": 1, "Alpha": 1.0}, + ], + }, + "x0": 0, + "y0": 0, + "x1": 1, + "y1": 1, + "x2": 2, + "y2": 2, + }, + { + "Format": int(ot.PaintFormat.PaintLinearGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + {"StopOffset": 0.0, "PaletteIndex": 0, "Alpha": 0.5}, + {"StopOffset": 1.0, "PaletteIndex": 1, "Alpha": 1.0}, + ], + }, + "x0": 0, + "y0": 0, + "x1": 1, + "y1": 1, + "x2": 2, + "y2": 2, + }, + ], + [ + '', + " ", + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + " ", + " ", + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + "", + ], + [NO_VARIATION_INDEX, 0], + id="linear_grad-stop[0].alpha", + ), + pytest.param( + [ + { + "Format": int(ot.PaintFormat.PaintSweepGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.REPEAT), + "ColorStop": [ + {"StopOffset": 0.4, "PaletteIndex": 0, "Alpha": 1.0}, + {"StopOffset": 0.6, "PaletteIndex": 1, "Alpha": 1.0}, + ], + }, + "centerX": 0, + "centerY": 0, + "startAngle": 0, + "endAngle": 180.0, + }, + { + "Format": int(ot.PaintFormat.PaintSweepGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.REPEAT), + "ColorStop": [ + {"StopOffset": 0.4, "PaletteIndex": 0, "Alpha": 1.0}, + {"StopOffset": 0.6, "PaletteIndex": 1, "Alpha": 1.0}, + ], + }, + "centerX": 0, + "centerY": 0, + "startAngle": 90.0, + "endAngle": 180.0, + }, + ], + [ + '', + " ", + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + " ", + " ", + ' ', + ' ', + ' ', + ' ', + " ", + " ", + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + "", + ], + [NO_VARIATION_INDEX, NO_VARIATION_INDEX, 0, NO_VARIATION_INDEX], + id="sweep_grad-startAngle", + ), + pytest.param( + [ + { + "Format": int(ot.PaintFormat.PaintLinearGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + {"StopOffset": 0.0, "PaletteIndex": 0, "Alpha": 1.0}, + {"StopOffset": 1.0, "PaletteIndex": 1, "Alpha": 1.0}, + ], + }, + "x0": 0, + "y0": 0, + "x1": 1, + "y1": 1, + "x2": 2, + "y2": 2, + }, + { + "Format": int(ot.PaintFormat.PaintLinearGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + {"StopOffset": -0.5, "PaletteIndex": 0, "Alpha": 1.0}, + {"StopOffset": 1.0, "PaletteIndex": 1, "Alpha": 1.0}, + ], + }, + "x0": 0, + "y0": 0, + "x1": 1, + "y1": 1, + "x2": 2, + "y2": -200, + }, + ], + [ + '', + " ", + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + " ", + " ", + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + "", + ], + [ + 0, + NO_VARIATION_INDEX, + NO_VARIATION_INDEX, + NO_VARIATION_INDEX, + NO_VARIATION_INDEX, + NO_VARIATION_INDEX, + NO_VARIATION_INDEX, + 1, + ], + id="linear_grad-stop[0].offset-y2", + ), + pytest.param( + [ + { + "Format": int(ot.PaintFormat.PaintRadialGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + {"StopOffset": 0.0, "PaletteIndex": 0, "Alpha": 1.0}, + {"StopOffset": 1.0, "PaletteIndex": 1, "Alpha": 1.0}, + ], + }, + "x0": 0, + "y0": 0, + "r0": 0, + "x1": 1, + "y1": 1, + "r1": 1, + }, + { + "Format": int(ot.PaintFormat.PaintRadialGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + {"StopOffset": 0.1, "PaletteIndex": 0, "Alpha": 0.6}, + {"StopOffset": 0.9, "PaletteIndex": 1, "Alpha": 0.7}, + ], + }, + "x0": -1, + "y0": -2, + "r0": 3, + "x1": -4, + "y1": -5, + "r1": 6, + }, + ], + [ + '', + " ", + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + "", + ], + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + id="radial_grad-all-different", + ), + pytest.param( + [ + { + "Format": int(ot.PaintFormat.PaintTransform), + "Paint": { + "Format": int(ot.PaintFormat.PaintRadialGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + { + "StopOffset": 0.0, + "PaletteIndex": 0, + "Alpha": 1.0, + }, + { + "StopOffset": 1.0, + "PaletteIndex": 1, + "Alpha": 1.0, + }, + ], + }, + "x0": 0, + "y0": 0, + "r0": 0, + "x1": 1, + "y1": 1, + "r1": 1, + }, + "Transform": { + "xx": 1.0, + "xy": 0.0, + "yx": 0.0, + "yy": 1.0, + "dx": 0.0, + "dy": 0.0, + }, + }, + { + "Format": int(ot.PaintFormat.PaintTransform), + "Paint": { + "Format": int(ot.PaintFormat.PaintRadialGradient), + "ColorLine": { + "Extend": int(ot.ExtendMode.PAD), + "ColorStop": [ + { + "StopOffset": 0.0, + "PaletteIndex": 0, + "Alpha": 1.0, + }, + { + "StopOffset": 1.0, + "PaletteIndex": 1, + "Alpha": 1.0, + }, + ], + }, + "x0": 0, + "y0": 0, + "r0": 0, + "x1": 1, + "y1": 1, + "r1": 1, + }, + "Transform": { + "xx": 1.0, + "xy": 0.0, + "yx": 0.0, + "yy": 0.5, + "dx": 0.0, + "dy": -100.0, + }, + }, + ], + [ + '', + ' ', + " ", + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + " ", + ' ', + ' ', + ' ', + ' ', + " ", + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + " ", + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + " ", + "", + ], + [ + NO_VARIATION_INDEX, + NO_VARIATION_INDEX, + NO_VARIATION_INDEX, + 0, + NO_VARIATION_INDEX, + 1, + ], + id="transform-yy-dy", + ), + ], + ) + def test_merge_Paint(self, paints, ttFont, expected_xml, expected_varIdxes): + paints = [build_paint(p) for p in paints] + out = deepcopy(paints[0]) + + model = VariationModel([{}, {"ZZZZ": 1.0}]) + merger = COLRVariationMerger(model, ["ZZZZ"], ttFont) + + merger.mergeThings(out, paints) + + assert compile_decompile(out, ttFont) == out + assert dump_xml(out, ttFont) == expected_xml + assert merger.varIdxes == expected_varIdxes