colorLib: update builders to latest COLRv1 draft
LayerV1Record and Affine2x2 are gone. LayerV1List now contains a list of Paint DAGs Added 4 new Paint formats: PaintGlyph, PaintColorGlyph, PaintTransform and PaintComposite
This commit is contained in:
parent
7f6a05b007
commit
fdf6a5c1fc
@ -6,13 +6,26 @@ import collections
|
||||
import copy
|
||||
import enum
|
||||
from functools import partial
|
||||
from typing import Any, Dict, Iterable, List, Mapping, Optional, Sequence, Tuple, Union
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
Iterable,
|
||||
List,
|
||||
Mapping,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
from fontTools.ttLib.tables import C_O_L_R_
|
||||
from fontTools.ttLib.tables import C_P_A_L_
|
||||
from fontTools.ttLib.tables import _n_a_m_e
|
||||
from fontTools.ttLib.tables import otTables as ot
|
||||
from fontTools.ttLib.tables.otTables import (
|
||||
ExtendMode,
|
||||
CompositeMode,
|
||||
VariableValue,
|
||||
VariableFloat,
|
||||
VariableInt,
|
||||
@ -21,11 +34,11 @@ from .errors import ColorLibError
|
||||
|
||||
|
||||
# TODO move type aliases to colorLib.types?
|
||||
T = TypeVar("T")
|
||||
_Kwargs = Mapping[str, Any]
|
||||
_PaintInput = Union[int, _Kwargs, ot.Paint]
|
||||
_LayerTuple = Tuple[str, _PaintInput]
|
||||
_LayersList = Sequence[_LayerTuple]
|
||||
_ColorGlyphsDict = Dict[str, _LayersList]
|
||||
_PaintInput = Union[int, _Kwargs, ot.Paint, Tuple[str, "_PaintInput"]]
|
||||
_PaintInputList = Sequence[_PaintInput]
|
||||
_ColorGlyphsDict = Dict[str, Union[_PaintInputList, ot.LayerV1List]]
|
||||
_ColorGlyphsV0Dict = Dict[str, Sequence[Tuple[str, int]]]
|
||||
_Number = Union[int, float]
|
||||
_ScalarInput = Union[_Number, VariableValue, Tuple[_Number, int]]
|
||||
@ -33,10 +46,13 @@ _ColorStopTuple = Tuple[_ScalarInput, int]
|
||||
_ColorStopInput = Union[_ColorStopTuple, _Kwargs, ot.ColorStop]
|
||||
_ColorStopsList = Sequence[_ColorStopInput]
|
||||
_ExtendInput = Union[int, str, ExtendMode]
|
||||
_CompositeInput = Union[int, str, CompositeMode]
|
||||
_ColorLineInput = Union[_Kwargs, ot.ColorLine]
|
||||
_PointTuple = Tuple[_ScalarInput, _ScalarInput]
|
||||
_AffineTuple = Tuple[_ScalarInput, _ScalarInput, _ScalarInput, _ScalarInput]
|
||||
_AffineInput = Union[_AffineTuple, ot.Affine2x2]
|
||||
_AffineTuple = Tuple[
|
||||
_ScalarInput, _ScalarInput, _ScalarInput, _ScalarInput, _ScalarInput, _ScalarInput
|
||||
]
|
||||
_AffineInput = Union[_AffineTuple, ot.Affine2x3]
|
||||
|
||||
|
||||
def populateCOLRv0(
|
||||
@ -91,14 +107,13 @@ def buildCOLR(
|
||||
"""Build COLR table from color layers mapping.
|
||||
|
||||
Args:
|
||||
colorGlyphs: map of base glyph names to lists of (layer glyph names,
|
||||
Paint) tuples. For COLRv0, a paint is simply the color palette index
|
||||
(int); for COLRv1, paint can be either solid colors (with variable
|
||||
opacity), linear gradients or radial gradients.
|
||||
colorGlyphs: map of base glyph name to, either list of (layer glyph name,
|
||||
color palette index) tuples for COLRv0; or list of Paints (dicts)
|
||||
for COLRv1.
|
||||
version: the version of COLR table. If None, the version is determined
|
||||
by the presence of gradients or variation data (varStore), which
|
||||
require version 1; otherwise, if there are only simple colors, version
|
||||
0 is used.
|
||||
by the presence of COLRv1 paints or variation data (varStore), which
|
||||
require version 1; otherwise, if all base glyphs use only simple color
|
||||
layers, version 0 is used.
|
||||
glyphMap: a map from glyph names to glyph indices, as returned from
|
||||
TTFont.getReverseGlyphMap(), to optionally sort base records by GID.
|
||||
varStore: Optional ItemVarationStore for deltas associated with v1 layer.
|
||||
@ -113,10 +128,9 @@ def buildCOLR(
|
||||
|
||||
if version in (None, 0) and not varStore:
|
||||
# split color glyphs into v0 and v1 and encode separately
|
||||
colorGlyphsV0, colorGlyphsV1 = _splitSolidAndGradientGlyphs(colorGlyphs)
|
||||
colorGlyphsV0, colorGlyphsV1 = _split_color_glyphs_by_version(colorGlyphs)
|
||||
if version == 0 and colorGlyphsV1:
|
||||
# TODO Derive "average" solid color from gradients?
|
||||
raise ValueError("Can't encode gradients in COLRv0")
|
||||
raise ValueError("Can't encode COLRv1 glyphs in COLRv0")
|
||||
else:
|
||||
# unless explicitly requested for v1 or have variations, in which case
|
||||
# we encode all color glyph as v1
|
||||
@ -277,29 +291,16 @@ def buildCPAL(
|
||||
_DEFAULT_ALPHA = VariableFloat(1.0)
|
||||
|
||||
|
||||
def _splitSolidAndGradientGlyphs(
|
||||
def _split_color_glyphs_by_version(
|
||||
colorGlyphs: _ColorGlyphsDict,
|
||||
) -> Tuple[Dict[str, List[Tuple[str, int]]], Dict[str, List[Tuple[str, ot.Paint]]]]:
|
||||
) -> Tuple[_ColorGlyphsV0Dict, _ColorGlyphsDict]:
|
||||
colorGlyphsV0 = {}
|
||||
colorGlyphsV1 = {}
|
||||
for baseGlyph, layers in colorGlyphs.items():
|
||||
newLayers = []
|
||||
allSolidColors = True
|
||||
for layerGlyph, paint in layers:
|
||||
paint = _to_ot_paint(paint)
|
||||
if (
|
||||
paint.Format != 1
|
||||
or paint.Color.Alpha.value != _DEFAULT_ALPHA.value
|
||||
):
|
||||
allSolidColors = False
|
||||
newLayers.append((layerGlyph, paint))
|
||||
if allSolidColors:
|
||||
colorGlyphsV0[baseGlyph] = [
|
||||
(layerGlyph, paint.Color.PaletteIndex)
|
||||
for layerGlyph, paint in newLayers
|
||||
]
|
||||
if all(isinstance(l, tuple) and isinstance(l[1], int) for l in layers):
|
||||
colorGlyphsV0[baseGlyph] = layers
|
||||
else:
|
||||
colorGlyphsV1[baseGlyph] = newLayers
|
||||
colorGlyphsV1[baseGlyph] = layers
|
||||
|
||||
# sanity check
|
||||
assert set(colorGlyphs) == (set(colorGlyphsV0) | set(colorGlyphsV1))
|
||||
@ -351,15 +352,23 @@ def buildColorStop(
|
||||
return self
|
||||
|
||||
|
||||
def _to_extend_mode(v: _ExtendInput) -> ExtendMode:
|
||||
if isinstance(v, ExtendMode):
|
||||
def _to_enum_value(v: Union[str, int, T], enumClass: Type[T]) -> T:
|
||||
if isinstance(v, enumClass):
|
||||
return v
|
||||
elif isinstance(v, str):
|
||||
try:
|
||||
return getattr(ExtendMode, v.upper())
|
||||
return getattr(enumClass, v.upper())
|
||||
except AttributeError:
|
||||
raise ValueError(f"{v!r} is not a valid ExtendMode")
|
||||
return ExtendMode(v)
|
||||
raise ValueError(f"{v!r} is not a valid {enumClass.__name__}")
|
||||
return enumClass(v)
|
||||
|
||||
|
||||
def _to_extend_mode(v: _ExtendInput) -> ExtendMode:
|
||||
return _to_enum_value(v, ExtendMode)
|
||||
|
||||
|
||||
def _to_composite_mode(v: _CompositeInput) -> CompositeMode:
|
||||
return _to_enum_value(v, CompositeMode)
|
||||
|
||||
|
||||
def buildColorLine(
|
||||
@ -406,12 +415,17 @@ def buildLinearGradientPaint(
|
||||
return self
|
||||
|
||||
|
||||
def buildAffine2x2(
|
||||
xx: _ScalarInput, xy: _ScalarInput, yx: _ScalarInput, yy: _ScalarInput
|
||||
) -> ot.Affine2x2:
|
||||
self = ot.Affine2x2()
|
||||
def buildAffine2x3(
|
||||
xx: _ScalarInput,
|
||||
xy: _ScalarInput,
|
||||
yx: _ScalarInput,
|
||||
yy: _ScalarInput,
|
||||
dx: _ScalarInput,
|
||||
dy: _ScalarInput,
|
||||
) -> ot.Affine2x3:
|
||||
self = ot.Affine2x3()
|
||||
locs = locals()
|
||||
for attr in ("xx", "xy", "yx", "yy"):
|
||||
for attr in ("xx", "xy", "yx", "yy", "dx", "dy"):
|
||||
value = locs[attr]
|
||||
setattr(self, attr, _to_variable_float(value))
|
||||
return self
|
||||
@ -423,7 +437,6 @@ def buildRadialGradientPaint(
|
||||
c1: _PointTuple,
|
||||
r0: _ScalarInput,
|
||||
r1: _ScalarInput,
|
||||
transform: Optional[_AffineInput] = None,
|
||||
) -> ot.Paint:
|
||||
|
||||
self = ot.Paint()
|
||||
@ -435,50 +448,86 @@ def buildRadialGradientPaint(
|
||||
setattr(self, f"y{i}", _to_variable_int(y))
|
||||
setattr(self, f"r{i}", _to_variable_int(r))
|
||||
|
||||
if transform is not None and not isinstance(transform, ot.Affine2x2):
|
||||
transform = buildAffine2x2(*transform)
|
||||
self.Transform = transform
|
||||
|
||||
return self
|
||||
|
||||
|
||||
def _to_ot_paint(paint: _PaintInput) -> ot.Paint:
|
||||
def buildPaintGlyph(glyph: str, paint: _PaintInput) -> ot.Paint:
|
||||
self = ot.Paint()
|
||||
self.Format = 4
|
||||
self.Glyph = glyph
|
||||
self.Paint = buildPaint(paint)
|
||||
return self
|
||||
|
||||
|
||||
def buildPaintColorGlyph(glyph: str) -> ot.Paint:
|
||||
self = ot.Paint()
|
||||
self.Format = 5
|
||||
self.Glyph = glyph
|
||||
return self
|
||||
|
||||
|
||||
def buildPaintTransform(transform: _AffineInput, paint: _PaintInput) -> ot.Paint:
|
||||
self = ot.Paint()
|
||||
self.Format = 6
|
||||
if not isinstance(transform, ot.Affine2x3):
|
||||
transform = buildAffine2x3(*transform)
|
||||
self.Transform = transform
|
||||
self.Paint = buildPaint(paint)
|
||||
return self
|
||||
|
||||
|
||||
def buildPaintComposite(
|
||||
mode: _CompositeInput, source: _PaintInput, backdrop: _PaintInput
|
||||
):
|
||||
self = ot.Paint()
|
||||
self.Format = 7
|
||||
self.SourcePaint = buildPaint(source)
|
||||
self.CompositeMode = _to_composite_mode(mode)
|
||||
self.BackdropPaint = buildPaint(backdrop)
|
||||
return self
|
||||
|
||||
|
||||
_PAINT_BUILDERS = {
|
||||
1: buildSolidColorPaint,
|
||||
2: buildLinearGradientPaint,
|
||||
3: buildRadialGradientPaint,
|
||||
4: buildPaintGlyph,
|
||||
5: buildPaintColorGlyph,
|
||||
6: buildPaintTransform,
|
||||
7: buildPaintComposite,
|
||||
}
|
||||
|
||||
|
||||
def buildPaint(paint: _PaintInput) -> ot.Paint:
|
||||
if isinstance(paint, ot.Paint):
|
||||
return paint
|
||||
elif isinstance(paint, int):
|
||||
paletteIndex = paint
|
||||
return buildSolidColorPaint(paletteIndex)
|
||||
elif isinstance(paint, tuple):
|
||||
layerGlyph, paint = paint
|
||||
return buildPaintGlyph(layerGlyph, paint)
|
||||
elif isinstance(paint, collections.abc.Mapping):
|
||||
return buildPaint(**paint)
|
||||
raise TypeError(f"expected int, Mapping or ot.Paint, found {type(paint.__name__)}")
|
||||
kwargs = dict(paint)
|
||||
fmt = kwargs.pop("format")
|
||||
try:
|
||||
return _PAINT_BUILDERS[fmt](**kwargs)
|
||||
except KeyError:
|
||||
raise NotImplementedError(fmt)
|
||||
raise TypeError(
|
||||
f"expected int, Mapping or ot.Paint, found {type(paint).__name__}: {paint!r}"
|
||||
)
|
||||
|
||||
|
||||
def buildLayerV1Record(layerGlyph: str, paint: _PaintInput) -> ot.LayerV1Record:
|
||||
self = ot.LayerV1Record()
|
||||
self.LayerGlyph = layerGlyph
|
||||
self.Paint = _to_ot_paint(paint)
|
||||
return self
|
||||
|
||||
|
||||
def buildLayerV1List(
|
||||
layers: Sequence[Union[_LayerTuple, ot.LayerV1Record]]
|
||||
) -> ot.LayerV1List:
|
||||
def buildLayerV1List(layers: _PaintInputList) -> ot.LayerV1List:
|
||||
self = ot.LayerV1List()
|
||||
self.LayerCount = len(layers)
|
||||
records = []
|
||||
for layer in layers:
|
||||
if isinstance(layer, ot.LayerV1Record):
|
||||
record = layer
|
||||
else:
|
||||
layerGlyph, paint = layer
|
||||
record = buildLayerV1Record(layerGlyph, paint)
|
||||
records.append(record)
|
||||
self.LayerV1Record = records
|
||||
self.Paint = [buildPaint(layer) for layer in layers]
|
||||
return self
|
||||
|
||||
|
||||
def buildBaseGlyphV1Record(
|
||||
baseGlyph: str, layers: Union[_LayersList, ot.LayerV1List]
|
||||
baseGlyph: str, layers: Union[_PaintInputList, ot.LayerV1List]
|
||||
) -> ot.BaseGlyphV1List:
|
||||
self = ot.BaseGlyphV1Record()
|
||||
self.BaseGlyph = baseGlyph
|
||||
@ -489,7 +538,7 @@ def buildBaseGlyphV1Record(
|
||||
|
||||
|
||||
def buildBaseGlyphV1List(
|
||||
colorGlyphs: Union[_ColorGlyphsDict, Dict[str, ot.LayerV1List]],
|
||||
colorGlyphs: _ColorGlyphsDict,
|
||||
glyphMap: Optional[Mapping[str, int]] = None,
|
||||
) -> ot.BaseGlyphV1List:
|
||||
if glyphMap is not None:
|
||||
@ -506,17 +555,3 @@ def buildBaseGlyphV1List(
|
||||
self.BaseGlyphCount = len(records)
|
||||
self.BaseGlyphV1Record = records
|
||||
return self
|
||||
|
||||
|
||||
_PAINT_BUILDERS = {
|
||||
1: buildSolidColorPaint,
|
||||
2: buildLinearGradientPaint,
|
||||
3: buildRadialGradientPaint,
|
||||
}
|
||||
|
||||
|
||||
def buildPaint(format: int, **kwargs) -> ot.Paint:
|
||||
try:
|
||||
return _PAINT_BUILDERS[format](**kwargs)
|
||||
except KeyError:
|
||||
raise NotImplementedError(format)
|
||||
|
@ -284,12 +284,14 @@ def test_buildColorLine():
|
||||
] == stops
|
||||
|
||||
|
||||
def test_buildAffine2x2():
|
||||
matrix = builder.buildAffine2x2(1.5, 0, 0.5, 2.0)
|
||||
def test_buildAffine2x3():
|
||||
matrix = builder.buildAffine2x3(1.5, 0, 0.5, 2.0, 1.0, -3.0)
|
||||
assert matrix.xx == builder.VariableFloat(1.5)
|
||||
assert matrix.xy == builder.VariableFloat(0.0)
|
||||
assert matrix.yx == builder.VariableFloat(0.5)
|
||||
assert matrix.yy == builder.VariableFloat(2.0)
|
||||
assert matrix.dx == builder.VariableFloat(1.0)
|
||||
assert matrix.dy == builder.VariableFloat(-3.0)
|
||||
|
||||
|
||||
def test_buildLinearGradientPaint():
|
||||
@ -337,36 +339,24 @@ def test_buildRadialGradientPaint():
|
||||
assert (gradient.x1, gradient.y1) == c1
|
||||
assert gradient.r0 == r0
|
||||
assert gradient.r1 == r1
|
||||
assert gradient.Transform is None
|
||||
|
||||
gradient = builder.buildRadialGradientPaint({"stops": color_stops}, c0, c1, r0, r1)
|
||||
assert gradient.ColorLine.Extend == builder.ExtendMode.PAD
|
||||
assert gradient.ColorLine.ColorStop == color_stops
|
||||
|
||||
matrix = builder.buildAffine2x2(2.0, 0.0, 0.0, 2.0)
|
||||
gradient = builder.buildRadialGradientPaint(
|
||||
color_line, c0, c1, r0, r1, transform=matrix
|
||||
)
|
||||
assert gradient.Transform == matrix
|
||||
|
||||
gradient = builder.buildRadialGradientPaint(
|
||||
color_line, c0, c1, r0, r1, transform=(2.0, 0.0, 0.0, 2.0)
|
||||
)
|
||||
assert gradient.Transform == matrix
|
||||
|
||||
|
||||
def test_buildLayerV1Record():
|
||||
layer = builder.buildLayerV1Record("a", 2)
|
||||
assert layer.LayerGlyph == "a"
|
||||
def test_buildPaintGlyph():
|
||||
layer = builder.buildPaintGlyph("a", 2)
|
||||
assert layer.Glyph == "a"
|
||||
assert layer.Paint.Format == 1
|
||||
assert layer.Paint.Color.PaletteIndex == 2
|
||||
|
||||
layer = builder.buildLayerV1Record("a", builder.buildSolidColorPaint(3, 0.9))
|
||||
layer = builder.buildPaintGlyph("a", builder.buildSolidColorPaint(3, 0.9))
|
||||
assert layer.Paint.Format == 1
|
||||
assert layer.Paint.Color.PaletteIndex == 3
|
||||
assert layer.Paint.Color.Alpha.value == 0.9
|
||||
|
||||
layer = builder.buildLayerV1Record(
|
||||
layer = builder.buildPaintGlyph(
|
||||
"a",
|
||||
builder.buildLinearGradientPaint(
|
||||
{"stops": [(0.0, 3), (1.0, 4)]}, (100, 200), (150, 250)
|
||||
@ -382,7 +372,7 @@ def test_buildLayerV1Record():
|
||||
assert layer.Paint.x1.value == 150
|
||||
assert layer.Paint.y1.value == 250
|
||||
|
||||
layer = builder.buildLayerV1Record(
|
||||
layer = builder.buildPaintGlyph(
|
||||
"a",
|
||||
builder.buildRadialGradientPaint(
|
||||
{
|
||||
@ -414,13 +404,13 @@ def test_buildLayerV1Record():
|
||||
assert layer.Paint.r1.value == 10
|
||||
|
||||
|
||||
def test_buildLayerV1Record_from_dict():
|
||||
layer = builder.buildLayerV1Record("a", {"format": 1, "paletteIndex": 0})
|
||||
assert layer.LayerGlyph == "a"
|
||||
def test_buildPaintGlyph_from_dict():
|
||||
layer = builder.buildPaintGlyph("a", {"format": 1, "paletteIndex": 0})
|
||||
assert layer.Glyph == "a"
|
||||
assert layer.Paint.Format == 1
|
||||
assert layer.Paint.Color.PaletteIndex == 0
|
||||
|
||||
layer = builder.buildLayerV1Record(
|
||||
layer = builder.buildPaintGlyph(
|
||||
"a",
|
||||
{
|
||||
"format": 2,
|
||||
@ -432,7 +422,7 @@ def test_buildLayerV1Record_from_dict():
|
||||
assert layer.Paint.Format == 2
|
||||
assert layer.Paint.ColorLine.ColorStop[0].StopOffset.value == 0.0
|
||||
|
||||
layer = builder.buildLayerV1Record(
|
||||
layer = builder.buildPaintGlyph(
|
||||
"a",
|
||||
{
|
||||
"format": 3,
|
||||
@ -477,12 +467,12 @@ def test_buildLayerV1List():
|
||||
"r1": 10,
|
||||
},
|
||||
),
|
||||
builder.buildLayerV1Record("e", builder.buildSolidColorPaint(8)),
|
||||
builder.buildPaintGlyph("e", builder.buildSolidColorPaint(8)),
|
||||
]
|
||||
layers = builder.buildLayerV1List(layers)
|
||||
|
||||
assert layers.LayerCount == len(layers.LayerV1Record)
|
||||
assert all(isinstance(l, ot.LayerV1Record) for l in layers.LayerV1Record)
|
||||
assert layers.LayerCount == len(layers.Paint)
|
||||
assert all(isinstance(l, ot.Paint) for l in layers.Paint)
|
||||
|
||||
|
||||
def test_buildBaseGlyphV1Record():
|
||||
@ -540,17 +530,17 @@ def test_buildBaseGlyphV1List():
|
||||
assert baseGlyphs.BaseGlyphV1Record[2].BaseGlyph == "g"
|
||||
|
||||
|
||||
def test_splitSolidAndGradientGlyphs():
|
||||
def test_split_color_glyphs_by_version():
|
||||
colorGlyphs = {
|
||||
"a": [
|
||||
("b", 0),
|
||||
("c", 1),
|
||||
("d", {"format": 1, "paletteIndex": 2}),
|
||||
("e", builder.buildSolidColorPaint(paletteIndex=3)),
|
||||
("d", 2),
|
||||
("e", 3),
|
||||
]
|
||||
}
|
||||
|
||||
colorGlyphsV0, colorGlyphsV1 = builder._splitSolidAndGradientGlyphs(colorGlyphs)
|
||||
colorGlyphsV0, colorGlyphsV1 = builder._split_color_glyphs_by_version(colorGlyphs)
|
||||
|
||||
assert colorGlyphsV0 == {"a": [("b", 0), ("c", 1), ("d", 2), ("e", 3)]}
|
||||
assert not colorGlyphsV1
|
||||
@ -559,7 +549,7 @@ def test_splitSolidAndGradientGlyphs():
|
||||
"a": [("b", builder.buildSolidColorPaint(paletteIndex=0, alpha=0.0))]
|
||||
}
|
||||
|
||||
colorGlyphsV0, colorGlyphsV1 = builder._splitSolidAndGradientGlyphs(colorGlyphs)
|
||||
colorGlyphsV0, colorGlyphsV1 = builder._split_color_glyphs_by_version(colorGlyphs)
|
||||
|
||||
assert not colorGlyphsV0
|
||||
assert colorGlyphsV1 == colorGlyphs
|
||||
@ -580,23 +570,13 @@ def test_splitSolidAndGradientGlyphs():
|
||||
],
|
||||
}
|
||||
|
||||
colorGlyphsV0, colorGlyphsV1 = builder._splitSolidAndGradientGlyphs(colorGlyphs)
|
||||
colorGlyphsV0, colorGlyphsV1 = builder._split_color_glyphs_by_version(colorGlyphs)
|
||||
|
||||
assert colorGlyphsV0 == {"a": [("b", 0)]}
|
||||
assert "a" not in colorGlyphsV1
|
||||
assert "c" in colorGlyphsV1
|
||||
assert len(colorGlyphsV1["c"]) == 2
|
||||
|
||||
layer_d = colorGlyphsV1["c"][0]
|
||||
assert layer_d[0] == "d"
|
||||
assert isinstance(layer_d[1], ot.Paint)
|
||||
assert layer_d[1].Format == 1
|
||||
|
||||
layer_e = colorGlyphsV1["c"][1]
|
||||
assert layer_e[0] == "e"
|
||||
assert isinstance(layer_e[1], ot.Paint)
|
||||
assert layer_e[1].Format == 2
|
||||
|
||||
|
||||
class BuildCOLRTest(object):
|
||||
def test_automatic_version_all_solid_color_glyphs(self):
|
||||
@ -691,9 +671,7 @@ class BuildCOLRTest(object):
|
||||
colr.table.BaseGlyphV1List.BaseGlyphV1Record[0].LayerV1List, ot.LayerV1List
|
||||
)
|
||||
assert (
|
||||
colr.table.BaseGlyphV1List.BaseGlyphV1Record[0]
|
||||
.LayerV1List.LayerV1Record[0]
|
||||
.LayerGlyph
|
||||
colr.table.BaseGlyphV1List.BaseGlyphV1Record[0].LayerV1List.Paint[0].Glyph
|
||||
== "e"
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user