• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from fontTools.ttLib.tables import otTables as ot
2from fontTools.colorLib.builder import buildColrV1
3from fontTools.colorLib.unbuilder import unbuildColrV1
4import pytest
5
6
7TEST_COLOR_GLYPHS = {
8    "glyph00010": {
9        "Format": int(ot.PaintFormat.PaintColrLayers),
10        "Layers": [
11            {
12                "Format": int(ot.PaintFormat.PaintGlyph),
13                "Paint": {
14                    "Format": int(ot.PaintFormat.PaintSolid),
15                    "PaletteIndex": 2,
16                    "Alpha": 0.5,
17                },
18                "Glyph": "glyph00011",
19            },
20            {
21                "Format": int(ot.PaintFormat.PaintGlyph),
22                "Paint": {
23                    "Format": int(ot.PaintFormat.PaintVarLinearGradient),
24                    "ColorLine": {
25                        "Extend": "repeat",
26                        "ColorStop": [
27                            {
28                                "StopOffset": 0.0,
29                                "PaletteIndex": 3,
30                                "Alpha": 1.0,
31                                "VarIndexBase": 0,
32                            },
33                            {
34                                "StopOffset": 0.5,
35                                "PaletteIndex": 4,
36                                "Alpha": 1.0,
37                                "VarIndexBase": 1,
38                            },
39                            {
40                                "StopOffset": 1.0,
41                                "PaletteIndex": 5,
42                                "Alpha": 1.0,
43                                "VarIndexBase": 2,
44                            },
45                        ],
46                    },
47                    "x0": 1,
48                    "y0": 2,
49                    "x1": -3,
50                    "y1": -4,
51                    "x2": 5,
52                    "y2": 6,
53                    "VarIndexBase": 0xFFFFFFFF,
54                },
55                "Glyph": "glyph00012",
56            },
57            {
58                "Format": int(ot.PaintFormat.PaintGlyph),
59                "Paint": {
60                    "Format": int(ot.PaintFormat.PaintVarTransform),
61                    "Paint": {
62                        "Format": int(ot.PaintFormat.PaintRadialGradient),
63                        "ColorLine": {
64                            "Extend": "pad",
65                            "ColorStop": [
66                                {
67                                    "StopOffset": 0,
68                                    "PaletteIndex": 6,
69                                    "Alpha": 1.0,
70                                },
71                                {
72                                    "StopOffset": 1.0,
73                                    "PaletteIndex": 7,
74                                    "Alpha": 0.4,
75                                },
76                            ],
77                        },
78                        "x0": 7,
79                        "y0": 8,
80                        "r0": 9,
81                        "x1": 10,
82                        "y1": 11,
83                        "r1": 12,
84                    },
85                    "Transform": {
86                        "xx": -13.0,
87                        "yx": 14.0,
88                        "xy": 15.0,
89                        "yy": -17.0,
90                        "dx": 18.0,
91                        "dy": 19.0,
92                        "VarIndexBase": 3,
93                    },
94                },
95                "Glyph": "glyph00013",
96            },
97            {
98                "Format": int(ot.PaintFormat.PaintVarTranslate),
99                "Paint": {
100                    "Format": int(ot.PaintFormat.PaintRotate),
101                    "Paint": {
102                        "Format": int(ot.PaintFormat.PaintVarSkew),
103                        "Paint": {
104                            "Format": int(ot.PaintFormat.PaintGlyph),
105                            "Paint": {
106                                "Format": int(ot.PaintFormat.PaintSolid),
107                                "PaletteIndex": 2,
108                                "Alpha": 0.5,
109                            },
110                            "Glyph": "glyph00011",
111                        },
112                        "xSkewAngle": -11.0,
113                        "ySkewAngle": 5.0,
114                        "VarIndexBase": 4,
115                    },
116                    "angle": 45.0,
117                },
118                "dx": 257.0,
119                "dy": 258.0,
120                "VarIndexBase": 5,
121            },
122        ],
123    },
124    "glyph00014": {
125        "Format": int(ot.PaintFormat.PaintComposite),
126        "SourcePaint": {
127            "Format": int(ot.PaintFormat.PaintColrGlyph),
128            "Glyph": "glyph00010",
129        },
130        "CompositeMode": "src_over",
131        "BackdropPaint": {
132            "Format": int(ot.PaintFormat.PaintTransform),
133            "Paint": {
134                "Format": int(ot.PaintFormat.PaintColrGlyph),
135                "Glyph": "glyph00010",
136            },
137            "Transform": {
138                "xx": 1.0,
139                "yx": 0.0,
140                "xy": 0.0,
141                "yy": 1.0,
142                "dx": 300.0,
143                "dy": 0.0,
144            },
145        },
146    },
147    "glyph00015": {
148        "Format": int(ot.PaintFormat.PaintGlyph),
149        "Paint": {
150            "Format": int(ot.PaintFormat.PaintSweepGradient),
151            "ColorLine": {
152                "Extend": "pad",
153                "ColorStop": [
154                    {
155                        "StopOffset": 0.0,
156                        "PaletteIndex": 3,
157                        "Alpha": 1.0,
158                    },
159                    {
160                        "StopOffset": 1.0,
161                        "PaletteIndex": 5,
162                        "Alpha": 1.0,
163                    },
164                ],
165            },
166            "centerX": 259,
167            "centerY": 300,
168            "startAngle": 45.0,
169            "endAngle": 135.0,
170        },
171        "Glyph": "glyph00011",
172    },
173    "glyph00016": {
174        "Format": int(ot.PaintFormat.PaintColrLayers),
175        "Layers": [
176            {
177                "Format": int(ot.PaintFormat.PaintGlyph),
178                "Paint": {
179                    "Format": int(ot.PaintFormat.PaintVarSolid),
180                    "PaletteIndex": 2,
181                    "Alpha": 0.5,
182                    "VarIndexBase": 6,
183                },
184                "Glyph": "glyph00011",
185            },
186            {
187                "Format": int(ot.PaintFormat.PaintGlyph),
188                "Paint": {
189                    "Format": int(ot.PaintFormat.PaintVarLinearGradient),
190                    "ColorLine": {
191                        "Extend": "repeat",
192                        "ColorStop": [
193                            {
194                                "StopOffset": 0.0,
195                                "PaletteIndex": 3,
196                                "Alpha": 1.0,
197                                "VarIndexBase": 7,
198                            },
199                            {
200                                "StopOffset": 0.5,
201                                "PaletteIndex": 4,
202                                "Alpha": 1.0,
203                                "VarIndexBase": 8,
204                            },
205                            {
206                                "StopOffset": 1.0,
207                                "PaletteIndex": 5,
208                                "Alpha": 1.0,
209                                "VarIndexBase": 9,
210                            },
211                        ],
212                    },
213                    "x0": 1,
214                    "y0": 2,
215                    "x1": -3,
216                    "y1": -4,
217                    "x2": 5,
218                    "y2": 6,
219                    "VarIndexBase": 0xFFFFFFFF,
220                },
221                "Glyph": "glyph00012",
222            },
223        ],
224    },
225    # When PaintColrLayers contains more than 255 layers, we build a tree
226    # of nested PaintColrLayers of max 255 items (NumLayers field is a uint8).
227    # Below we test that unbuildColrV1 restores a flat list of layers without
228    # nested PaintColrLayers.
229    "glyph00017": {
230        "Format": int(ot.PaintFormat.PaintColrLayers),
231        "Layers": [
232            {
233                "Format": int(ot.PaintFormat.PaintGlyph),
234                "Paint": {
235                    "Format": int(ot.PaintFormat.PaintSolid),
236                    "PaletteIndex": i,
237                    "Alpha": 1.0,
238                },
239                "Glyph": "glyph{str(18 + i).zfill(5)}",
240            }
241            for i in range(256)
242        ],
243    },
244}
245
246
247def test_unbuildColrV1():
248    layers, baseGlyphs = buildColrV1(TEST_COLOR_GLYPHS)
249    colorGlyphs = unbuildColrV1(layers, baseGlyphs)
250    assert colorGlyphs == TEST_COLOR_GLYPHS
251
252
253def test_unbuildColrV1_noLayers():
254    _, baseGlyphsV1 = buildColrV1(TEST_COLOR_GLYPHS)
255    # Just looking to see we don't crash
256    unbuildColrV1(None, baseGlyphsV1)
257