diff --git a/Lib/fontTools/colorLib/builder.py b/Lib/fontTools/colorLib/builder.py index 5e7d8c6eb..d5084f456 100644 --- a/Lib/fontTools/colorLib/builder.py +++ b/Lib/fontTools/colorLib/builder.py @@ -542,6 +542,38 @@ class LayerV1ListBuilder: ot_paint.Paint = self.buildPaint(paint) return ot_paint + def buildPaintRotate( + self, + paint: _PaintInput, + angle: _ScalarInput, + centerX: _ScalarInput, + centerY: _ScalarInput, + ) -> ot.Paint: + ot_paint = ot.Paint() + ot_paint.Format = int(ot.Paint.Format.PaintRotate) + ot_paint.Paint = self.buildPaint(paint) + ot_paint.angle = _to_variable_f16dot16_float(angle) + ot_paint.centerX = _to_variable_f16dot16_float(centerX) + ot_paint.centerY = _to_variable_f16dot16_float(centerY) + return ot_paint + + def buildPaintSkew( + self, + paint: _PaintInput, + xSkewAngle: _ScalarInput, + ySkewAngle: _ScalarInput, + centerX: _ScalarInput, + centerY: _ScalarInput, + ) -> ot.Paint: + ot_paint = ot.Paint() + ot_paint.Format = int(ot.Paint.Format.PaintSkew) + ot_paint.Paint = self.buildPaint(paint) + ot_paint.xSkewAngle = _to_variable_f16dot16_float(xSkewAngle) + ot_paint.ySkewAngle = _to_variable_f16dot16_float(ySkewAngle) + ot_paint.centerX = _to_variable_f16dot16_float(centerX) + ot_paint.centerY = _to_variable_f16dot16_float(centerY) + return ot_paint + def buildPaintComposite( self, mode: _CompositeInput, diff --git a/Lib/fontTools/ttLib/tables/otData.py b/Lib/fontTools/ttLib/tables/otData.py index f260a542a..776cf75ba 100755 --- a/Lib/fontTools/ttLib/tables/otData.py +++ b/Lib/fontTools/ttLib/tables/otData.py @@ -1664,6 +1664,23 @@ otData = [ ]), ('PaintFormat8', [ + ('uint8', 'PaintFormat', None, None, 'Format identifier-format = 8'), + ('Offset24', 'Paint', None, None, 'Offset (from beginning of PaintRotate table) to Paint subtable.'), + ('VarFixed', 'angle', None, None, ''), + ('VarFixed', 'centerX', None, None, ''), + ('VarFixed', 'centerY', None, None, ''), + ]), + + ('PaintFormat9', [ + ('uint8', 'PaintFormat', None, None, 'Format identifier-format = 9'), + ('Offset24', 'Paint', None, None, 'Offset (from beginning of PaintRotate table) to Paint subtable.'), + ('VarFixed', 'xSkewAngle', None, None, ''), + ('VarFixed', 'ySkewAngle', None, None, ''), + ('VarFixed', 'centerX', None, None, ''), + ('VarFixed', 'centerY', None, None, ''), + ]), + + ('PaintFormat10', [ ('uint8', 'PaintFormat', None, None, 'Format identifier-format = 8'), ('LOffset24To(Paint)', 'SourcePaint', None, None, 'Offset (from beginning of PaintComposite table) to source Paint subtable.'), ('CompositeMode', 'CompositeMode', None, None, 'A CompositeMode enumeration value.'), diff --git a/Lib/fontTools/ttLib/tables/otTables.py b/Lib/fontTools/ttLib/tables/otTables.py index 7a04d5aa1..c4208a55f 100644 --- a/Lib/fontTools/ttLib/tables/otTables.py +++ b/Lib/fontTools/ttLib/tables/otTables.py @@ -1334,7 +1334,9 @@ class Paint(getFormatSwitchingBaseTableClass("uint8")): PaintGlyph = 5 PaintColrGlyph = 6 PaintTransform = 7 - PaintComposite = 8 + PaintRotate = 8 + PaintSkew = 9 + PaintComposite = 10 def getFormatName(self): try: diff --git a/Tests/colorLib/builder_test.py b/Tests/colorLib/builder_test.py index 86b5f9e92..152e16e08 100644 --- a/Tests/colorLib/builder_test.py +++ b/Tests/colorLib/builder_test.py @@ -544,7 +544,7 @@ def test_buildPaintComposite(): composite = layerBuilder.buildPaintComposite( mode=ot.CompositeMode.SRC_OVER, source={ - "format": 8, + "format": 10, "mode": "src_over", "source": {"format": 5, "glyph": "c", "paint": 2}, "backdrop": {"format": 5, "glyph": "b", "paint": 1}, @@ -574,6 +574,44 @@ def test_buildPaintComposite(): assert composite.BackdropPaint.Paint.Color.PaletteIndex == 0 +def test_buildPaintRotate(): + layerBuilder = LayerV1ListBuilder() + paint = layerBuilder.buildPaintRotate( + paint=layerBuilder.buildPaintGlyph( + "a", layerBuilder.buildPaintSolid(paletteIndex=0, alpha=1.0) + ), + angle=15, + centerX=127, + centerY=129, + ) + + assert paint.Format == ot.Paint.Format.PaintRotate + assert paint.Paint.Format == ot.Paint.Format.PaintGlyph + assert paint.angle.value == 15 + assert paint.centerX.value == 127 + assert paint.centerY.value == 129 + + +def test_buildPaintRotate(): + layerBuilder = LayerV1ListBuilder() + paint = layerBuilder.buildPaintSkew( + paint=layerBuilder.buildPaintGlyph( + "a", layerBuilder.buildPaintSolid(paletteIndex=0, alpha=1.0) + ), + xSkewAngle=15, + ySkewAngle=42, + centerX=127, + centerY=129, + ) + + assert paint.Format == ot.Paint.Format.PaintSkew + assert paint.Paint.Format == ot.Paint.Format.PaintGlyph + assert paint.xSkewAngle.value == 15 + assert paint.ySkewAngle.value == 42 + assert paint.centerX.value == 127 + assert paint.centerY.value == 129 + + def test_buildColrV1(): colorGlyphs = { "a": [("b", 0), ("c", 1)],