Update to builder per review discussion
This commit is contained in:
parent
4171e28f32
commit
cf2097f7c0
@ -152,7 +152,6 @@ def buildCOLR(
|
|||||||
if colorGlyphsV1:
|
if colorGlyphsV1:
|
||||||
colr.LayerV1List, colr.BaseGlyphV1List = buildColrV1(colorGlyphsV1, glyphMap)
|
colr.LayerV1List, colr.BaseGlyphV1List = buildColrV1(colorGlyphsV1, glyphMap)
|
||||||
|
|
||||||
|
|
||||||
if version is None:
|
if version is None:
|
||||||
version = 1 if (varStore or colorGlyphsV1) else 0
|
version = 1 if (varStore or colorGlyphsV1) else 0
|
||||||
elif version not in (0, 1):
|
elif version not in (0, 1):
|
||||||
@ -369,15 +368,6 @@ def buildColorIndex(
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
def buildPaintSolid(
|
|
||||||
paletteIndex: int, alpha: _ScalarInput = _DEFAULT_ALPHA
|
|
||||||
) -> ot.Paint:
|
|
||||||
self = ot.Paint()
|
|
||||||
self.Format = int(ot.Paint.Format.PaintSolid)
|
|
||||||
self.Color = buildColorIndex(paletteIndex, alpha)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def buildColorStop(
|
def buildColorStop(
|
||||||
offset: _ScalarInput,
|
offset: _ScalarInput,
|
||||||
paletteIndex: int,
|
paletteIndex: int,
|
||||||
@ -433,17 +423,6 @@ def _to_color_line(obj):
|
|||||||
raise TypeError(obj)
|
raise TypeError(obj)
|
||||||
|
|
||||||
|
|
||||||
_PAINT_BUILDERS = {
|
|
||||||
1: lambda _, kwargs: buildPaintSolid(**kwargs),
|
|
||||||
2: lambda _, kwargs: buildPaintLinearGradient(**kwargs),
|
|
||||||
3: lambda _, kwargs: buildPaintRadialGradient(**kwargs),
|
|
||||||
4: lambda builder, kwargs: buildPaintGlyph(builder, **kwargs),
|
|
||||||
5: lambda _, kwargs: buildPaintColrGlyph(**kwargs),
|
|
||||||
6: lambda builder, kwargs: buildPaintTransform(builder, **kwargs),
|
|
||||||
7: lambda builder, kwargs: buildPaintComposite(builder, **kwargs),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _as_tuple(obj) -> Tuple[Any, ...]:
|
def _as_tuple(obj) -> Tuple[Any, ...]:
|
||||||
# start simple, who even cares about cyclic graphs or interesting field types
|
# start simple, who even cares about cyclic graphs or interesting field types
|
||||||
def _tuple_safe(value):
|
def _tuple_safe(value):
|
||||||
@ -454,6 +433,7 @@ def _as_tuple(obj) -> Tuple[Any, ...]:
|
|||||||
elif isinstance(value, collections.abc.MutableSequence):
|
elif isinstance(value, collections.abc.MutableSequence):
|
||||||
return tuple(_tuple_safe(e) for e in value)
|
return tuple(_tuple_safe(e) for e in value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
return tuple(_tuple_safe(obj))
|
return tuple(_tuple_safe(obj))
|
||||||
|
|
||||||
|
|
||||||
@ -468,7 +448,7 @@ def _reuse_ranges(num_layers: int) -> Generator[Tuple[int, int], None, None]:
|
|||||||
yield (lbound, ubound)
|
yield (lbound, ubound)
|
||||||
|
|
||||||
|
|
||||||
class LayerCollector:
|
class LayerV1ListBuilder:
|
||||||
slices: List[ot.Paint]
|
slices: List[ot.Paint]
|
||||||
layers: List[ot.Paint]
|
layers: List[ot.Paint]
|
||||||
reusePool: Mapping[Tuple[Any, ...], int]
|
reusePool: Mapping[Tuple[Any, ...], int]
|
||||||
@ -478,21 +458,107 @@ class LayerCollector:
|
|||||||
self.layers = []
|
self.layers = []
|
||||||
self.reusePool = {}
|
self.reusePool = {}
|
||||||
|
|
||||||
def buildColrLayers(self, paints: List[_PaintInput]) -> ot.Paint:
|
def buildPaintSolid(
|
||||||
paint = ot.Paint()
|
self, paletteIndex: int, alpha: _ScalarInput = _DEFAULT_ALPHA
|
||||||
paint.Format = int(ot.Paint.Format.PaintColrLayers)
|
) -> ot.Paint:
|
||||||
self.slices.append(paint)
|
ot_paint = ot.Paint()
|
||||||
|
ot_paint.Format = int(ot.Paint.Format.PaintSolid)
|
||||||
|
ot_paint.Color = buildColorIndex(paletteIndex, alpha)
|
||||||
|
return ot_paint
|
||||||
|
|
||||||
paints = [self.build(p) for p in paints]
|
def buildPaintLinearGradient(
|
||||||
|
self,
|
||||||
|
colorLine: _ColorLineInput,
|
||||||
|
p0: _PointTuple,
|
||||||
|
p1: _PointTuple,
|
||||||
|
p2: Optional[_PointTuple] = None,
|
||||||
|
) -> ot.Paint:
|
||||||
|
ot_paint = ot.Paint()
|
||||||
|
ot_paint.Format = int(ot.Paint.Format.PaintLinearGradient)
|
||||||
|
ot_paint.ColorLine = _to_color_line(colorLine)
|
||||||
|
|
||||||
|
if p2 is None:
|
||||||
|
p2 = copy.copy(p1)
|
||||||
|
for i, (x, y) in enumerate((p0, p1, p2)):
|
||||||
|
setattr(ot_paint, f"x{i}", _to_variable_int16(x))
|
||||||
|
setattr(ot_paint, f"y{i}", _to_variable_int16(y))
|
||||||
|
|
||||||
|
return ot_paint
|
||||||
|
|
||||||
|
def buildPaintRadialGradient(
|
||||||
|
self,
|
||||||
|
colorLine: _ColorLineInput,
|
||||||
|
c0: _PointTuple,
|
||||||
|
c1: _PointTuple,
|
||||||
|
r0: _ScalarInput,
|
||||||
|
r1: _ScalarInput,
|
||||||
|
) -> ot.Paint:
|
||||||
|
|
||||||
|
ot_paint = ot.Paint()
|
||||||
|
ot_paint.Format = int(ot.Paint.Format.PaintRadialGradient)
|
||||||
|
ot_paint.ColorLine = _to_color_line(colorLine)
|
||||||
|
|
||||||
|
for i, (x, y), r in [(0, c0, r0), (1, c1, r1)]:
|
||||||
|
setattr(ot_paint, f"x{i}", _to_variable_int16(x))
|
||||||
|
setattr(ot_paint, f"y{i}", _to_variable_int16(y))
|
||||||
|
setattr(ot_paint, f"r{i}", _to_variable_uint16(r))
|
||||||
|
|
||||||
|
return ot_paint
|
||||||
|
|
||||||
|
def buildPaintGlyph(self, glyph: str, paint: _PaintInput) -> ot.Paint:
|
||||||
|
ot_paint = ot.Paint()
|
||||||
|
ot_paint.Format = int(ot.Paint.Format.PaintGlyph)
|
||||||
|
ot_paint.Glyph = glyph
|
||||||
|
ot_paint.Paint = self.buildPaint(paint)
|
||||||
|
return ot_paint
|
||||||
|
|
||||||
|
def buildPaintColrGlyph(self, glyph: str) -> ot.Paint:
|
||||||
|
ot_paint = ot.Paint()
|
||||||
|
ot_paint.Format = int(ot.Paint.Format.PaintColrGlyph)
|
||||||
|
ot_paint.Glyph = glyph
|
||||||
|
return ot_paint
|
||||||
|
|
||||||
|
def buildPaintTransform(
|
||||||
|
self, transform: _AffineInput, paint: _PaintInput
|
||||||
|
) -> ot.Paint:
|
||||||
|
ot_paint = ot.Paint()
|
||||||
|
ot_paint.Format = int(ot.Paint.Format.PaintTransform)
|
||||||
|
if not isinstance(transform, ot.Affine2x3):
|
||||||
|
transform = buildAffine2x3(transform)
|
||||||
|
ot_paint.Transform = transform
|
||||||
|
ot_paint.Paint = self.buildPaint(paint)
|
||||||
|
return ot_paint
|
||||||
|
|
||||||
|
def buildPaintComposite(
|
||||||
|
self,
|
||||||
|
mode: _CompositeInput,
|
||||||
|
source: _PaintInput,
|
||||||
|
backdrop: _PaintInput,
|
||||||
|
):
|
||||||
|
ot_paint = ot.Paint()
|
||||||
|
ot_paint.Format = int(ot.Paint.Format.PaintComposite)
|
||||||
|
ot_paint.SourcePaint = self.buildPaint(source)
|
||||||
|
ot_paint.CompositeMode = _to_composite_mode(mode)
|
||||||
|
ot_paint.BackdropPaint = self.buildPaint(backdrop)
|
||||||
|
return ot_paint
|
||||||
|
|
||||||
|
def buildColrLayers(self, paints: List[_PaintInput]) -> ot.Paint:
|
||||||
|
ot_paint = ot.Paint()
|
||||||
|
ot_paint.Format = int(ot.Paint.Format.PaintColrLayers)
|
||||||
|
self.slices.append(ot_paint)
|
||||||
|
|
||||||
|
paints = [self.buildPaint(p) for p in paints]
|
||||||
|
|
||||||
# Look for reuse, with preference to longer sequences
|
# Look for reuse, with preference to longer sequences
|
||||||
found_reuse = True
|
found_reuse = True
|
||||||
while found_reuse:
|
while found_reuse:
|
||||||
found_reuse = False
|
found_reuse = False
|
||||||
|
|
||||||
ranges = sorted(_reuse_ranges(len(paints)),
|
ranges = sorted(
|
||||||
|
_reuse_ranges(len(paints)),
|
||||||
key=lambda t: (t[1] - t[0], t[1], t[0]),
|
key=lambda t: (t[1] - t[0], t[1], t[0]),
|
||||||
reverse=True)
|
reverse=True,
|
||||||
|
)
|
||||||
for lbound, ubound in ranges:
|
for lbound, ubound in ranges:
|
||||||
reuse_lbound = self.reusePool.get(_as_tuple(paints[lbound:ubound]), -1)
|
reuse_lbound = self.reusePool.get(_as_tuple(paints[lbound:ubound]), -1)
|
||||||
if reuse_lbound == -1:
|
if reuse_lbound == -1:
|
||||||
@ -505,62 +571,56 @@ class LayerCollector:
|
|||||||
found_reuse = True
|
found_reuse = True
|
||||||
break
|
break
|
||||||
|
|
||||||
paint.NumLayers = len(paints)
|
ot_paint.NumLayers = len(paints)
|
||||||
paint.FirstLayerIndex = len(self.layers)
|
ot_paint.FirstLayerIndex = len(self.layers)
|
||||||
self.layers.extend(paints)
|
self.layers.extend(paints)
|
||||||
|
|
||||||
# Register our parts for reuse
|
# Register our parts for reuse
|
||||||
for lbound, ubound in _reuse_ranges(len(paints)):
|
for lbound, ubound in _reuse_ranges(len(paints)):
|
||||||
self.reusePool[_as_tuple(paints[lbound:ubound])] = lbound + paint.FirstLayerIndex
|
self.reusePool[_as_tuple(paints[lbound:ubound])] = (
|
||||||
|
lbound + ot_paint.FirstLayerIndex
|
||||||
|
)
|
||||||
|
|
||||||
return paint
|
return ot_paint
|
||||||
|
|
||||||
def build(self, paint: _PaintInput) -> ot.Paint:
|
def buildPaint(self, paint: _PaintInput) -> ot.Paint:
|
||||||
if isinstance(paint, ot.Paint):
|
if isinstance(paint, ot.Paint):
|
||||||
return paint
|
return paint
|
||||||
elif isinstance(paint, int):
|
elif isinstance(paint, int):
|
||||||
paletteIndex = paint
|
paletteIndex = paint
|
||||||
return buildPaintSolid(paletteIndex)
|
return self.buildPaintSolid(paletteIndex)
|
||||||
elif isinstance(paint, tuple):
|
elif isinstance(paint, tuple):
|
||||||
layerGlyph, paint = paint
|
layerGlyph, paint = paint
|
||||||
return buildPaintGlyph(self, layerGlyph, paint)
|
return self.buildPaintGlyph(layerGlyph, paint)
|
||||||
elif isinstance(paint, list):
|
elif isinstance(paint, list):
|
||||||
# implicit PaintColrLayers for a list of > 1
|
# implicit PaintColrLayers for a list of > 1
|
||||||
if len(paint) == 0:
|
if len(paint) == 0:
|
||||||
raise ValueError("An empty list is hard to paint")
|
raise ValueError("An empty list is hard to paint")
|
||||||
elif len(paint) == 1:
|
elif len(paint) == 1:
|
||||||
return self.build(paint[0])
|
return self.buildPaint(paint[0])
|
||||||
else:
|
else:
|
||||||
return self.buildColrLayers(paint)
|
return self.buildColrLayers(paint)
|
||||||
elif isinstance(paint, collections.abc.Mapping):
|
elif isinstance(paint, collections.abc.Mapping):
|
||||||
kwargs = dict(paint)
|
kwargs = dict(paint)
|
||||||
fmt = kwargs.pop("format")
|
fmt = kwargs.pop("format")
|
||||||
try:
|
try:
|
||||||
return _PAINT_BUILDERS[fmt](self, kwargs)
|
return LayerV1ListBuilder._buildFunctions[fmt](self, **kwargs)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise NotImplementedError(fmt)
|
raise NotImplementedError(fmt)
|
||||||
raise TypeError(
|
raise TypeError(f"Not sure what to do with {type(paint).__name__}: {paint!r}")
|
||||||
f"Not sure what to do with {type(paint).__name__}: {paint!r}"
|
|
||||||
)
|
def build(self) -> ot.LayerV1List:
|
||||||
|
layers = ot.LayerV1List()
|
||||||
|
layers.LayerCount = len(self.layers)
|
||||||
|
layers.Paint = self.layers
|
||||||
|
return layers
|
||||||
|
|
||||||
|
|
||||||
def buildPaintLinearGradient(
|
LayerV1ListBuilder._buildFunctions = {
|
||||||
colorLine: _ColorLineInput,
|
pf.value: getattr(LayerV1ListBuilder, "build" + pf.name)
|
||||||
p0: _PointTuple,
|
for pf in ot.Paint.Format
|
||||||
p1: _PointTuple,
|
if pf != ot.Paint.Format.PaintColrLayers
|
||||||
p2: Optional[_PointTuple] = None,
|
}
|
||||||
) -> ot.Paint:
|
|
||||||
self = ot.Paint()
|
|
||||||
self.Format = int(ot.Paint.Format.PaintLinearGradient)
|
|
||||||
self.ColorLine = _to_color_line(colorLine)
|
|
||||||
|
|
||||||
if p2 is None:
|
|
||||||
p2 = copy.copy(p1)
|
|
||||||
for i, (x, y) in enumerate((p0, p1, p2)):
|
|
||||||
setattr(self, f"x{i}", _to_variable_int16(x))
|
|
||||||
setattr(self, f"y{i}", _to_variable_int16(y))
|
|
||||||
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def buildAffine2x3(transform: _AffineTuple) -> ot.Affine2x3:
|
def buildAffine2x3(transform: _AffineTuple) -> ot.Affine2x3:
|
||||||
@ -581,70 +641,12 @@ def buildAffine2x3(transform: _AffineTuple) -> ot.Affine2x3:
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
def buildPaintRadialGradient(
|
|
||||||
colorLine: _ColorLineInput,
|
|
||||||
c0: _PointTuple,
|
|
||||||
c1: _PointTuple,
|
|
||||||
r0: _ScalarInput,
|
|
||||||
r1: _ScalarInput,
|
|
||||||
) -> ot.Paint:
|
|
||||||
|
|
||||||
self = ot.Paint()
|
|
||||||
self.Format = int(ot.Paint.Format.PaintRadialGradient)
|
|
||||||
self.ColorLine = _to_color_line(colorLine)
|
|
||||||
|
|
||||||
for i, (x, y), r in [(0, c0, r0), (1, c1, r1)]:
|
|
||||||
setattr(self, f"x{i}", _to_variable_int16(x))
|
|
||||||
setattr(self, f"y{i}", _to_variable_int16(y))
|
|
||||||
setattr(self, f"r{i}", _to_variable_uint16(r))
|
|
||||||
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def buildPaintGlyph(layerCollector: LayerCollector, glyph: str, paint: _PaintInput) -> ot.Paint:
|
|
||||||
self = ot.Paint()
|
|
||||||
self.Format = int(ot.Paint.Format.PaintGlyph)
|
|
||||||
self.Glyph = glyph
|
|
||||||
self.Paint = layerCollector.build(paint)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def buildPaintColrGlyph(
|
|
||||||
glyph: str
|
|
||||||
) -> ot.Paint:
|
|
||||||
self = ot.Paint()
|
|
||||||
self.Format = int(ot.Paint.Format.PaintColrGlyph)
|
|
||||||
self.Glyph = glyph
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def buildPaintTransform(layerCollector: LayerCollector, transform: _AffineInput, paint: _PaintInput) -> ot.Paint:
|
|
||||||
self = ot.Paint()
|
|
||||||
self.Format = int(ot.Paint.Format.PaintTransform)
|
|
||||||
if not isinstance(transform, ot.Affine2x3):
|
|
||||||
transform = buildAffine2x3(transform)
|
|
||||||
self.Transform = transform
|
|
||||||
self.Paint = layerCollector.build(paint)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def buildPaintComposite(
|
|
||||||
layerCollector: LayerCollector, mode: _CompositeInput, source: _PaintInput, backdrop: _PaintInput
|
|
||||||
):
|
|
||||||
self = ot.Paint()
|
|
||||||
self.Format = int(ot.Paint.Format.PaintComposite)
|
|
||||||
self.SourcePaint = layerCollector.build(source)
|
|
||||||
self.CompositeMode = _to_composite_mode(mode)
|
|
||||||
self.BackdropPaint = layerCollector.build(backdrop)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def buildBaseGlyphV1Record(
|
def buildBaseGlyphV1Record(
|
||||||
baseGlyph: str, layerCollector: LayerCollector, paint: _PaintInput
|
baseGlyph: str, layerBuilder: LayerV1ListBuilder, paint: _PaintInput
|
||||||
) -> ot.BaseGlyphV1List:
|
) -> ot.BaseGlyphV1List:
|
||||||
self = ot.BaseGlyphV1Record()
|
self = ot.BaseGlyphV1Record()
|
||||||
self.BaseGlyph = baseGlyph
|
self.BaseGlyph = baseGlyph
|
||||||
self.Paint = layerCollector.build(paint)
|
self.Paint = layerBuilder.buildPaint(paint)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
@ -668,10 +670,10 @@ def buildColrV1(
|
|||||||
|
|
||||||
errors = {}
|
errors = {}
|
||||||
baseGlyphs = []
|
baseGlyphs = []
|
||||||
layerCollector = LayerCollector()
|
layerBuilder = LayerV1ListBuilder()
|
||||||
for baseGlyph, paint in colorGlyphItems:
|
for baseGlyph, paint in colorGlyphItems:
|
||||||
try:
|
try:
|
||||||
baseGlyphs.append(buildBaseGlyphV1Record(baseGlyph, layerCollector, paint))
|
baseGlyphs.append(buildBaseGlyphV1Record(baseGlyph, layerBuilder, paint))
|
||||||
|
|
||||||
except (ColorLibError, OverflowError, ValueError, TypeError) as e:
|
except (ColorLibError, OverflowError, ValueError, TypeError) as e:
|
||||||
errors[baseGlyph] = e
|
errors[baseGlyph] = e
|
||||||
@ -682,9 +684,7 @@ def buildColrV1(
|
|||||||
exc.errors = errors
|
exc.errors = errors
|
||||||
raise exc from next(iter(errors.values()))
|
raise exc from next(iter(errors.values()))
|
||||||
|
|
||||||
layers = ot.LayerV1List()
|
layers = layerBuilder.build()
|
||||||
layers.LayerCount = len(layerCollector.layers)
|
|
||||||
layers.Paint = layerCollector.layers
|
|
||||||
glyphs = ot.BaseGlyphV1List()
|
glyphs = ot.BaseGlyphV1List()
|
||||||
glyphs.BaseGlyphCount = len(baseGlyphs)
|
glyphs.BaseGlyphCount = len(baseGlyphs)
|
||||||
glyphs.BaseGlyphV1Record = baseGlyphs
|
glyphs.BaseGlyphV1Record = baseGlyphs
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from fontTools.ttLib import newTable
|
from fontTools.ttLib import newTable
|
||||||
from fontTools.ttLib.tables import otTables as ot
|
from fontTools.ttLib.tables import otTables as ot
|
||||||
from fontTools.colorLib import builder
|
from fontTools.colorLib import builder
|
||||||
from fontTools.colorLib.builder import LayerCollector
|
from fontTools.colorLib.builder import LayerV1ListBuilder
|
||||||
from fontTools.colorLib.errors import ColorLibError
|
from fontTools.colorLib.errors import ColorLibError
|
||||||
import pytest
|
import pytest
|
||||||
from typing import List
|
from typing import List
|
||||||
@ -208,19 +208,21 @@ def test_buildColorIndex():
|
|||||||
|
|
||||||
|
|
||||||
def test_buildPaintSolid():
|
def test_buildPaintSolid():
|
||||||
p = builder.buildPaintSolid(0)
|
p = LayerV1ListBuilder().buildPaintSolid(0)
|
||||||
assert p.Format == ot.Paint.Format.PaintSolid
|
assert p.Format == ot.Paint.Format.PaintSolid
|
||||||
assert p.Color.PaletteIndex == 0
|
assert p.Color.PaletteIndex == 0
|
||||||
assert p.Color.Alpha.value == 1.0
|
assert p.Color.Alpha.value == 1.0
|
||||||
assert p.Color.Alpha.varIdx == 0
|
assert p.Color.Alpha.varIdx == 0
|
||||||
|
|
||||||
p = builder.buildPaintSolid(1, alpha=0.5)
|
p = LayerV1ListBuilder().buildPaintSolid(1, alpha=0.5)
|
||||||
assert p.Format == ot.Paint.Format.PaintSolid
|
assert p.Format == ot.Paint.Format.PaintSolid
|
||||||
assert p.Color.PaletteIndex == 1
|
assert p.Color.PaletteIndex == 1
|
||||||
assert p.Color.Alpha.value == 0.5
|
assert p.Color.Alpha.value == 0.5
|
||||||
assert p.Color.Alpha.varIdx == 0
|
assert p.Color.Alpha.varIdx == 0
|
||||||
|
|
||||||
p = builder.buildPaintSolid(3, alpha=builder.VariableFloat(0.5, varIdx=2))
|
p = LayerV1ListBuilder().buildPaintSolid(
|
||||||
|
3, alpha=builder.VariableFloat(0.5, varIdx=2)
|
||||||
|
)
|
||||||
assert p.Format == ot.Paint.Format.PaintSolid
|
assert p.Format == ot.Paint.Format.PaintSolid
|
||||||
assert p.Color.PaletteIndex == 3
|
assert p.Color.PaletteIndex == 3
|
||||||
assert p.Color.Alpha.value == 0.5
|
assert p.Color.Alpha.value == 0.5
|
||||||
@ -297,6 +299,7 @@ def test_buildAffine2x3():
|
|||||||
|
|
||||||
|
|
||||||
def test_buildPaintLinearGradient():
|
def test_buildPaintLinearGradient():
|
||||||
|
layerBuilder = LayerV1ListBuilder()
|
||||||
color_stops = [
|
color_stops = [
|
||||||
builder.buildColorStop(0.0, 0),
|
builder.buildColorStop(0.0, 0),
|
||||||
builder.buildColorStop(0.5, 1),
|
builder.buildColorStop(0.5, 1),
|
||||||
@ -306,23 +309,24 @@ def test_buildPaintLinearGradient():
|
|||||||
p0 = (builder.VariableInt(100), builder.VariableInt(200))
|
p0 = (builder.VariableInt(100), builder.VariableInt(200))
|
||||||
p1 = (builder.VariableInt(150), builder.VariableInt(250))
|
p1 = (builder.VariableInt(150), builder.VariableInt(250))
|
||||||
|
|
||||||
gradient = builder.buildPaintLinearGradient(color_line, p0, p1)
|
gradient = layerBuilder.buildPaintLinearGradient(color_line, p0, p1)
|
||||||
assert gradient.Format == 2
|
assert gradient.Format == 3
|
||||||
assert gradient.ColorLine == color_line
|
assert gradient.ColorLine == color_line
|
||||||
assert (gradient.x0, gradient.y0) == p0
|
assert (gradient.x0, gradient.y0) == p0
|
||||||
assert (gradient.x1, gradient.y1) == p1
|
assert (gradient.x1, gradient.y1) == p1
|
||||||
assert (gradient.x2, gradient.y2) == p1
|
assert (gradient.x2, gradient.y2) == p1
|
||||||
|
|
||||||
gradient = builder.buildPaintLinearGradient({"stops": color_stops}, p0, p1)
|
gradient = layerBuilder.buildPaintLinearGradient({"stops": color_stops}, p0, p1)
|
||||||
assert gradient.ColorLine.Extend == builder.ExtendMode.PAD
|
assert gradient.ColorLine.Extend == builder.ExtendMode.PAD
|
||||||
assert gradient.ColorLine.ColorStop == color_stops
|
assert gradient.ColorLine.ColorStop == color_stops
|
||||||
|
|
||||||
gradient = builder.buildPaintLinearGradient(color_line, p0, p1, p2=(150, 230))
|
gradient = layerBuilder.buildPaintLinearGradient(color_line, p0, p1, p2=(150, 230))
|
||||||
assert (gradient.x2.value, gradient.y2.value) == (150, 230)
|
assert (gradient.x2.value, gradient.y2.value) == (150, 230)
|
||||||
assert (gradient.x2, gradient.y2) != (gradient.x1, gradient.y1)
|
assert (gradient.x2, gradient.y2) != (gradient.x1, gradient.y1)
|
||||||
|
|
||||||
|
|
||||||
def test_buildPaintRadialGradient():
|
def test_buildPaintRadialGradient():
|
||||||
|
layerBuilder = LayerV1ListBuilder()
|
||||||
color_stops = [
|
color_stops = [
|
||||||
builder.buildColorStop(0.0, 0),
|
builder.buildColorStop(0.0, 0),
|
||||||
builder.buildColorStop(0.5, 1),
|
builder.buildColorStop(0.5, 1),
|
||||||
@ -334,7 +338,7 @@ def test_buildPaintRadialGradient():
|
|||||||
r0 = builder.VariableInt(10)
|
r0 = builder.VariableInt(10)
|
||||||
r1 = builder.VariableInt(5)
|
r1 = builder.VariableInt(5)
|
||||||
|
|
||||||
gradient = builder.buildPaintRadialGradient(color_line, c0, c1, r0, r1)
|
gradient = layerBuilder.buildPaintRadialGradient(color_line, c0, c1, r0, r1)
|
||||||
assert gradient.Format == ot.Paint.Format.PaintRadialGradient
|
assert gradient.Format == ot.Paint.Format.PaintRadialGradient
|
||||||
assert gradient.ColorLine == color_line
|
assert gradient.ColorLine == color_line
|
||||||
assert (gradient.x0, gradient.y0) == c0
|
assert (gradient.x0, gradient.y0) == c0
|
||||||
@ -342,29 +346,31 @@ def test_buildPaintRadialGradient():
|
|||||||
assert gradient.r0 == r0
|
assert gradient.r0 == r0
|
||||||
assert gradient.r1 == r1
|
assert gradient.r1 == r1
|
||||||
|
|
||||||
gradient = builder.buildPaintRadialGradient({"stops": color_stops}, c0, c1, r0, r1)
|
gradient = layerBuilder.buildPaintRadialGradient(
|
||||||
|
{"stops": color_stops}, c0, c1, r0, r1
|
||||||
|
)
|
||||||
assert gradient.ColorLine.Extend == builder.ExtendMode.PAD
|
assert gradient.ColorLine.Extend == builder.ExtendMode.PAD
|
||||||
assert gradient.ColorLine.ColorStop == color_stops
|
assert gradient.ColorLine.ColorStop == color_stops
|
||||||
|
|
||||||
|
|
||||||
def test_buildPaintGlyph_Solid():
|
def test_buildPaintGlyph_Solid():
|
||||||
collector = LayerCollector()
|
layerBuilder = LayerV1ListBuilder()
|
||||||
layer = builder.buildPaintGlyph(collector, "a", 2)
|
layer = layerBuilder.buildPaintGlyph("a", 2)
|
||||||
assert layer.Glyph == "a"
|
assert layer.Glyph == "a"
|
||||||
assert layer.Paint.Format == ot.Paint.Format.PaintSolid
|
assert layer.Paint.Format == ot.Paint.Format.PaintSolid
|
||||||
assert layer.Paint.Color.PaletteIndex == 2
|
assert layer.Paint.Color.PaletteIndex == 2
|
||||||
|
|
||||||
layer = builder.buildPaintGlyph(collector, "a", builder.buildPaintSolid(3, 0.9))
|
layer = layerBuilder.buildPaintGlyph("a", layerBuilder.buildPaintSolid(3, 0.9))
|
||||||
assert layer.Paint.Format == ot.Paint.Format.PaintSolid
|
assert layer.Paint.Format == ot.Paint.Format.PaintSolid
|
||||||
assert layer.Paint.Color.PaletteIndex == 3
|
assert layer.Paint.Color.PaletteIndex == 3
|
||||||
assert layer.Paint.Color.Alpha.value == 0.9
|
assert layer.Paint.Color.Alpha.value == 0.9
|
||||||
|
|
||||||
|
|
||||||
def test_buildPaintGlyph_LinearGradient():
|
def test_buildPaintGlyph_LinearGradient():
|
||||||
layer = builder.buildPaintGlyph(
|
layerBuilder = LayerV1ListBuilder()
|
||||||
LayerCollector(),
|
layer = layerBuilder.buildPaintGlyph(
|
||||||
"a",
|
"a",
|
||||||
builder.buildPaintLinearGradient(
|
layerBuilder.buildPaintLinearGradient(
|
||||||
{"stops": [(0.0, 3), (1.0, 4)]}, (100, 200), (150, 250)
|
{"stops": [(0.0, 3), (1.0, 4)]}, (100, 200), (150, 250)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -380,10 +386,10 @@ def test_buildPaintGlyph_LinearGradient():
|
|||||||
|
|
||||||
|
|
||||||
def test_buildPaintGlyph_RadialGradient():
|
def test_buildPaintGlyph_RadialGradient():
|
||||||
layer = builder.buildPaintGlyph(
|
layerBuilder = LayerV1ListBuilder()
|
||||||
LayerCollector(),
|
layer = layerBuilder.buildPaintGlyph(
|
||||||
"a",
|
"a",
|
||||||
builder.buildPaintRadialGradient(
|
layerBuilder.buildPaintRadialGradient(
|
||||||
{
|
{
|
||||||
"stops": [
|
"stops": [
|
||||||
(0.0, 5),
|
(0.0, 5),
|
||||||
@ -414,18 +420,19 @@ def test_buildPaintGlyph_RadialGradient():
|
|||||||
|
|
||||||
|
|
||||||
def test_buildPaintGlyph_Dict_Solid():
|
def test_buildPaintGlyph_Dict_Solid():
|
||||||
layer = builder.buildPaintGlyph(LayerCollector(), "a", {"format": 1, "paletteIndex": 0})
|
layerBuilder = LayerV1ListBuilder()
|
||||||
|
layer = layerBuilder.buildPaintGlyph("a", {"format": 2, "paletteIndex": 0})
|
||||||
assert layer.Glyph == "a"
|
assert layer.Glyph == "a"
|
||||||
assert layer.Paint.Format == ot.Paint.Format.PaintSolid
|
assert layer.Paint.Format == ot.Paint.Format.PaintSolid
|
||||||
assert layer.Paint.Color.PaletteIndex == 0
|
assert layer.Paint.Color.PaletteIndex == 0
|
||||||
|
|
||||||
|
|
||||||
def test_buildPaintGlyph_Dict_LinearGradient():
|
def test_buildPaintGlyph_Dict_LinearGradient():
|
||||||
layer = builder.buildPaintGlyph(
|
layerBuilder = LayerV1ListBuilder()
|
||||||
LayerCollector(),
|
layer = layerBuilder.buildPaintGlyph(
|
||||||
"a",
|
"a",
|
||||||
{
|
{
|
||||||
"format": 2,
|
"format": 3,
|
||||||
"colorLine": {"stops": [(0.0, 0), (1.0, 1)]},
|
"colorLine": {"stops": [(0.0, 0), (1.0, 1)]},
|
||||||
"p0": (0, 0),
|
"p0": (0, 0),
|
||||||
"p1": (10, 10),
|
"p1": (10, 10),
|
||||||
@ -436,11 +443,11 @@ def test_buildPaintGlyph_Dict_LinearGradient():
|
|||||||
|
|
||||||
|
|
||||||
def test_buildPaintGlyph_Dict_RadialGradient():
|
def test_buildPaintGlyph_Dict_RadialGradient():
|
||||||
layer = builder.buildPaintGlyph(
|
layerBuilder = LayerV1ListBuilder()
|
||||||
LayerCollector(),
|
layer = layerBuilder.buildPaintGlyph(
|
||||||
"a",
|
"a",
|
||||||
{
|
{
|
||||||
"format": 3,
|
"format": 4,
|
||||||
"colorLine": {"stops": [(0.0, 0), (1.0, 1)]},
|
"colorLine": {"stops": [(0.0, 0), (1.0, 1)]},
|
||||||
"c0": (0, 0),
|
"c0": (0, 0),
|
||||||
"c1": (10, 10),
|
"c1": (10, 10),
|
||||||
@ -453,36 +460,36 @@ def test_buildPaintGlyph_Dict_RadialGradient():
|
|||||||
|
|
||||||
|
|
||||||
def test_buildPaintColrGlyph():
|
def test_buildPaintColrGlyph():
|
||||||
paint = builder.buildPaintColrGlyph("a")
|
paint = LayerV1ListBuilder().buildPaintColrGlyph("a")
|
||||||
assert paint.Format == ot.Paint.Format.PaintColrGlyph
|
assert paint.Format == ot.Paint.Format.PaintColrGlyph
|
||||||
assert paint.Glyph == "a"
|
assert paint.Glyph == "a"
|
||||||
|
|
||||||
|
|
||||||
def test_buildPaintTransform():
|
def test_buildPaintTransform():
|
||||||
paint = builder.buildPaintTransform(
|
layerBuilder = LayerV1ListBuilder()
|
||||||
layerCollector=LayerCollector(),
|
paint = layerBuilder.buildPaintTransform(
|
||||||
transform=builder.buildAffine2x3((1, 2, 3, 4, 5, 6)),
|
transform=builder.buildAffine2x3((1, 2, 3, 4, 5, 6)),
|
||||||
paint=builder.buildPaintGlyph(
|
paint=layerBuilder.buildPaintGlyph(
|
||||||
layerCollector=LayerCollector(),
|
|
||||||
glyph="a",
|
glyph="a",
|
||||||
paint=builder.buildPaintSolid(paletteIndex=0, alpha=1.0),
|
paint=layerBuilder.buildPaintSolid(paletteIndex=0, alpha=1.0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert paint.Format == ot.Paint.Format.PaintTransform
|
assert paint.Format == ot.Paint.Format.PaintTransform
|
||||||
|
assert paint.Paint.Format == ot.Paint.Format.PaintGlyph
|
||||||
|
assert paint.Paint.Paint.Format == ot.Paint.Format.PaintSolid
|
||||||
|
|
||||||
assert paint.Transform.xx.value == 1.0
|
assert paint.Transform.xx.value == 1.0
|
||||||
assert paint.Transform.yx.value == 2.0
|
assert paint.Transform.yx.value == 2.0
|
||||||
assert paint.Transform.xy.value == 3.0
|
assert paint.Transform.xy.value == 3.0
|
||||||
assert paint.Transform.yy.value == 4.0
|
assert paint.Transform.yy.value == 4.0
|
||||||
assert paint.Transform.dx.value == 5.0
|
assert paint.Transform.dx.value == 5.0
|
||||||
assert paint.Transform.dy.value == 6.0
|
assert paint.Transform.dy.value == 6.0
|
||||||
assert paint.Paint.Format == ot.Paint.Format.PaintGlyph
|
|
||||||
|
|
||||||
paint = builder.buildPaintTransform(
|
paint = layerBuilder.buildPaintTransform(
|
||||||
LayerCollector(),
|
|
||||||
(1, 0, 0, 0.3333, 10, 10),
|
(1, 0, 0, 0.3333, 10, 10),
|
||||||
{
|
{
|
||||||
"format": 3,
|
"format": 4,
|
||||||
"colorLine": {"stops": [(0.0, 0), (1.0, 1)]},
|
"colorLine": {"stops": [(0.0, 0), (1.0, 1)]},
|
||||||
"c0": (100, 100),
|
"c0": (100, 100),
|
||||||
"c1": (100, 100),
|
"c1": (100, 100),
|
||||||
@ -502,18 +509,17 @@ def test_buildPaintTransform():
|
|||||||
|
|
||||||
|
|
||||||
def test_buildPaintComposite():
|
def test_buildPaintComposite():
|
||||||
collector = LayerCollector()
|
layerBuilder = LayerV1ListBuilder()
|
||||||
composite = builder.buildPaintComposite(
|
composite = layerBuilder.buildPaintComposite(
|
||||||
layerCollector=collector,
|
|
||||||
mode=ot.CompositeMode.SRC_OVER,
|
mode=ot.CompositeMode.SRC_OVER,
|
||||||
source={
|
source={
|
||||||
"format": 7,
|
"format": 8,
|
||||||
"mode": "src_over",
|
"mode": "src_over",
|
||||||
"source": {"format": 4, "glyph": "c", "paint": 2},
|
"source": {"format": 5, "glyph": "c", "paint": 2},
|
||||||
"backdrop": {"format": 4, "glyph": "b", "paint": 1},
|
"backdrop": {"format": 5, "glyph": "b", "paint": 1},
|
||||||
},
|
},
|
||||||
backdrop=builder.buildPaintGlyph(
|
backdrop=layerBuilder.buildPaintGlyph(
|
||||||
collector, "a", builder.buildPaintSolid(paletteIndex=0, alpha=1.0)
|
"a", layerBuilder.buildPaintSolid(paletteIndex=0, alpha=1.0)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -541,11 +547,11 @@ def test_buildColrV1():
|
|||||||
colorGlyphs = {
|
colorGlyphs = {
|
||||||
"a": [("b", 0), ("c", 1)],
|
"a": [("b", 0), ("c", 1)],
|
||||||
"d": [
|
"d": [
|
||||||
("e", {"format": 1, "paletteIndex": 2, "alpha": 0.8}),
|
("e", {"format": 2, "paletteIndex": 2, "alpha": 0.8}),
|
||||||
(
|
(
|
||||||
"f",
|
"f",
|
||||||
{
|
{
|
||||||
"format": 3,
|
"format": 4,
|
||||||
"colorLine": {"stops": [(0.0, 3), (1.0, 4)], "extend": "reflect"},
|
"colorLine": {"stops": [(0.0, 3), (1.0, 4)], "extend": "reflect"},
|
||||||
"c0": (0, 0),
|
"c0": (0, 0),
|
||||||
"c1": (0, 0),
|
"c1": (0, 0),
|
||||||
@ -583,6 +589,7 @@ def test_buildColrV1():
|
|||||||
|
|
||||||
|
|
||||||
def test_split_color_glyphs_by_version():
|
def test_split_color_glyphs_by_version():
|
||||||
|
layerBuilder = LayerV1ListBuilder()
|
||||||
colorGlyphs = {
|
colorGlyphs = {
|
||||||
"a": [
|
"a": [
|
||||||
("b", 0),
|
("b", 0),
|
||||||
@ -597,7 +604,9 @@ def test_split_color_glyphs_by_version():
|
|||||||
assert colorGlyphsV0 == {"a": [("b", 0), ("c", 1), ("d", 2), ("e", 3)]}
|
assert colorGlyphsV0 == {"a": [("b", 0), ("c", 1), ("d", 2), ("e", 3)]}
|
||||||
assert not colorGlyphsV1
|
assert not colorGlyphsV1
|
||||||
|
|
||||||
colorGlyphs = {"a": [("b", builder.buildPaintSolid(paletteIndex=0, alpha=0.0))]}
|
colorGlyphs = {
|
||||||
|
"a": [("b", layerBuilder.buildPaintSolid(paletteIndex=0, alpha=0.0))]
|
||||||
|
}
|
||||||
|
|
||||||
colorGlyphsV0, colorGlyphsV1 = builder._split_color_glyphs_by_version(colorGlyphs)
|
colorGlyphsV0, colorGlyphsV1 = builder._split_color_glyphs_by_version(colorGlyphs)
|
||||||
|
|
||||||
@ -611,7 +620,7 @@ def test_split_color_glyphs_by_version():
|
|||||||
(
|
(
|
||||||
"e",
|
"e",
|
||||||
{
|
{
|
||||||
"format": 2,
|
"format": 3,
|
||||||
"colorLine": {"stops": [(0.0, 2), (1.0, 3)]},
|
"colorLine": {"stops": [(0.0, 2), (1.0, 3)]},
|
||||||
"p0": (0, 0),
|
"p0": (0, 0),
|
||||||
"p1": (10, 10),
|
"p1": (10, 10),
|
||||||
@ -647,25 +656,27 @@ def test_build_layerv1list_empty():
|
|||||||
colr = builder.buildCOLR(
|
colr = builder.buildCOLR(
|
||||||
{
|
{
|
||||||
"a": {
|
"a": {
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": {"format": 1, "paletteIndex": 2, "alpha": 0.8},
|
"paint": {"format": 2, "paletteIndex": 2, "alpha": 0.8},
|
||||||
"glyph": "b",
|
"glyph": "b",
|
||||||
},
|
},
|
||||||
# A list of 1 shouldn't become a PaintColrLayers
|
# A list of 1 shouldn't become a PaintColrLayers
|
||||||
"b": [{
|
"b": [
|
||||||
"format": 4, # PaintGlyph
|
{
|
||||||
"paint": {
|
"format": 5, # PaintGlyph
|
||||||
"format": 2,
|
"paint": {
|
||||||
"colorLine": {
|
"format": 3,
|
||||||
"stops": [(0.0, 2), (1.0, 3)],
|
"colorLine": {
|
||||||
"extend": "reflect",
|
"stops": [(0.0, 2), (1.0, 3)],
|
||||||
|
"extend": "reflect",
|
||||||
|
},
|
||||||
|
"p0": (1, 2),
|
||||||
|
"p1": (3, 4),
|
||||||
|
"p2": (2, 2),
|
||||||
},
|
},
|
||||||
"p0": (1, 2),
|
"glyph": "bb",
|
||||||
"p1": (3, 4),
|
}
|
||||||
"p2": (2, 2),
|
],
|
||||||
},
|
|
||||||
"glyph": "bb",
|
|
||||||
}],
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -687,26 +698,28 @@ def _paint_names(paints) -> List[str]:
|
|||||||
if paint.Format == int(ot.Paint.Format.PaintGlyph):
|
if paint.Format == int(ot.Paint.Format.PaintGlyph):
|
||||||
result.append(paint.Glyph)
|
result.append(paint.Glyph)
|
||||||
elif paint.Format == int(ot.Paint.Format.PaintColrLayers):
|
elif paint.Format == int(ot.Paint.Format.PaintColrLayers):
|
||||||
result.append(f"Layers[{paint.FirstLayerIndex}:{paint.FirstLayerIndex+paint.NumLayers}]")
|
result.append(
|
||||||
|
f"Layers[{paint.FirstLayerIndex}:{paint.FirstLayerIndex+paint.NumLayers}]"
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def test_build_layerv1list_simple():
|
def test_build_layerv1list_simple():
|
||||||
# Two colr glyphs, each with two layers the first of which is common
|
# Two colr glyphs, each with two layers the first of which is common
|
||||||
# All layers use the same solid paint
|
# All layers use the same solid paint
|
||||||
solid_paint = {"format": 1, "paletteIndex": 2, "alpha": 0.8}
|
solid_paint = {"format": 2, "paletteIndex": 2, "alpha": 0.8}
|
||||||
backdrop = {
|
backdrop = {
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": solid_paint,
|
"paint": solid_paint,
|
||||||
"glyph": "back",
|
"glyph": "back",
|
||||||
}
|
}
|
||||||
a_foreground = {
|
a_foreground = {
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": solid_paint,
|
"paint": solid_paint,
|
||||||
"glyph": "a_fore",
|
"glyph": "a_fore",
|
||||||
}
|
}
|
||||||
b_foreground = {
|
b_foreground = {
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": solid_paint,
|
"paint": solid_paint,
|
||||||
"glyph": "b_fore",
|
"glyph": "b_fore",
|
||||||
}
|
}
|
||||||
@ -733,41 +746,46 @@ def test_build_layerv1list_simple():
|
|||||||
assert colr.table.BaseGlyphV1List.BaseGlyphCount == 2
|
assert colr.table.BaseGlyphV1List.BaseGlyphCount == 2
|
||||||
assert len(colr.table.BaseGlyphV1List.BaseGlyphV1Record) == 2
|
assert len(colr.table.BaseGlyphV1List.BaseGlyphV1Record) == 2
|
||||||
assert colr.table.LayerV1List.LayerCount == 4
|
assert colr.table.LayerV1List.LayerCount == 4
|
||||||
assert _paint_names(colr.table.LayerV1List.Paint) == ["back", "a_fore", "back", "b_fore"]
|
assert _paint_names(colr.table.LayerV1List.Paint) == [
|
||||||
|
"back",
|
||||||
|
"a_fore",
|
||||||
|
"back",
|
||||||
|
"b_fore",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_build_layerv1list_with_sharing():
|
def test_build_layerv1list_with_sharing():
|
||||||
# Three colr glyphs, each with two layers in common
|
# Three colr glyphs, each with two layers in common
|
||||||
solid_paint = {"format": 1, "paletteIndex": 2, "alpha": 0.8}
|
solid_paint = {"format": 2, "paletteIndex": 2, "alpha": 0.8}
|
||||||
backdrop = [
|
backdrop = [
|
||||||
{
|
{
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": solid_paint,
|
"paint": solid_paint,
|
||||||
"glyph": "back1",
|
"glyph": "back1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": solid_paint,
|
"paint": solid_paint,
|
||||||
"glyph": "back2",
|
"glyph": "back2",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
a_foreground = {
|
a_foreground = {
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": solid_paint,
|
"paint": solid_paint,
|
||||||
"glyph": "a_fore",
|
"glyph": "a_fore",
|
||||||
}
|
}
|
||||||
b_background = {
|
b_background = {
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": solid_paint,
|
"paint": solid_paint,
|
||||||
"glyph": "b_back",
|
"glyph": "b_back",
|
||||||
}
|
}
|
||||||
b_foreground = {
|
b_foreground = {
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": solid_paint,
|
"paint": solid_paint,
|
||||||
"glyph": "b_fore",
|
"glyph": "b_fore",
|
||||||
}
|
}
|
||||||
c_background = {
|
c_background = {
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": solid_paint,
|
"paint": solid_paint,
|
||||||
"glyph": "c_back",
|
"glyph": "c_back",
|
||||||
}
|
}
|
||||||
@ -789,17 +807,29 @@ def test_build_layerv1list_with_sharing():
|
|||||||
baseGlyphs = colr.table.BaseGlyphV1List.BaseGlyphV1Record
|
baseGlyphs = colr.table.BaseGlyphV1List.BaseGlyphV1Record
|
||||||
assert colr.table.BaseGlyphV1List.BaseGlyphCount == 3
|
assert colr.table.BaseGlyphV1List.BaseGlyphCount == 3
|
||||||
assert len(baseGlyphs) == 3
|
assert len(baseGlyphs) == 3
|
||||||
assert (_paint_names([b.Paint for b in baseGlyphs]) ==
|
assert _paint_names([b.Paint for b in baseGlyphs]) == [
|
||||||
["Layers[0:3]", "Layers[3:6]", "Layers[6:8]"])
|
"Layers[0:3]",
|
||||||
assert (_paint_names(colr.table.LayerV1List.Paint) ==
|
"Layers[3:6]",
|
||||||
["back1", "back2", "a_fore", "b_back", "Layers[0:2]", "b_fore", "c_back", "Layers[0:2]"])
|
"Layers[6:8]",
|
||||||
|
]
|
||||||
|
assert _paint_names(colr.table.LayerV1List.Paint) == [
|
||||||
|
"back1",
|
||||||
|
"back2",
|
||||||
|
"a_fore",
|
||||||
|
"b_back",
|
||||||
|
"Layers[0:2]",
|
||||||
|
"b_fore",
|
||||||
|
"c_back",
|
||||||
|
"Layers[0:2]",
|
||||||
|
]
|
||||||
assert colr.table.LayerV1List.LayerCount == 8
|
assert colr.table.LayerV1List.LayerCount == 8
|
||||||
|
|
||||||
|
|
||||||
def test_build_layerv1list_with_overlaps():
|
def test_build_layerv1list_with_overlaps():
|
||||||
paints = [
|
paints = [
|
||||||
{
|
{
|
||||||
"format": 4, # PaintGlyph
|
"format": 5, # PaintGlyph
|
||||||
"paint": {"format": 1, "paletteIndex": 2, "alpha": 0.8},
|
"paint": {"format": 2, "paletteIndex": 2, "alpha": 0.8},
|
||||||
"glyph": c,
|
"glyph": c,
|
||||||
}
|
}
|
||||||
for c in "abcdefghi"
|
for c in "abcdefghi"
|
||||||
@ -818,14 +848,29 @@ def test_build_layerv1list_with_overlaps():
|
|||||||
assertNoV0Content(colr)
|
assertNoV0Content(colr)
|
||||||
|
|
||||||
baseGlyphs = colr.table.BaseGlyphV1List.BaseGlyphV1Record
|
baseGlyphs = colr.table.BaseGlyphV1List.BaseGlyphV1Record
|
||||||
#assert colr.table.BaseGlyphV1List.BaseGlyphCount == 2
|
# assert colr.table.BaseGlyphV1List.BaseGlyphCount == 2
|
||||||
|
|
||||||
assert (_paint_names(colr.table.LayerV1List.Paint) ==
|
assert _paint_names(colr.table.LayerV1List.Paint) == [
|
||||||
["a", "b", "c", "d", "Layers[0:4]", "e", "f", "Layers[2:4]", "Layers[5:7]", "g", "h"])
|
"a",
|
||||||
assert (_paint_names([b.Paint for b in baseGlyphs]) ==
|
"b",
|
||||||
["Layers[0:4]", "Layers[4:7]", "Layers[7:11]"])
|
"c",
|
||||||
|
"d",
|
||||||
|
"Layers[0:4]",
|
||||||
|
"e",
|
||||||
|
"f",
|
||||||
|
"Layers[2:4]",
|
||||||
|
"Layers[5:7]",
|
||||||
|
"g",
|
||||||
|
"h",
|
||||||
|
]
|
||||||
|
assert _paint_names([b.Paint for b in baseGlyphs]) == [
|
||||||
|
"Layers[0:4]",
|
||||||
|
"Layers[4:7]",
|
||||||
|
"Layers[7:11]",
|
||||||
|
]
|
||||||
assert colr.table.LayerV1List.LayerCount == 11
|
assert colr.table.LayerV1List.LayerCount == 11
|
||||||
|
|
||||||
|
|
||||||
class BuildCOLRTest(object):
|
class BuildCOLRTest(object):
|
||||||
def test_automatic_version_all_solid_color_glyphs(self):
|
def test_automatic_version_all_solid_color_glyphs(self):
|
||||||
colr = builder.buildCOLR({"a": [("b", 0), ("c", 1)]})
|
colr = builder.buildCOLR({"a": [("b", 0), ("c", 1)]})
|
||||||
@ -841,7 +886,7 @@ class BuildCOLRTest(object):
|
|||||||
(
|
(
|
||||||
"b",
|
"b",
|
||||||
{
|
{
|
||||||
"format": 3,
|
"format": 4,
|
||||||
"colorLine": {
|
"colorLine": {
|
||||||
"stops": [(0.0, 0), (1.0, 1)],
|
"stops": [(0.0, 0), (1.0, 1)],
|
||||||
"extend": "repeat",
|
"extend": "repeat",
|
||||||
@ -852,13 +897,13 @@ class BuildCOLRTest(object):
|
|||||||
"r1": 2,
|
"r1": 2,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
("c", {"format": 1, "paletteIndex": 2, "alpha": 0.8}),
|
("c", {"format": 2, "paletteIndex": 2, "alpha": 0.8}),
|
||||||
],
|
],
|
||||||
"d": [
|
"d": [
|
||||||
(
|
(
|
||||||
"e",
|
"e",
|
||||||
{
|
{
|
||||||
"format": 2,
|
"format": 3,
|
||||||
"colorLine": {
|
"colorLine": {
|
||||||
"stops": [(0.0, 2), (1.0, 3)],
|
"stops": [(0.0, 2), (1.0, 3)],
|
||||||
"extend": "reflect",
|
"extend": "reflect",
|
||||||
@ -885,14 +930,14 @@ class BuildCOLRTest(object):
|
|||||||
(
|
(
|
||||||
"e",
|
"e",
|
||||||
{
|
{
|
||||||
"format": 2,
|
"format": 3,
|
||||||
"colorLine": {"stops": [(0.0, 2), (1.0, 3)]},
|
"colorLine": {"stops": [(0.0, 2), (1.0, 3)]},
|
||||||
"p0": (1, 2),
|
"p0": (1, 2),
|
||||||
"p1": (3, 4),
|
"p1": (3, 4),
|
||||||
"p2": (2, 2),
|
"p2": (2, 2),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
("f", {"format": 1, "paletteIndex": 2, "alpha": 0.8}),
|
("f", {"format": 2, "paletteIndex": 2, "alpha": 0.8}),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -910,9 +955,7 @@ class BuildCOLRTest(object):
|
|||||||
colr.table.BaseGlyphV1List.BaseGlyphV1Record[0], ot.BaseGlyphV1Record
|
colr.table.BaseGlyphV1List.BaseGlyphV1Record[0], ot.BaseGlyphV1Record
|
||||||
)
|
)
|
||||||
assert colr.table.BaseGlyphV1List.BaseGlyphV1Record[0].BaseGlyph == "d"
|
assert colr.table.BaseGlyphV1List.BaseGlyphV1Record[0].BaseGlyph == "d"
|
||||||
assert isinstance(
|
assert isinstance(colr.table.LayerV1List, ot.LayerV1List)
|
||||||
colr.table.LayerV1List, ot.LayerV1List
|
|
||||||
)
|
|
||||||
assert colr.table.LayerV1List.Paint[0].Glyph == "e"
|
assert colr.table.LayerV1List.Paint[0].Glyph == "e"
|
||||||
|
|
||||||
def test_explicit_version_0(self):
|
def test_explicit_version_0(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user