1from fontTools import ttLib 2from fontTools.misc.testTools import getXML, parseXML 3from fontTools.ttLib.tables.C_O_L_R_ import table_C_O_L_R_ 4 5import binascii 6import pytest 7 8 9COLR_V0_SAMPLE = ( 10 (b"\x00\x00", "Version (0)"), 11 (b"\x00\x01", "BaseGlyphRecordCount (1)"), 12 ( 13 b"\x00\x00\x00\x0e", 14 "Offset to BaseGlyphRecordArray from beginning of table (14)", 15 ), 16 (b"\x00\x00\x00\x14", "Offset to LayerRecordArray from beginning of table (20)"), 17 (b"\x00\x03", "LayerRecordCount (3)"), 18 (b"\x00\x06", "BaseGlyphRecord[0].BaseGlyph (6)"), 19 (b"\x00\x00", "BaseGlyphRecord[0].FirstLayerIndex (0)"), 20 (b"\x00\x03", "BaseGlyphRecord[0].NumLayers (3)"), 21 (b"\x00\x07", "LayerRecord[0].LayerGlyph (7)"), 22 (b"\x00\x00", "LayerRecord[0].PaletteIndex (0)"), 23 (b"\x00\x08", "LayerRecord[1].LayerGlyph (8)"), 24 (b"\x00\x01", "LayerRecord[1].PaletteIndex (1)"), 25 (b"\x00\t", "LayerRecord[2].LayerGlyph (9)"), 26 (b"\x00\x02", "LayerRecord[3].PaletteIndex (2)"), 27) 28 29COLR_V0_DATA = b"".join(t[0] for t in COLR_V0_SAMPLE) 30 31 32COLR_V0_XML = [ 33 '<version value="0"/>', 34 '<ColorGlyph name="glyph00006">', 35 ' <layer colorID="0" name="glyph00007"/>', 36 ' <layer colorID="1" name="glyph00008"/>', 37 ' <layer colorID="2" name="glyph00009"/>', 38 "</ColorGlyph>", 39] 40 41 42def dump(table, ttFont=None): 43 print("\n".join(getXML(table.toXML, ttFont))) 44 45 46def diff_binary_fragments(font_bytes, expected_fragments): 47 pos = 0 48 prev_desc = "" 49 errors = 0 50 for expected_bytes, description in expected_fragments: 51 actual_bytes = font_bytes[pos : pos + len(expected_bytes)] 52 if actual_bytes != expected_bytes: 53 print( 54 f'{description} (previous "{prev_desc}", actual_bytes: {"".join("%02x" % v for v in actual_bytes)} bytes: {str(font_bytes[pos:pos+16])}' 55 ) 56 errors += 1 57 pos += len(expected_bytes) 58 prev_desc = description 59 assert errors == 0 60 assert pos == len( 61 font_bytes 62 ), f"Leftover font bytes, used {pos} of {len(font_bytes)}" 63 64 65@pytest.fixture 66def font(): 67 font = ttLib.TTFont() 68 font.setGlyphOrder(["glyph%05d" % i for i in range(30)]) 69 return font 70 71 72class COLR_V0_Test(object): 73 def test_decompile_and_compile(self, font): 74 colr = table_C_O_L_R_() 75 colr.decompile(COLR_V0_DATA, font) 76 diff_binary_fragments(colr.compile(font), COLR_V0_SAMPLE) 77 78 def test_decompile_and_dump_xml(self, font): 79 colr = table_C_O_L_R_() 80 colr.decompile(COLR_V0_DATA, font) 81 82 dump(colr, font) 83 assert getXML(colr.toXML, font) == COLR_V0_XML 84 85 def test_load_from_xml_and_compile(self, font): 86 colr = table_C_O_L_R_() 87 for name, attrs, content in parseXML(COLR_V0_XML): 88 colr.fromXML(name, attrs, content, font) 89 90 diff_binary_fragments(colr.compile(font), COLR_V0_SAMPLE) 91 92 def test_round_trip_xml(self, font): 93 colr = table_C_O_L_R_() 94 for name, attrs, content in parseXML(COLR_V0_XML): 95 colr.fromXML(name, attrs, content, font) 96 compiled = colr.compile(font) 97 98 colr = table_C_O_L_R_() 99 colr.decompile(compiled, font) 100 assert getXML(colr.toXML, font) == COLR_V0_XML 101 102 103COLR_V1_SAMPLE = ( 104 (b"\x00\x01", "Version (1)"), 105 (b"\x00\x01", "BaseGlyphRecordCount (1)"), 106 ( 107 b"\x00\x00\x00\x22", 108 "Offset to BaseGlyphRecordArray from beginning of table (34)", 109 ), 110 (b"\x00\x00\x00\x28", "Offset to LayerRecordArray from beginning of table (40)"), 111 (b"\x00\x03", "LayerRecordCount (3)"), 112 (b"\x00\x00\x00\x34", "Offset to BaseGlyphList from beginning of table (52)"), 113 (b"\x00\x00\x00\x9f", "Offset to LayerList from beginning of table (159)"), 114 (b"\x00\x00\x01\x62", "Offset to ClipList (354)"), 115 (b"\x00\x00\x00\x00", "Offset to DeltaSetIndexMap (NULL)"), 116 (b"\x00\x00\x00\x00", "Offset to VarStore (NULL)"), 117 (b"\x00\x06", "BaseGlyphRecord[0].BaseGlyph (6)"), 118 (b"\x00\x00", "BaseGlyphRecord[0].FirstLayerIndex (0)"), 119 (b"\x00\x03", "BaseGlyphRecord[0].NumLayers (3)"), 120 (b"\x00\x07", "LayerRecord[0].LayerGlyph (7)"), 121 (b"\x00\x00", "LayerRecord[0].PaletteIndex (0)"), 122 (b"\x00\x08", "LayerRecord[1].LayerGlyph (8)"), 123 (b"\x00\x01", "LayerRecord[1].PaletteIndex (1)"), 124 (b"\x00\t", "LayerRecord[2].LayerGlyph (9)"), 125 (b"\x00\x02", "LayerRecord[2].PaletteIndex (2)"), 126 # BaseGlyphList 127 (b"\x00\x00\x00\x03", "BaseGlyphList.BaseGlyphCount (3)"), 128 (b"\x00\n", "BaseGlyphList.BaseGlyphPaintRecord[0].BaseGlyph (10)"), 129 ( 130 b"\x00\x00\x00\x16", 131 "Offset to Paint table from beginning of BaseGlyphList (22)", 132 ), 133 (b"\x00\x0e", "BaseGlyphList.BaseGlyphPaintRecord[1].BaseGlyph (14)"), 134 ( 135 b"\x00\x00\x00\x1c", 136 "Offset to Paint table from beginning of BaseGlyphList (28)", 137 ), 138 (b"\x00\x0f", "BaseGlyphList.BaseGlyphPaintRecord[2].BaseGlyph (15)"), 139 ( 140 b"\x00\x00\x00\x4a", 141 "Offset to Paint table from beginning of BaseGlyphList (74)", 142 ), 143 # BaseGlyphPaintRecord[0] 144 (b"\x01", "BaseGlyphPaintRecord[0].Paint.Format (1)"), 145 (b"\x04", "BaseGlyphPaintRecord[0].Paint.NumLayers (4)"), 146 (b"\x00\x00\x00\x00", "BaseGlyphPaintRecord[0].Paint.FirstLayerIndex (0)"), 147 # BaseGlyphPaintRecord[1] 148 (b"\x20", "BaseGlyphPaintRecord[1].Paint.Format (32)"), 149 (b"\x00\x00\x0f", "Offset to SourcePaint from beginning of PaintComposite (15)"), 150 (b"\x03", "BaseGlyphPaintRecord[1].Paint.CompositeMode [SRC_OVER] (3)"), 151 (b"\x00\x00\x08", "Offset to BackdropPaint from beginning of PaintComposite (8)"), 152 (b"\x0d", "BaseGlyphPaintRecord[1].Paint.BackdropPaint.Format (13)"), 153 (b"\x00\x00\x07", "Offset to Paint from beginning of PaintVarTransform (7)"), 154 (b"\x00\x00\x0a", "Offset to VarAffine2x3 from beginning of PaintVarTransform (10)"), 155 (b"\x0b", "BaseGlyphPaintRecord[1].Paint.BackdropPaint.Format (11)"), 156 (b"\x00\x0a", "BaseGlyphPaintRecord[1].Paint.BackdropPaint.Glyph (10)"), 157 (b"\x00\x01\x00\x00", "VarAffine2x3.xx (1.0)"), 158 (b"\x00\x00\x00\x00", "VarAffine2x3.xy (0.0)"), 159 (b"\x00\x00\x00\x00", "VarAffine2x3.yx (0.0)"), 160 (b"\x00\x01\x00\x00", "VarAffine2x3.yy (1.0)"), 161 (b"\x01\x2c\x00\x00", "VarAffine2x3.dx (300.0)"), 162 (b"\x00\x00\x00\x00", "VarAffine2x3.dy (0.0)"), 163 (b"\x00\x00\x00\x00", "VarIndexBase (0)"), 164 (b"\x0a", "BaseGlyphPaintRecord[1].Paint.SourcePaint.Format (10)"), 165 (b"\x00\x00\x06", "Offset to Paint subtable from beginning of PaintGlyph (6)"), 166 (b"\x00\x0b", "BaseGlyphPaintRecord[1].Paint.SourcePaint.Glyph (11)"), 167 (b"\x08", "BaseGlyphPaintRecord[1].Paint.SourcePaint.Paint.Format (8)"), 168 (b"\x00\x00\x0c", "Offset to ColorLine from beginning of PaintSweepGradient (12)"), 169 (b"\x01\x03", "centerX (259)"), 170 (b"\x01\x2c", "centerY (300)"), 171 (b"\x10\x00", "startAngle (0.25)"), 172 (b"\x30\x00", "endAngle (0.75)"), 173 (b"\x00", "ColorLine.Extend (0; pad)"), 174 (b"\x00\x02", "ColorLine.StopCount (2)"), 175 (b"\x00\x00", "ColorLine.ColorStop[0].StopOffset (0.0)"), 176 (b"\x00\x03", "ColorLine.ColorStop[0].PaletteIndex (3)"), 177 (b"@\x00", "ColorLine.ColorStop[0].Alpha (1.0)"), 178 (b"@\x00", "ColorLine.ColorStop[1].StopOffset (1.0)"), 179 (b"\x00\x05", "ColorLine.ColorStop[1].PaletteIndex (5)"), 180 (b"@\x00", "ColorLine.ColorStop[1].Alpha (1.0)"), 181 # LayerList 182 (b"\x00\x00\x00\x04", "LayerList.LayerCount (4)"), 183 ( 184 b"\x00\x00\x00\x14", 185 "First Offset to Paint table from beginning of LayerList (20)", 186 ), 187 ( 188 b"\x00\x00\x00\x23", 189 "Second Offset to Paint table from beginning of LayerList (35)", 190 ), 191 ( 192 b"\x00\x00\x00\x4e", 193 "Third Offset to Paint table from beginning of LayerList (78)", 194 ), 195 ( 196 b"\x00\x00\x00\x9e", 197 "Fourth Offset to Paint table from beginning of LayerList (158)", 198 ), 199 # BaseGlyphPaintRecord[2] 200 (b"\x0a", "BaseGlyphPaintRecord[2].Paint.Format (10)"), 201 (b"\x00\x00\x06", "Offset to Paint subtable from beginning of PaintGlyph (6)"), 202 (b"\x00\x0b", "BaseGlyphPaintRecord[2].Paint.Glyph (11)"), 203 # PaintVarSolid 204 (b"\x03", "LayerList.Paint[0].Paint.Format (3)"), 205 (b"\x00\x02", "Paint.PaletteIndex (2)"), 206 (b" \x00", "Paint.Alpha.value (0.5)"), 207 (b"\x00\x00\x00\x06", "VarIndexBase (6)"), 208 # PaintGlyph glyph00012 209 (b"\x0a", "LayerList.Paint[1].Format (10)"), 210 (b"\x00\x00\x06", "Offset to Paint subtable from beginning of PaintGlyph (6)"), 211 (b"\x00\x0c", "LayerList.Paint[1].Glyph (glyph00012)"), 212 (b"\x04", "LayerList.Paint[1].Paint.Format (4)"), 213 (b"\x00\x00\x10", "Offset to ColorLine from beginning of PaintLinearGradient (16)"), 214 (b"\x00\x01", "Paint.x0 (1)"), 215 (b"\x00\x02", "Paint.y0 (2)"), 216 (b"\xff\xfd", "Paint.x1 (-3)"), 217 (b"\xff\xfc", "Paint.y1 (-4)"), 218 (b"\x00\x05", "Paint.x2 (5)"), 219 (b"\x00\x06", "Paint.y2 (6)"), 220 (b"\x01", "ColorLine.Extend (1; repeat)"), 221 (b"\x00\x03", "ColorLine.StopCount (3)"), 222 (b"\x00\x00", "ColorLine.ColorStop[0].StopOffset (0.0)"), 223 (b"\x00\x03", "ColorLine.ColorStop[0].PaletteIndex (3)"), 224 (b"@\x00", "ColorLine.ColorStop[0].Alpha (1.0)"), 225 (b" \x00", "ColorLine.ColorStop[1].StopOffset (0.5)"), 226 (b"\x00\x04", "ColorLine.ColorStop[1].PaletteIndex (4)"), 227 (b"@\x00", "ColorLine.ColorStop[1].Alpha (1.0)"), 228 (b"@\x00", "ColorLine.ColorStop[2].StopOffset (1.0)"), 229 (b"\x00\x05", "ColorLine.ColorStop[2].PaletteIndex (5)"), 230 (b"@\x00", "ColorLine.ColorStop[2].Alpha (1.0)"), 231 # PaintGlyph glyph00013 232 (b"\x0a", "LayerList.Paint[2].Format (10)"), 233 (b"\x00\x00\x06", "Offset to Paint subtable from beginning of PaintGlyph (6)"), 234 (b"\x00\x0d", "LayerList.Paint[2].Glyph (13)"), 235 (b"\x0c", "LayerList.Paint[2].Paint.Format (12)"), 236 (b"\x00\x00\x07", "Offset to Paint subtable from beginning of PaintTransform (7)"), 237 (b"\x00\x00\x32", "Offset to Affine2x3 subtable from beginning of PaintTransform (50)"), 238 (b"\x07", "LayerList.Paint[2].Paint.Paint.Format (7)"), 239 (b"\x00\x00\x14", "Offset to ColorLine from beginning of PaintVarRadialGradient (20)"), 240 (b"\x00\x07", "Paint.x0.value (7)"), 241 (b"\x00\x08", "Paint.y0.value (8)"), 242 (b"\x00\t", "Paint.r0.value (9)"), 243 (b"\x00\n", "Paint.x1.value (10)"), 244 (b"\x00\x0b", "Paint.y1.value (11)"), 245 (b"\x00\x0c", "Paint.r1.value (12)"), 246 (b"\xff\xff\xff\xff", "VarIndexBase (0xFFFFFFFF)"), 247 (b"\x00", "ColorLine.Extend (0; pad)"), 248 (b"\x00\x02", "ColorLine.StopCount (2)"), 249 (b"\x00\x00", "ColorLine.ColorStop[0].StopOffset.value (0.0)"), 250 (b"\x00\x06", "ColorLine.ColorStop[0].PaletteIndex (6)"), 251 (b"@\x00", "ColorLine.ColorStop[0].Alpha.value (1.0)"), 252 (b"\xff\xff\xff\xff", "VarIndexBase (0xFFFFFFFF)"), 253 (b"@\x00", "ColorLine.ColorStop[1].StopOffset.value (1.0)"), 254 (b"\x00\x07", "ColorLine.ColorStop[1].PaletteIndex (7)"), 255 (b"\x19\x9a", "ColorLine.ColorStop[1].Alpha.value (0.4)"), 256 257 (b"\x00\x00\x00\x07", "VarIndexBase (7)"), 258 (b"\xff\xf3\x00\x00", "Affine2x3.xx (-13)"), 259 (b"\x00\x0e\x00\x00", "Affine2x3.xy (14)"), 260 (b"\x00\x0f\x00\x00", "Affine2x3.yx (15)"), 261 (b"\xff\xef\x00\x00", "Affine2x3.yy (-17)"), 262 (b"\x00\x12\x00\x00", "Affine2x3.yy (18)"), 263 (b"\x00\x13\x00\x00", "Affine2x3.yy (19)"), 264 265 # PaintTranslate 266 (b"\x0e", "LayerList.Paint[3].Format (14)"), 267 (b"\x00\x00\x08", "Offset to Paint subtable from beginning of PaintTranslate (8)"), 268 (b"\x01\x01", "dx (257)"), 269 (b"\x01\x02", "dy (258)"), 270 271 # PaintRotateAroundCenter 272 (b"\x1a", "LayerList.Paint[3].Paint.Format (26)"), 273 ( 274 b"\x00\x00\x0a", 275 "Offset to Paint subtable from beginning of PaintRotateAroundCenter (11)", 276 ), 277 (b"\x10\x00", "angle (0.25)"), 278 (b"\x00\xff", "centerX (255)"), 279 (b"\x01\x00", "centerY (256)"), 280 281 # PaintSkew 282 (b"\x1c", "LayerList.Paint[3].Paint.Paint.Format (28)"), 283 ( 284 b"\x00\x00\x08", 285 "Offset to Paint subtable from beginning of PaintSkew (8)", 286 ), 287 (b"\xfc\x17", "xSkewAngle (-0.0611)"), 288 (b"\x01\xc7", "ySkewAngle (0.0278)"), 289 290 # PaintGlyph 291 (b"\x0a", "LayerList.Paint[3].Paint.Paint.Paint.Format (10)"), 292 (b"\x00\x00\x06", "Offset to Paint subtable from beginning of PaintGlyph (6)"), 293 (b"\x00\x0b", "LayerList.Paint[2].Glyph (11)"), 294 295 # PaintSolid 296 (b"\x02", "LayerList.Paint[0].Paint.Paint.Paint.Paint.Format (2)"), 297 (b"\x00\x02", "Paint.PaletteIndex (2)"), 298 (b" \x00", "Paint.Alpha (0.5)"), 299 300 # ClipList 301 (b'\x01', "ClipList.Format (1)"), 302 (b'\x00\x00\x00\x02', "ClipList.ClipCount (2)"), 303 (b'\x00\x0a', "ClipRecord[0].StartGlyphID (10)"), 304 (b'\x00\x0a', "ClipRecord[0].EndGlyphID (10)"), 305 (b'\x00\x00\x13', "Offset to ClipBox subtable from beginning of ClipList (19)"), 306 (b'\x00\x0e', "ClipRecord[1].StartGlyphID (14)"), 307 (b'\x00\x0f', "ClipRecord[1].EndGlyphID (15)"), 308 (b'\x00\x00\x20', "Offset to ClipBox subtable from beginning of ClipList (32)"), 309 310 (b'\x02', "ClipBox.Format (2)"), 311 (b'\x00\x00', "ClipBox.xMin (0)"), 312 (b'\x00\x00', "ClipBox.yMin (0)"), 313 (b'\x01\xf4', "ClipBox.xMax (500)"), 314 (b'\x01\xf4', "ClipBox.yMax (500)"), 315 (b'\x00\x00\x00\t', "ClipBox.VarIndexBase (9)"), 316 317 (b'\x01', "ClipBox.Format (1)"), 318 (b'\x00\x00', "ClipBox.xMin (0)"), 319 (b'\x00\x00', "ClipBox.yMin (0)"), 320 (b'\x03\xe8', "ClipBox.xMax (1000)"), 321 (b'\x03\xe8', "ClipBox.yMax (1000)"), 322) 323 324COLR_V1_DATA = b"".join(t[0] for t in COLR_V1_SAMPLE) 325 326COLR_V1_XML = [ 327 '<Version value="1"/>', 328 "<!-- BaseGlyphRecordCount=1 -->", 329 "<BaseGlyphRecordArray>", 330 ' <BaseGlyphRecord index="0">', 331 ' <BaseGlyph value="glyph00006"/>', 332 ' <FirstLayerIndex value="0"/>', 333 ' <NumLayers value="3"/>', 334 " </BaseGlyphRecord>", 335 "</BaseGlyphRecordArray>", 336 "<LayerRecordArray>", 337 ' <LayerRecord index="0">', 338 ' <LayerGlyph value="glyph00007"/>', 339 ' <PaletteIndex value="0"/>', 340 " </LayerRecord>", 341 ' <LayerRecord index="1">', 342 ' <LayerGlyph value="glyph00008"/>', 343 ' <PaletteIndex value="1"/>', 344 " </LayerRecord>", 345 ' <LayerRecord index="2">', 346 ' <LayerGlyph value="glyph00009"/>', 347 ' <PaletteIndex value="2"/>', 348 " </LayerRecord>", 349 "</LayerRecordArray>", 350 "<!-- LayerRecordCount=3 -->", 351 "<BaseGlyphList>", 352 " <!-- BaseGlyphCount=3 -->", 353 ' <BaseGlyphPaintRecord index="0">', 354 ' <BaseGlyph value="glyph00010"/>', 355 ' <Paint Format="1"><!-- PaintColrLayers -->', 356 ' <NumLayers value="4"/>', 357 ' <FirstLayerIndex value="0"/>', 358 " </Paint>", 359 " </BaseGlyphPaintRecord>", 360 ' <BaseGlyphPaintRecord index="1">', 361 ' <BaseGlyph value="glyph00014"/>', 362 ' <Paint Format="32"><!-- PaintComposite -->', 363 ' <SourcePaint Format="11"><!-- PaintColrGlyph -->', 364 ' <Glyph value="glyph00010"/>', 365 " </SourcePaint>", 366 ' <CompositeMode value="src_over"/>', 367 ' <BackdropPaint Format="13"><!-- PaintVarTransform -->', 368 ' <Paint Format="11"><!-- PaintColrGlyph -->', 369 ' <Glyph value="glyph00010"/>', 370 " </Paint>", 371 " <Transform>", 372 ' <xx value="1.0"/>', 373 ' <yx value="0.0"/>', 374 ' <xy value="0.0"/>', 375 ' <yy value="1.0"/>', 376 ' <dx value="300.0"/>', 377 ' <dy value="0.0"/>', 378 ' <VarIndexBase value="0"/>', 379 " </Transform>", 380 " </BackdropPaint>", 381 " </Paint>", 382 " </BaseGlyphPaintRecord>", 383 ' <BaseGlyphPaintRecord index="2">', 384 ' <BaseGlyph value="glyph00015"/>', 385 ' <Paint Format="10"><!-- PaintGlyph -->', 386 ' <Paint Format="8"><!-- PaintSweepGradient -->', 387 " <ColorLine>", 388 ' <Extend value="pad"/>', 389 " <!-- StopCount=2 -->", 390 ' <ColorStop index="0">', 391 ' <StopOffset value="0.0"/>', 392 ' <PaletteIndex value="3"/>', 393 ' <Alpha value="1.0"/>', 394 " </ColorStop>", 395 ' <ColorStop index="1">', 396 ' <StopOffset value="1.0"/>', 397 ' <PaletteIndex value="5"/>', 398 ' <Alpha value="1.0"/>', 399 " </ColorStop>", 400 " </ColorLine>", 401 ' <centerX value="259"/>', 402 ' <centerY value="300"/>', 403 ' <startAngle value="45.0"/>', 404 ' <endAngle value="135.0"/>', 405 " </Paint>", 406 ' <Glyph value="glyph00011"/>', 407 " </Paint>", 408 " </BaseGlyphPaintRecord>", 409 "</BaseGlyphList>", 410 "<LayerList>", 411 " <!-- LayerCount=4 -->", 412 ' <Paint index="0" Format="10"><!-- PaintGlyph -->', 413 ' <Paint Format="3"><!-- PaintVarSolid -->', 414 ' <PaletteIndex value="2"/>', 415 ' <Alpha value="0.5"/>', 416 ' <VarIndexBase value="6"/>', 417 " </Paint>", 418 ' <Glyph value="glyph00011"/>', 419 " </Paint>", 420 ' <Paint index="1" Format="10"><!-- PaintGlyph -->', 421 ' <Paint Format="4"><!-- PaintLinearGradient -->', 422 " <ColorLine>", 423 ' <Extend value="repeat"/>', 424 " <!-- StopCount=3 -->", 425 ' <ColorStop index="0">', 426 ' <StopOffset value="0.0"/>', 427 ' <PaletteIndex value="3"/>', 428 ' <Alpha value="1.0"/>', 429 " </ColorStop>", 430 ' <ColorStop index="1">', 431 ' <StopOffset value="0.5"/>', 432 ' <PaletteIndex value="4"/>', 433 ' <Alpha value="1.0"/>', 434 " </ColorStop>", 435 ' <ColorStop index="2">', 436 ' <StopOffset value="1.0"/>', 437 ' <PaletteIndex value="5"/>', 438 ' <Alpha value="1.0"/>', 439 " </ColorStop>", 440 " </ColorLine>", 441 ' <x0 value="1"/>', 442 ' <y0 value="2"/>', 443 ' <x1 value="-3"/>', 444 ' <y1 value="-4"/>', 445 ' <x2 value="5"/>', 446 ' <y2 value="6"/>', 447 " </Paint>", 448 ' <Glyph value="glyph00012"/>', 449 " </Paint>", 450 ' <Paint index="2" Format="10"><!-- PaintGlyph -->', 451 ' <Paint Format="12"><!-- PaintTransform -->', 452 ' <Paint Format="7"><!-- PaintVarRadialGradient -->', 453 " <ColorLine>", 454 ' <Extend value="pad"/>', 455 " <!-- StopCount=2 -->", 456 ' <ColorStop index="0">', 457 ' <StopOffset value="0.0"/>', 458 ' <PaletteIndex value="6"/>', 459 ' <Alpha value="1.0"/>', 460 " <VarIndexBase/>", 461 " </ColorStop>", 462 ' <ColorStop index="1">', 463 ' <StopOffset value="1.0"/>', 464 ' <PaletteIndex value="7"/>', 465 ' <Alpha value="0.4"/>', 466 ' <VarIndexBase value="7"/>', 467 " </ColorStop>", 468 " </ColorLine>", 469 ' <x0 value="7"/>', 470 ' <y0 value="8"/>', 471 ' <r0 value="9"/>', 472 ' <x1 value="10"/>', 473 ' <y1 value="11"/>', 474 ' <r1 value="12"/>', 475 " <VarIndexBase/>", 476 " </Paint>", 477 " <Transform>", 478 ' <xx value="-13.0"/>', 479 ' <yx value="14.0"/>', 480 ' <xy value="15.0"/>', 481 ' <yy value="-17.0"/>', 482 ' <dx value="18.0"/>', 483 ' <dy value="19.0"/>', 484 " </Transform>", 485 " </Paint>", 486 ' <Glyph value="glyph00013"/>', 487 " </Paint>", 488 ' <Paint index="3" Format="14"><!-- PaintTranslate -->', 489 ' <Paint Format="26"><!-- PaintRotateAroundCenter -->', 490 ' <Paint Format="28"><!-- PaintSkew -->', 491 ' <Paint Format="10"><!-- PaintGlyph -->', 492 ' <Paint Format="2"><!-- PaintSolid -->', 493 ' <PaletteIndex value="2"/>', 494 ' <Alpha value="0.5"/>', 495 " </Paint>", 496 ' <Glyph value="glyph00011"/>', 497 " </Paint>", 498 ' <xSkewAngle value="-11.0"/>', 499 ' <ySkewAngle value="5.0"/>', 500 " </Paint>", 501 ' <angle value="45.0"/>', 502 ' <centerX value="255"/>', 503 ' <centerY value="256"/>', 504 " </Paint>", 505 ' <dx value="257"/>', 506 ' <dy value="258"/>', 507 " </Paint>", 508 "</LayerList>", 509 '<ClipList Format="1">', 510 " <Clip>", 511 ' <Glyph value="glyph00010"/>', 512 ' <ClipBox Format="2">', 513 ' <xMin value="0"/>', 514 ' <yMin value="0"/>', 515 ' <xMax value="500"/>', 516 ' <yMax value="500"/>', 517 ' <VarIndexBase value="9"/>', 518 " </ClipBox>", 519 " </Clip>", 520 " <Clip>", 521 ' <Glyph value="glyph00014"/>', 522 ' <Glyph value="glyph00015"/>', 523 ' <ClipBox Format="1">', 524 ' <xMin value="0"/>', 525 ' <yMin value="0"/>', 526 ' <xMax value="1000"/>', 527 ' <yMax value="1000"/>', 528 " </ClipBox>", 529 " </Clip>", 530 "</ClipList>", 531] 532 533COLR_V1_VAR_XML = [ 534 '<VarIndexMap Format="0">', 535 ' <Map index="0" outer="1" inner="1"/>', 536 ' <Map index="1" outer="1" inner="0"/>', 537 ' <Map index="2" outer="1" inner="0"/>', 538 ' <Map index="3" outer="1" inner="1"/>', 539 ' <Map index="4" outer="1" inner="0"/>', 540 ' <Map index="5" outer="1" inner="0"/>', 541 ' <Map index="6" outer="0" inner="2"/>', 542 ' <Map index="7" outer="0" inner="0"/>', 543 ' <Map index="8" outer="0" inner="1"/>', 544 ' <Map index="9" outer="1" inner="0"/>', 545 ' <Map index="10" outer="1" inner="0"/>', 546 ' <Map index="11" outer="0" inner="3"/>', 547 ' <Map index="12" outer="0" inner="3"/>', 548 "</VarIndexMap>", 549 '<VarStore Format="1">', 550 ' <Format value="1"/>', 551 " <VarRegionList>", 552 " <!-- RegionAxisCount=1 -->", 553 " <!-- RegionCount=1 -->", 554 ' <Region index="0">', 555 ' <VarRegionAxis index="0">', 556 ' <StartCoord value="0.0"/>', 557 ' <PeakCoord value="1.0"/>', 558 ' <EndCoord value="1.0"/>', 559 " </VarRegionAxis>", 560 " </Region>", 561 " </VarRegionList>", 562 " <!-- VarDataCount=2 -->", 563 ' <VarData index="0">', 564 " <!-- ItemCount=4 -->", 565 ' <NumShorts value="1"/>', 566 " <!-- VarRegionCount=1 -->", 567 ' <VarRegionIndex index="0" value="0"/>', 568 ' <Item index="0" value="[-3277]"/>', 569 ' <Item index="1" value="[6553]"/>', 570 ' <Item index="2" value="[8192]"/>', 571 ' <Item index="3" value="[500]"/>', 572 " </VarData>", 573 ' <VarData index="1">', 574 " <!-- ItemCount=2 -->", 575 ' <NumShorts value="32769"/>', 576 " <!-- VarRegionCount=1 -->", 577 ' <VarRegionIndex index="0" value="0"/>', 578 ' <Item index="0" value="[0]"/>', 579 ' <Item index="1" value="[65536]"/>', 580 " </VarData>", 581 "</VarStore>", 582] 583 584 585class COLR_V1_Test(object): 586 def test_decompile_and_compile(self, font): 587 colr = table_C_O_L_R_() 588 colr.decompile(COLR_V1_DATA, font) 589 diff_binary_fragments(colr.compile(font), COLR_V1_SAMPLE) 590 591 def test_decompile_and_dump_xml(self, font): 592 colr = table_C_O_L_R_() 593 colr.decompile(COLR_V1_DATA, font) 594 595 dump(colr, font) 596 assert getXML(colr.toXML, font) == COLR_V1_XML 597 598 def test_load_from_xml_and_compile(self, font): 599 colr = table_C_O_L_R_() 600 for name, attrs, content in parseXML(COLR_V1_XML): 601 colr.fromXML(name, attrs, content, font) 602 diff_binary_fragments(colr.compile(font), COLR_V1_SAMPLE) 603 604 def test_round_trip_xml(self, font): 605 colr = table_C_O_L_R_() 606 for name, attrs, content in parseXML(COLR_V1_XML): 607 colr.fromXML(name, attrs, content, font) 608 compiled = colr.compile(font) 609 610 colr = table_C_O_L_R_() 611 colr.decompile(compiled, font) 612 assert getXML(colr.toXML, font) == COLR_V1_XML 613 614 615class COLR_V1_Variable_Test(object): 616 def test_round_trip_xml(self, font): 617 colr = table_C_O_L_R_() 618 xml = COLR_V1_XML + COLR_V1_VAR_XML 619 for name, attrs, content in parseXML(xml): 620 colr.fromXML(name, attrs, content, font) 621 compiled = colr.compile(font) 622 623 colr = table_C_O_L_R_() 624 colr.decompile(compiled, font) 625 assert getXML(colr.toXML, font) == xml 626