Merge pull request #2008 from fonttools/colrv1-rev2

Update COLRv1 impl following proposed changes in the draft spec
This commit is contained in:
Cosimo Lupo 2020-07-10 09:57:00 +01:00 committed by GitHub
commit 4594a0c378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 253 additions and 309 deletions

View File

@ -35,7 +35,6 @@ _ColorStopsList = Sequence[_ColorStopInput]
_ExtendInput = Union[int, str, ExtendMode] _ExtendInput = Union[int, str, ExtendMode]
_ColorLineInput = Union[_Kwargs, ot.ColorLine] _ColorLineInput = Union[_Kwargs, ot.ColorLine]
_PointTuple = Tuple[_ScalarInput, _ScalarInput] _PointTuple = Tuple[_ScalarInput, _ScalarInput]
_PointInput = Union[_PointTuple, ot.Point]
_AffineTuple = Tuple[_ScalarInput, _ScalarInput, _ScalarInput, _ScalarInput] _AffineTuple = Tuple[_ScalarInput, _ScalarInput, _ScalarInput, _ScalarInput]
_AffineInput = Union[_AffineTuple, ot.Affine2x2] _AffineInput = Union[_AffineTuple, ot.Affine2x2]
@ -132,7 +131,7 @@ def buildCOLR(
colr.BaseGlyphRecordArray = colr.LayerRecordArray = None colr.BaseGlyphRecordArray = colr.LayerRecordArray = None
if colorGlyphsV1: if colorGlyphsV1:
colr.BaseGlyphV1Array = buildBaseGlyphV1Array(colorGlyphsV1, glyphMap) colr.BaseGlyphV1List = buildBaseGlyphV1List(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
@ -275,7 +274,7 @@ def buildCPAL(
# COLR v1 tables # COLR v1 tables
# See draft proposal at: https://github.com/googlefonts/colr-gradients-spec # See draft proposal at: https://github.com/googlefonts/colr-gradients-spec
_DEFAULT_TRANSPARENCY = VariableFloat(0.0) _DEFAULT_ALPHA = VariableFloat(1.0)
def _splitSolidAndGradientGlyphs( def _splitSolidAndGradientGlyphs(
@ -290,7 +289,7 @@ def _splitSolidAndGradientGlyphs(
paint = _to_ot_paint(paint) paint = _to_ot_paint(paint)
if ( if (
paint.Format != 1 paint.Format != 1
or paint.Color.Transparency.value != _DEFAULT_TRANSPARENCY.value or paint.Color.Alpha.value != _DEFAULT_ALPHA.value
): ):
allSolidColors = False allSolidColors = False
newLayers.append((layerGlyph, paint)) newLayers.append((layerGlyph, paint))
@ -323,32 +322,32 @@ _to_variable_float = partial(_to_variable_value, cls=VariableFloat)
_to_variable_int = partial(_to_variable_value, cls=VariableInt) _to_variable_int = partial(_to_variable_value, cls=VariableInt)
def buildColor( def buildColorIndex(
paletteIndex: int, transparency: _ScalarInput = _DEFAULT_TRANSPARENCY paletteIndex: int, alpha: _ScalarInput = _DEFAULT_ALPHA
) -> ot.Color: ) -> ot.ColorIndex:
self = ot.Color() self = ot.ColorIndex()
self.PaletteIndex = int(paletteIndex) self.PaletteIndex = int(paletteIndex)
self.Transparency = _to_variable_float(transparency) self.Alpha = _to_variable_float(alpha)
return self return self
def buildSolidColorPaint( def buildSolidColorPaint(
paletteIndex: int, transparency: _ScalarInput = _DEFAULT_TRANSPARENCY paletteIndex: int, alpha: _ScalarInput = _DEFAULT_ALPHA
) -> ot.Paint: ) -> ot.Paint:
self = ot.Paint() self = ot.Paint()
self.Format = 1 self.Format = 1
self.Color = buildColor(paletteIndex, transparency) self.Color = buildColorIndex(paletteIndex, alpha)
return self return self
def buildColorStop( def buildColorStop(
offset: _ScalarInput, offset: _ScalarInput,
paletteIndex: int, paletteIndex: int,
transparency: _ScalarInput = _DEFAULT_TRANSPARENCY, alpha: _ScalarInput = _DEFAULT_ALPHA,
) -> ot.ColorStop: ) -> ot.ColorStop:
self = ot.ColorStop() self = ot.ColorStop()
self.StopOffset = _to_variable_float(offset) self.StopOffset = _to_variable_float(offset)
self.Color = buildColor(paletteIndex, transparency) self.Color = buildColorIndex(paletteIndex, alpha)
return self return self
@ -380,20 +379,6 @@ def buildColorLine(
return self return self
def buildPoint(x: _ScalarInput, y: _ScalarInput) -> ot.Point:
self = ot.Point()
# positions are encoded as Int16 so round to int
self.x = _to_variable_int(x)
self.y = _to_variable_int(y)
return self
def _to_variable_point(pt: _PointInput) -> ot.Point:
if isinstance(pt, ot.Point):
return pt
return buildPoint(*pt)
def _to_color_line(obj): def _to_color_line(obj):
if isinstance(obj, ot.ColorLine): if isinstance(obj, ot.ColorLine):
return obj return obj
@ -404,9 +389,9 @@ def _to_color_line(obj):
def buildLinearGradientPaint( def buildLinearGradientPaint(
colorLine: _ColorLineInput, colorLine: _ColorLineInput,
p0: _PointInput, p0: _PointTuple,
p1: _PointInput, p1: _PointTuple,
p2: Optional[_PointInput] = None, p2: Optional[_PointTuple] = None,
) -> ot.Paint: ) -> ot.Paint:
self = ot.Paint() self = ot.Paint()
self.Format = 2 self.Format = 2
@ -414,8 +399,9 @@ def buildLinearGradientPaint(
if p2 is None: if p2 is None:
p2 = copy.copy(p1) p2 = copy.copy(p1)
for i, pt in enumerate((p0, p1, p2)): for i, (x, y) in enumerate((p0, p1, p2)):
setattr(self, f"p{i}", _to_variable_point(pt)) setattr(self, f"x{i}", _to_variable_int(x))
setattr(self, f"y{i}", _to_variable_int(y))
return self return self
@ -433,27 +419,25 @@ def buildAffine2x2(
def buildRadialGradientPaint( def buildRadialGradientPaint(
colorLine: _ColorLineInput, colorLine: _ColorLineInput,
c0: _PointInput, c0: _PointTuple,
c1: _PointInput, c1: _PointTuple,
r0: _ScalarInput, r0: _ScalarInput,
r1: _ScalarInput, r1: _ScalarInput,
affine: Optional[_AffineInput] = None, transform: Optional[_AffineInput] = None,
) -> ot.Paint: ) -> ot.Paint:
self = ot.Paint() self = ot.Paint()
self.Format = 3 self.Format = 3
self.ColorLine = _to_color_line(colorLine) self.ColorLine = _to_color_line(colorLine)
for i, pt in [(0, c0), (1, c1)]: for i, (x, y), r in [(0, c0, r0), (1, c1, r1)]:
setattr(self, f"c{i}", _to_variable_point(pt)) setattr(self, f"x{i}", _to_variable_int(x))
setattr(self, f"y{i}", _to_variable_int(y))
for i, r in [(0, r0), (1, r1)]:
# distances are encoded as UShort so we round to int
setattr(self, f"r{i}", _to_variable_int(r)) setattr(self, f"r{i}", _to_variable_int(r))
if affine is not None and not isinstance(affine, ot.Affine2x2): if transform is not None and not isinstance(transform, ot.Affine2x2):
affine = buildAffine2x2(*affine) transform = buildAffine2x2(*transform)
self.Affine = affine self.Transform = transform
return self return self
@ -476,10 +460,10 @@ def buildLayerV1Record(layerGlyph: str, paint: _PaintInput) -> ot.LayerV1Record:
return self return self
def buildLayerV1Array( def buildLayerV1List(
layers: Sequence[Union[_LayerTuple, ot.LayerV1Record]] layers: Sequence[Union[_LayerTuple, ot.LayerV1Record]]
) -> ot.LayerV1Array: ) -> ot.LayerV1List:
self = ot.LayerV1Array() self = ot.LayerV1List()
self.LayerCount = len(layers) self.LayerCount = len(layers)
records = [] records = []
for layer in layers: for layer in layers:
@ -494,20 +478,20 @@ def buildLayerV1Array(
def buildBaseGlyphV1Record( def buildBaseGlyphV1Record(
baseGlyph: str, layers: Union[_LayersList, ot.LayerV1Array] baseGlyph: str, layers: Union[_LayersList, ot.LayerV1List]
) -> ot.BaseGlyphV1Array: ) -> ot.BaseGlyphV1List:
self = ot.BaseGlyphV1Record() self = ot.BaseGlyphV1Record()
self.BaseGlyph = baseGlyph self.BaseGlyph = baseGlyph
if not isinstance(layers, ot.LayerV1Array): if not isinstance(layers, ot.LayerV1List):
layers = buildLayerV1Array(layers) layers = buildLayerV1List(layers)
self.LayerV1Array = layers self.LayerV1List = layers
return self return self
def buildBaseGlyphV1Array( def buildBaseGlyphV1List(
colorGlyphs: Union[_ColorGlyphsDict, Dict[str, ot.LayerV1Array]], colorGlyphs: Union[_ColorGlyphsDict, Dict[str, ot.LayerV1List]],
glyphMap: Optional[Mapping[str, int]] = None, glyphMap: Optional[Mapping[str, int]] = None,
) -> ot.BaseGlyphV1Array: ) -> ot.BaseGlyphV1List:
if glyphMap is not None: if glyphMap is not None:
colorGlyphItems = sorted( colorGlyphItems = sorted(
colorGlyphs.items(), key=lambda item: glyphMap[item[0]] colorGlyphs.items(), key=lambda item: glyphMap[item[0]]
@ -518,7 +502,7 @@ def buildBaseGlyphV1Array(
buildBaseGlyphV1Record(baseGlyph, layers) buildBaseGlyphV1Record(baseGlyph, layers)
for baseGlyph, layers in colorGlyphItems for baseGlyph, layers in colorGlyphItems
] ]
self = ot.BaseGlyphV1Array() self = ot.BaseGlyphV1List()
self.BaseGlyphCount = len(records) self.BaseGlyphCount = len(records)
self.BaseGlyphV1Record = records self.BaseGlyphV1Record = records
return self return self

View File

@ -134,48 +134,38 @@ class OTTableReader(object):
offset = self.offset + offset offset = self.offset + offset
return self.__class__(self.data, self.localState, offset, self.tableTag) return self.__class__(self.data, self.localState, offset, self.tableTag)
def readUShort(self): def readValue(self, typecode, staticSize):
pos = self.pos pos = self.pos
newpos = pos + 2 newpos = pos + staticSize
value, = struct.unpack(">H", self.data[pos:newpos]) value, = struct.unpack(f">{typecode}", self.data[pos:newpos])
self.pos = newpos self.pos = newpos
return value return value
def readUShortArray(self, count): def readUShort(self):
return self.readValue("H", staticSize=2)
def readArray(self, typecode, staticSize, count):
pos = self.pos pos = self.pos
newpos = pos + count * 2 newpos = pos + count * staticSize
value = array.array("H", self.data[pos:newpos]) value = array.array(typecode, self.data[pos:newpos])
if sys.byteorder != "big": value.byteswap() if sys.byteorder != "big": value.byteswap()
self.pos = newpos self.pos = newpos
return value return value
def readUShortArray(self, count):
return self.readArray("H", staticSize=2, count=count)
def readInt8(self): def readInt8(self):
pos = self.pos return self.readValue("b", staticSize=1)
newpos = pos + 1
value, = struct.unpack(">b", self.data[pos:newpos])
self.pos = newpos
return value
def readShort(self): def readShort(self):
pos = self.pos return self.readValue("h", staticSize=2)
newpos = pos + 2
value, = struct.unpack(">h", self.data[pos:newpos])
self.pos = newpos
return value
def readLong(self): def readLong(self):
pos = self.pos return self.readValue("l", staticSize=4)
newpos = pos + 4
value, = struct.unpack(">l", self.data[pos:newpos])
self.pos = newpos
return value
def readUInt8(self): def readUInt8(self):
pos = self.pos return self.readValue("B", staticSize=1)
newpos = pos + 1
value, = struct.unpack(">B", self.data[pos:newpos])
self.pos = newpos
return value
def readUInt24(self): def readUInt24(self):
pos = self.pos pos = self.pos
@ -185,11 +175,7 @@ class OTTableReader(object):
return value return value
def readULong(self): def readULong(self):
pos = self.pos return self.readValue("L", staticSize=4)
newpos = pos + 4
value, = struct.unpack(">L", self.data[pos:newpos])
self.pos = newpos
return value
def readTag(self): def readTag(self):
pos = self.pos pos = self.pos
@ -417,6 +403,9 @@ class OTTableWriter(object):
# But we just care about first one right now. # But we just care about first one right now.
return subwriter return subwriter
def writeValue(self, typecode, value):
self.items.append(struct.pack(f">{typecode}", value))
def writeUShort(self, value): def writeUShort(self, value):
assert 0 <= value < 0x10000, value assert 0 <= value < 0x10000, value
self.items.append(struct.pack(">H", value)) self.items.append(struct.pack(">H", value))

View File

@ -295,9 +295,10 @@ class Tag(SimpleValue):
class GlyphID(SimpleValue): class GlyphID(SimpleValue):
staticSize = 2 staticSize = 2
typecode = "H"
def readArray(self, reader, font, tableDict, count): def readArray(self, reader, font, tableDict, count):
glyphOrder = font.getGlyphOrder() glyphOrder = font.getGlyphOrder()
gids = reader.readUShortArray(count) gids = reader.readArray(self.typecode, self.staticSize, count)
try: try:
l = [glyphOrder[gid] for gid in gids] l = [glyphOrder[gid] for gid in gids]
except IndexError: except IndexError:
@ -305,9 +306,14 @@ class GlyphID(SimpleValue):
l = [font.getGlyphName(gid) for gid in gids] l = [font.getGlyphName(gid) for gid in gids]
return l return l
def read(self, reader, font, tableDict): def read(self, reader, font, tableDict):
return font.getGlyphName(reader.readUShort()) return font.getGlyphName(reader.readValue(self.typecode, self.staticSize))
def write(self, writer, font, tableDict, value, repeatIndex=None): def write(self, writer, font, tableDict, value, repeatIndex=None):
writer.writeUShort(font.getGlyphID(value)) writer.writeValue(self.typecode, font.getGlyphID(value))
class GlyphID32(GlyphID):
staticSize = 4
typecode = "L"
class NameID(UShort): class NameID(UShort):
@ -1680,22 +1686,22 @@ class _NamedTupleConverter(BaseConverter):
return self.tupleClass(**kwargs) return self.tupleClass(**kwargs)
class VariableScalar(_NamedTupleConverter): class VarFixed(_NamedTupleConverter):
tupleClass = VariableFloat tupleClass = VariableFloat
converterClasses = [Fixed, ULong] converterClasses = [Fixed, ULong]
class VariableNormalizedScalar(_NamedTupleConverter): class VarF2Dot14(_NamedTupleConverter):
tupleClass = VariableFloat tupleClass = VariableFloat
converterClasses = [F2Dot14, ULong] converterClasses = [F2Dot14, ULong]
class VariablePosition(_NamedTupleConverter): class VarInt16(_NamedTupleConverter):
tupleClass = VariableInt tupleClass = VariableInt
converterClasses = [Short, ULong] converterClasses = [Short, ULong]
class VariableDistance(_NamedTupleConverter): class VarUInt16(_NamedTupleConverter):
tupleClass = VariableInt tupleClass = VariableInt
converterClasses = [UShort, ULong] converterClasses = [UShort, ULong]
@ -1725,6 +1731,7 @@ converterMapping = {
"Version": Version, "Version": Version,
"Tag": Tag, "Tag": Tag,
"GlyphID": GlyphID, "GlyphID": GlyphID,
"GlyphID32": GlyphID32,
"NameID": NameID, "NameID": NameID,
"DeciPoints": DeciPoints, "DeciPoints": DeciPoints,
"Fixed": Fixed, "Fixed": Fixed,
@ -1755,8 +1762,8 @@ converterMapping = {
"LOffsetTo": lambda C: partial(LTable, tableClass=C), "LOffsetTo": lambda C: partial(LTable, tableClass=C),
# Variable types # Variable types
"VariableScalar": VariableScalar, "VarFixed": VarFixed,
"VariableNormalizedScalar": VariableNormalizedScalar, "VarF2Dot14": VarF2Dot14,
"VariablePosition": VariablePosition, "VarInt16": VarInt16,
"VariableDistance": VariableDistance, "VarUInt16": VarUInt16,
} }

View File

@ -1549,7 +1549,7 @@ otData = [
('LOffset', 'BaseGlyphRecordArray', None, None, 'Offset (from beginning of COLR table) to Base Glyph records.'), ('LOffset', 'BaseGlyphRecordArray', None, None, 'Offset (from beginning of COLR table) to Base Glyph records.'),
('LOffset', 'LayerRecordArray', None, None, 'Offset (from beginning of COLR table) to Layer Records.'), ('LOffset', 'LayerRecordArray', None, None, 'Offset (from beginning of COLR table) to Layer Records.'),
('uint16', 'LayerRecordCount', None, None, 'Number of Layer Records.'), ('uint16', 'LayerRecordCount', None, None, 'Number of Layer Records.'),
('LOffset', 'BaseGlyphV1Array', None, 'Version >= 1', 'Offset (from beginning of COLR table) to array of Version-1 Base Glyph records.'), ('LOffset', 'BaseGlyphV1List', None, 'Version >= 1', 'Offset (from beginning of COLR table) to array of Version-1 Base Glyph records.'),
('LOffset', 'VarStore', None, 'Version >= 1', 'Offset to variation store (may be NULL)'), ('LOffset', 'VarStore', None, 'Version >= 1', 'Offset to variation store (may be NULL)'),
]), ]),
@ -1572,46 +1572,41 @@ otData = [
('uint16', 'PaletteIndex', None, None, 'Index value to use with a selected color palette.'), ('uint16', 'PaletteIndex', None, None, 'Index value to use with a selected color palette.'),
]), ]),
('BaseGlyphV1Array', [ ('BaseGlyphV1List', [
('uint32', 'BaseGlyphCount', None, None, 'Number of Version-1 Base Glyph records'), ('uint32', 'BaseGlyphCount', None, None, 'Number of Version-1 Base Glyph records'),
('struct', 'BaseGlyphV1Record', 'BaseGlyphCount', 0, 'Array of Version-1 Base Glyph records'), ('struct', 'BaseGlyphV1Record', 'BaseGlyphCount', 0, 'Array of Version-1 Base Glyph records'),
]), ]),
('BaseGlyphV1Record', [ ('BaseGlyphV1Record', [
('GlyphID', 'BaseGlyph', None, None, 'Glyph ID of reference glyph.'), ('GlyphID', 'BaseGlyph', None, None, 'Glyph ID of reference glyph.'),
('LOffset', 'LayerV1Array', None, None, 'Offset (from beginning of BaseGlyphV1Array) to LayerV1Array.'), ('LOffset', 'LayerV1List', None, None, 'Offset (from beginning of BaseGlyphV1List) to LayerV1List.'),
]), ]),
('LayerV1Array', [ ('LayerV1List', [
('uint32', 'LayerCount', None, None, 'Number of Version-1 Layer records'), ('uint32', 'LayerCount', None, None, 'Number of Version-1 Layer records'),
('struct', 'LayerV1Record', 'LayerCount', 0, 'Array of Version-1 Layer records'), ('struct', 'LayerV1Record', 'LayerCount', 0, 'Array of Version-1 Layer records'),
]), ]),
('LayerV1Record', [ ('LayerV1Record', [
('GlyphID', 'LayerGlyph', None, None, 'Glyph ID of layer glyph (must be in z-order from bottom to top).'), ('GlyphID', 'LayerGlyph', None, None, 'Glyph ID of layer glyph (must be in z-order from bottom to top).'),
('LOffset', 'Paint', None, None, 'Offset (from beginning of LayerV1Array) to Paint subtable.'), ('LOffset', 'Paint', None, None, 'Offset (from beginning of LayerV1List) to Paint subtable.'),
]), ]),
('Affine2x2', [ ('Affine2x2', [
('VariableScalar', 'xx', None, None, ''), ('VarFixed', 'xx', None, None, ''),
('VariableScalar', 'xy', None, None, ''), ('VarFixed', 'xy', None, None, ''),
('VariableScalar', 'yx', None, None, ''), ('VarFixed', 'yx', None, None, ''),
('VariableScalar', 'yy', None, None, ''), ('VarFixed', 'yy', None, None, ''),
]), ]),
('Point', [ ('ColorIndex', [
('VariablePosition', 'x', None, None, ''),
('VariablePosition', 'y', None, None, ''),
]),
('Color', [
('uint16', 'PaletteIndex', None, None, 'Index value to use with a selected color palette.'), ('uint16', 'PaletteIndex', None, None, 'Index value to use with a selected color palette.'),
('VariableNormalizedScalar', 'Transparency', None, None, 'Values outsided [0.,1.] reserved'), ('VarF2Dot14', 'Alpha', None, None, 'Values outsided [0.,1.] reserved'),
]), ]),
('ColorStop', [ ('ColorStop', [
('VariableNormalizedScalar', 'StopOffset', None, None, ''), ('VarF2Dot14', 'StopOffset', None, None, ''),
('Color', 'Color', None, None, ''), ('ColorIndex', 'Color', None, None, ''),
]), ]),
('ColorLine', [ ('ColorLine', [
@ -1622,24 +1617,29 @@ otData = [
('PaintFormat1', [ ('PaintFormat1', [
('uint16', 'PaintFormat', None, None, 'Format identifier-format = 1'), ('uint16', 'PaintFormat', None, None, 'Format identifier-format = 1'),
('Color', 'Color', None, None, 'A solid color paint.'), ('ColorIndex', 'Color', None, None, 'A solid color paint.'),
]), ]),
('PaintFormat2', [ ('PaintFormat2', [
('uint16', 'PaintFormat', None, None, 'Format identifier-format = 2'), ('uint16', 'PaintFormat', None, None, 'Format identifier-format = 2'),
('LOffset', 'ColorLine', None, None, 'Offset (from beginning of Paint table) to ColorLine subtable.'), ('LOffset', 'ColorLine', None, None, 'Offset (from beginning of Paint table) to ColorLine subtable.'),
('Point', 'p0', None, None, ''), ('VarInt16', 'x0', None, None, ''),
('Point', 'p1', None, None, ''), ('VarInt16', 'y0', None, None, ''),
('Point', 'p2', None, None, 'Normal; equal to p1 in simple cases.'), ('VarInt16', 'x1', None, None, ''),
('VarInt16', 'y1', None, None, ''),
('VarInt16', 'x2', None, None, ''),
('VarInt16', 'y2', None, None, ''),
]), ]),
('PaintFormat3', [ ('PaintFormat3', [
('uint16', 'PaintFormat', None, None, 'Format identifier-format = 3'), ('uint16', 'PaintFormat', None, None, 'Format identifier-format = 3'),
('LOffset', 'ColorLine', None, None, 'Offset (from beginning of Paint table) to ColorLine subtable.'), ('LOffset', 'ColorLine', None, None, 'Offset (from beginning of Paint table) to ColorLine subtable.'),
('Point', 'c0', None, None, ''), ('VarInt16', 'x0', None, None, ''),
('Point', 'c1', None, None, ''), ('VarInt16', 'y0', None, None, ''),
('VariableDistance', 'r0', None, None, ''), ('VarUInt16', 'r0', None, None, ''),
('VariableDistance', 'r1', None, None, ''), ('VarInt16', 'x1', None, None, ''),
('LOffsetTo(Affine2x2)', 'Affine', None, None, 'Offset (from beginning of Paint table) to Affine2x2 subtable.'), ('VarInt16', 'y1', None, None, ''),
('VarUInt16', 'r1', None, None, ''),
('LOffsetTo(Affine2x2)', 'Transform', None, None, 'Offset (from beginning of Paint table) to Affine2x2 subtable.'),
]), ]),
] ]

View File

@ -1197,7 +1197,7 @@ class BaseGlyphRecordArray(BaseTable):
return self.__dict__.copy() return self.__dict__.copy()
class BaseGlyphV1Array(BaseTable): class BaseGlyphV1List(BaseTable):
def preWrite(self, font): def preWrite(self, font):
self.BaseGlyphV1Record = sorted( self.BaseGlyphV1Record = sorted(

View File

@ -188,63 +188,61 @@ def test_buildCPAL_invalid_color():
builder.buildCPAL([[(0, 0, 0, 0)], [(1, 1, -1, 2)]]) builder.buildCPAL([[(0, 0, 0, 0)], [(1, 1, -1, 2)]])
def test_buildColor(): def test_buildColorIndex():
c = builder.buildColor(0) c = builder.buildColorIndex(0)
assert c.PaletteIndex == 0 assert c.PaletteIndex == 0
assert c.Transparency.value == 0.0 assert c.Alpha.value == 1.0
assert c.Transparency.varIdx == 0 assert c.Alpha.varIdx == 0
c = builder.buildColor(1, transparency=0.5) c = builder.buildColorIndex(1, alpha=0.5)
assert c.PaletteIndex == 1 assert c.PaletteIndex == 1
assert c.Transparency.value == 0.5 assert c.Alpha.value == 0.5
assert c.Transparency.varIdx == 0 assert c.Alpha.varIdx == 0
c = builder.buildColor(3, transparency=builder.VariableFloat(0.5, varIdx=2)) c = builder.buildColorIndex(3, alpha=builder.VariableFloat(0.5, varIdx=2))
assert c.PaletteIndex == 3 assert c.PaletteIndex == 3
assert c.Transparency.value == 0.5 assert c.Alpha.value == 0.5
assert c.Transparency.varIdx == 2 assert c.Alpha.varIdx == 2
def test_buildSolidColorPaint(): def test_buildSolidColorPaint():
p = builder.buildSolidColorPaint(0) p = builder.buildSolidColorPaint(0)
assert p.Format == 1 assert p.Format == 1
assert p.Color.PaletteIndex == 0 assert p.Color.PaletteIndex == 0
assert p.Color.Transparency.value == 0.0 assert p.Color.Alpha.value == 1.0
assert p.Color.Transparency.varIdx == 0 assert p.Color.Alpha.varIdx == 0
p = builder.buildSolidColorPaint(1, transparency=0.5) p = builder.buildSolidColorPaint(1, alpha=0.5)
assert p.Format == 1 assert p.Format == 1
assert p.Color.PaletteIndex == 1 assert p.Color.PaletteIndex == 1
assert p.Color.Transparency.value == 0.5 assert p.Color.Alpha.value == 0.5
assert p.Color.Transparency.varIdx == 0 assert p.Color.Alpha.varIdx == 0
p = builder.buildSolidColorPaint( p = builder.buildSolidColorPaint(3, alpha=builder.VariableFloat(0.5, varIdx=2))
3, transparency=builder.VariableFloat(0.5, varIdx=2)
)
assert p.Format == 1 assert p.Format == 1
assert p.Color.PaletteIndex == 3 assert p.Color.PaletteIndex == 3
assert p.Color.Transparency.value == 0.5 assert p.Color.Alpha.value == 0.5
assert p.Color.Transparency.varIdx == 2 assert p.Color.Alpha.varIdx == 2
def test_buildColorStop(): def test_buildColorStop():
s = builder.buildColorStop(0.1, 2) s = builder.buildColorStop(0.1, 2)
assert s.StopOffset == builder.VariableFloat(0.1) assert s.StopOffset == builder.VariableFloat(0.1)
assert s.Color.PaletteIndex == 2 assert s.Color.PaletteIndex == 2
assert s.Color.Transparency == builder._DEFAULT_TRANSPARENCY assert s.Color.Alpha == builder._DEFAULT_ALPHA
s = builder.buildColorStop(offset=0.2, paletteIndex=3, transparency=0.4) s = builder.buildColorStop(offset=0.2, paletteIndex=3, alpha=0.4)
assert s.StopOffset == builder.VariableFloat(0.2) assert s.StopOffset == builder.VariableFloat(0.2)
assert s.Color == builder.buildColor(3, transparency=0.4) assert s.Color == builder.buildColorIndex(3, alpha=0.4)
s = builder.buildColorStop( s = builder.buildColorStop(
offset=builder.VariableFloat(0.0, varIdx=1), offset=builder.VariableFloat(0.0, varIdx=1),
paletteIndex=0, paletteIndex=0,
transparency=builder.VariableFloat(0.3, varIdx=2), alpha=builder.VariableFloat(0.3, varIdx=2),
) )
assert s.StopOffset == builder.VariableFloat(0.0, varIdx=1) assert s.StopOffset == builder.VariableFloat(0.0, varIdx=1)
assert s.Color.PaletteIndex == 0 assert s.Color.PaletteIndex == 0
assert s.Color.Transparency == builder.VariableFloat(0.3, varIdx=2) assert s.Color.Alpha == builder.VariableFloat(0.3, varIdx=2)
def test_buildColorLine(): def test_buildColorLine():
@ -272,42 +270,20 @@ def test_buildColorLine():
] == stops ] == stops
stops = [ stops = [
{"offset": (0.0, 1), "paletteIndex": 0, "transparency": (0.5, 2)}, {"offset": (0.0, 1), "paletteIndex": 0, "alpha": (0.5, 2)},
{"offset": (1.0, 3), "paletteIndex": 1, "transparency": (0.3, 4)}, {"offset": (1.0, 3), "paletteIndex": 1, "alpha": (0.3, 4)},
] ]
cline = builder.buildColorLine(stops) cline = builder.buildColorLine(stops)
assert [ assert [
{ {
"offset": cs.StopOffset, "offset": cs.StopOffset,
"paletteIndex": cs.Color.PaletteIndex, "paletteIndex": cs.Color.PaletteIndex,
"transparency": cs.Color.Transparency, "alpha": cs.Color.Alpha,
} }
for cs in cline.ColorStop for cs in cline.ColorStop
] == stops ] == stops
def test_buildPoint():
pt = builder.buildPoint(0, 1)
assert pt.x == builder.VariableInt(0)
assert pt.y == builder.VariableInt(1)
pt = builder.buildPoint(
builder.VariableInt(2, varIdx=1), builder.VariableInt(3, varIdx=2)
)
assert pt.x == builder.VariableInt(2, varIdx=1)
assert pt.y == builder.VariableInt(3, varIdx=2)
# float coords are rounded
pt = builder.buildPoint(x=-2.5, y=3.5)
assert pt.x == builder.VariableInt(-2)
assert pt.y == builder.VariableInt(4)
# tuple args are cast to VariableInt namedtuple
pt = builder.buildPoint((1, 2), (3, 4))
assert pt.x == builder.VariableInt(1, varIdx=2)
assert pt.y == builder.VariableInt(3, varIdx=4)
def test_buildAffine2x2(): def test_buildAffine2x2():
matrix = builder.buildAffine2x2(1.5, 0, 0.5, 2.0) matrix = builder.buildAffine2x2(1.5, 0, 0.5, 2.0)
assert matrix.xx == builder.VariableFloat(1.5) assert matrix.xx == builder.VariableFloat(1.5)
@ -320,49 +296,48 @@ def test_buildLinearGradientPaint():
color_stops = [ color_stops = [
builder.buildColorStop(0.0, 0), builder.buildColorStop(0.0, 0),
builder.buildColorStop(0.5, 1), builder.buildColorStop(0.5, 1),
builder.buildColorStop(1.0, 2, transparency=0.8), builder.buildColorStop(1.0, 2, alpha=0.8),
] ]
color_line = builder.buildColorLine(color_stops, extend=builder.ExtendMode.REPEAT) color_line = builder.buildColorLine(color_stops, extend=builder.ExtendMode.REPEAT)
p0 = builder.buildPoint(x=100, y=200) p0 = (builder.VariableInt(100), builder.VariableInt(200))
p1 = builder.buildPoint(x=150, y=250) p1 = (builder.VariableInt(150), builder.VariableInt(250))
gradient = builder.buildLinearGradientPaint(color_line, p0, p1) gradient = builder.buildLinearGradientPaint(color_line, p0, p1)
assert gradient.Format == 2 assert gradient.Format == 2
assert gradient.ColorLine == color_line assert gradient.ColorLine == color_line
assert gradient.p0 == p0 assert (gradient.x0, gradient.y0) == p0
assert gradient.p1 == p1 assert (gradient.x1, gradient.y1) == p1
assert gradient.p2 == gradient.p1 assert (gradient.x2, gradient.y2) == p1
assert gradient.p2 is not gradient.p1
gradient = builder.buildLinearGradientPaint({"stops": color_stops}, p0, p1) gradient = builder.buildLinearGradientPaint({"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.buildLinearGradientPaint(color_line, p0, p1, p2=(150, 230)) gradient = builder.buildLinearGradientPaint(color_line, p0, p1, p2=(150, 230))
assert gradient.p2 == builder.buildPoint(x=150, y=230) assert (gradient.x2.value, gradient.y2.value) == (150, 230)
assert gradient.p2 != gradient.p1 assert (gradient.x2, gradient.y2) != (gradient.x1, gradient.y1)
def test_buildRadialGradientPaint(): def test_buildRadialGradientPaint():
color_stops = [ color_stops = [
builder.buildColorStop(0.0, 0), builder.buildColorStop(0.0, 0),
builder.buildColorStop(0.5, 1), builder.buildColorStop(0.5, 1),
builder.buildColorStop(1.0, 2, transparency=0.8), builder.buildColorStop(1.0, 2, alpha=0.8),
] ]
color_line = builder.buildColorLine(color_stops, extend=builder.ExtendMode.REPEAT) color_line = builder.buildColorLine(color_stops, extend=builder.ExtendMode.REPEAT)
c0 = builder.buildPoint(x=100, y=200) c0 = (builder.VariableInt(100), builder.VariableInt(200))
c1 = builder.buildPoint(x=150, y=250) c1 = (builder.VariableInt(150), builder.VariableInt(250))
r0 = builder.VariableInt(10) r0 = builder.VariableInt(10)
r1 = builder.VariableInt(5) r1 = builder.VariableInt(5)
gradient = builder.buildRadialGradientPaint(color_line, c0, c1, r0, r1) gradient = builder.buildRadialGradientPaint(color_line, c0, c1, r0, r1)
assert gradient.Format == 3 assert gradient.Format == 3
assert gradient.ColorLine == color_line assert gradient.ColorLine == color_line
assert gradient.c0 == c0 assert (gradient.x0, gradient.y0) == c0
assert gradient.c1 == c1 assert (gradient.x1, gradient.y1) == c1
assert gradient.r0 == r0 assert gradient.r0 == r0
assert gradient.r1 == r1 assert gradient.r1 == r1
assert gradient.Affine is None assert gradient.Transform is None
gradient = builder.buildRadialGradientPaint({"stops": color_stops}, c0, c1, r0, r1) gradient = builder.buildRadialGradientPaint({"stops": color_stops}, c0, c1, r0, r1)
assert gradient.ColorLine.Extend == builder.ExtendMode.PAD assert gradient.ColorLine.Extend == builder.ExtendMode.PAD
@ -370,14 +345,14 @@ def test_buildRadialGradientPaint():
matrix = builder.buildAffine2x2(2.0, 0.0, 0.0, 2.0) matrix = builder.buildAffine2x2(2.0, 0.0, 0.0, 2.0)
gradient = builder.buildRadialGradientPaint( gradient = builder.buildRadialGradientPaint(
color_line, c0, c1, r0, r1, affine=matrix color_line, c0, c1, r0, r1, transform=matrix
) )
assert gradient.Affine == matrix assert gradient.Transform == matrix
gradient = builder.buildRadialGradientPaint( gradient = builder.buildRadialGradientPaint(
color_line, c0, c1, r0, r1, affine=(2.0, 0.0, 0.0, 2.0) color_line, c0, c1, r0, r1, transform=(2.0, 0.0, 0.0, 2.0)
) )
assert gradient.Affine == matrix assert gradient.Transform == matrix
def test_buildLayerV1Record(): def test_buildLayerV1Record():
@ -389,7 +364,7 @@ def test_buildLayerV1Record():
layer = builder.buildLayerV1Record("a", builder.buildSolidColorPaint(3, 0.9)) layer = builder.buildLayerV1Record("a", builder.buildSolidColorPaint(3, 0.9))
assert layer.Paint.Format == 1 assert layer.Paint.Format == 1
assert layer.Paint.Color.PaletteIndex == 3 assert layer.Paint.Color.PaletteIndex == 3
assert layer.Paint.Color.Transparency.value == 0.9 assert layer.Paint.Color.Alpha.value == 0.9
layer = builder.buildLayerV1Record( layer = builder.buildLayerV1Record(
"a", "a",
@ -402,10 +377,10 @@ def test_buildLayerV1Record():
assert layer.Paint.ColorLine.ColorStop[0].Color.PaletteIndex == 3 assert layer.Paint.ColorLine.ColorStop[0].Color.PaletteIndex == 3
assert layer.Paint.ColorLine.ColorStop[1].StopOffset.value == 1.0 assert layer.Paint.ColorLine.ColorStop[1].StopOffset.value == 1.0
assert layer.Paint.ColorLine.ColorStop[1].Color.PaletteIndex == 4 assert layer.Paint.ColorLine.ColorStop[1].Color.PaletteIndex == 4
assert layer.Paint.p0.x.value == 100 assert layer.Paint.x0.value == 100
assert layer.Paint.p0.y.value == 200 assert layer.Paint.y0.value == 200
assert layer.Paint.p1.x.value == 150 assert layer.Paint.x1.value == 150
assert layer.Paint.p1.y.value == 250 assert layer.Paint.y1.value == 250
layer = builder.buildLayerV1Record( layer = builder.buildLayerV1Record(
"a", "a",
@ -413,7 +388,7 @@ def test_buildLayerV1Record():
{ {
"stops": [ "stops": [
(0.0, 5), (0.0, 5),
{"offset": 0.5, "paletteIndex": 6, "transparency": 0.8}, {"offset": 0.5, "paletteIndex": 6, "alpha": 0.8},
(1.0, 7), (1.0, 7),
] ]
}, },
@ -428,14 +403,14 @@ def test_buildLayerV1Record():
assert layer.Paint.ColorLine.ColorStop[0].Color.PaletteIndex == 5 assert layer.Paint.ColorLine.ColorStop[0].Color.PaletteIndex == 5
assert layer.Paint.ColorLine.ColorStop[1].StopOffset.value == 0.5 assert layer.Paint.ColorLine.ColorStop[1].StopOffset.value == 0.5
assert layer.Paint.ColorLine.ColorStop[1].Color.PaletteIndex == 6 assert layer.Paint.ColorLine.ColorStop[1].Color.PaletteIndex == 6
assert layer.Paint.ColorLine.ColorStop[1].Color.Transparency.value == 0.8 assert layer.Paint.ColorLine.ColorStop[1].Color.Alpha.value == 0.8
assert layer.Paint.ColorLine.ColorStop[2].StopOffset.value == 1.0 assert layer.Paint.ColorLine.ColorStop[2].StopOffset.value == 1.0
assert layer.Paint.ColorLine.ColorStop[2].Color.PaletteIndex == 7 assert layer.Paint.ColorLine.ColorStop[2].Color.PaletteIndex == 7
assert layer.Paint.c0.x.value == 50 assert layer.Paint.x0.value == 50
assert layer.Paint.c0.y.value == 50 assert layer.Paint.y0.value == 50
assert layer.Paint.c1.x.value == 75
assert layer.Paint.c1.y.value == 75
assert layer.Paint.r0.value == 30 assert layer.Paint.r0.value == 30
assert layer.Paint.x1.value == 75
assert layer.Paint.y1.value == 75
assert layer.Paint.r1.value == 10 assert layer.Paint.r1.value == 10
@ -472,10 +447,10 @@ def test_buildLayerV1Record_from_dict():
assert layer.Paint.r0.value == 4 assert layer.Paint.r0.value == 4
def test_buildLayerV1Array(): def test_buildLayerV1List():
layers = [ layers = [
("a", 1), ("a", 1),
("b", {"format": 1, "paletteIndex": 2, "transparency": 0.5}), ("b", {"format": 1, "paletteIndex": 2, "alpha": 0.5}),
( (
"c", "c",
{ {
@ -492,7 +467,7 @@ def test_buildLayerV1Array():
"colorLine": { "colorLine": {
"stops": [ "stops": [
{"offset": 0.0, "paletteIndex": 5}, {"offset": 0.0, "paletteIndex": 5},
{"offset": 0.5, "paletteIndex": 6, "transparency": 0.8}, {"offset": 0.5, "paletteIndex": 6, "alpha": 0.8},
{"offset": 1.0, "paletteIndex": 7}, {"offset": 1.0, "paletteIndex": 7},
] ]
}, },
@ -504,28 +479,28 @@ def test_buildLayerV1Array():
), ),
builder.buildLayerV1Record("e", builder.buildSolidColorPaint(8)), builder.buildLayerV1Record("e", builder.buildSolidColorPaint(8)),
] ]
layersArray = builder.buildLayerV1Array(layers) layers = builder.buildLayerV1List(layers)
assert layersArray.LayerCount == len(layersArray.LayerV1Record) assert layers.LayerCount == len(layers.LayerV1Record)
assert all(isinstance(l, ot.LayerV1Record) for l in layersArray.LayerV1Record) assert all(isinstance(l, ot.LayerV1Record) for l in layers.LayerV1Record)
def test_buildBaseGlyphV1Record(): def test_buildBaseGlyphV1Record():
baseGlyphRec = builder.buildBaseGlyphV1Record("a", [("b", 0), ("c", 1)]) baseGlyphRec = builder.buildBaseGlyphV1Record("a", [("b", 0), ("c", 1)])
assert baseGlyphRec.BaseGlyph == "a" assert baseGlyphRec.BaseGlyph == "a"
assert isinstance(baseGlyphRec.LayerV1Array, ot.LayerV1Array) assert isinstance(baseGlyphRec.LayerV1List, ot.LayerV1List)
layerArray = builder.buildLayerV1Array([("b", 0), ("c", 1)]) layers = builder.buildLayerV1List([("b", 0), ("c", 1)])
baseGlyphRec = builder.buildBaseGlyphV1Record("a", layerArray) baseGlyphRec = builder.buildBaseGlyphV1Record("a", layers)
assert baseGlyphRec.BaseGlyph == "a" assert baseGlyphRec.BaseGlyph == "a"
assert baseGlyphRec.LayerV1Array == layerArray assert baseGlyphRec.LayerV1List == layers
def test_buildBaseGlyphV1Array(): def test_buildBaseGlyphV1List():
colorGlyphs = { colorGlyphs = {
"a": [("b", 0), ("c", 1)], "a": [("b", 0), ("c", 1)],
"d": [ "d": [
("e", {"format": 1, "paletteIndex": 2, "transparency": 0.8}), ("e", {"format": 1, "paletteIndex": 2, "alpha": 0.8}),
( (
"f", "f",
{ {
@ -538,7 +513,7 @@ def test_buildBaseGlyphV1Array():
}, },
), ),
], ],
"g": builder.buildLayerV1Array([("h", 5)]), "g": builder.buildLayerV1List([("h", 5)]),
} }
glyphMap = { glyphMap = {
".notdef": 0, ".notdef": 0,
@ -552,17 +527,17 @@ def test_buildBaseGlyphV1Array():
"h": 8, "h": 8,
} }
baseGlyphArray = builder.buildBaseGlyphV1Array(colorGlyphs, glyphMap) baseGlyphs = builder.buildBaseGlyphV1List(colorGlyphs, glyphMap)
assert baseGlyphArray.BaseGlyphCount == len(colorGlyphs) assert baseGlyphs.BaseGlyphCount == len(colorGlyphs)
assert baseGlyphArray.BaseGlyphV1Record[0].BaseGlyph == "d" assert baseGlyphs.BaseGlyphV1Record[0].BaseGlyph == "d"
assert baseGlyphArray.BaseGlyphV1Record[1].BaseGlyph == "a" assert baseGlyphs.BaseGlyphV1Record[1].BaseGlyph == "a"
assert baseGlyphArray.BaseGlyphV1Record[2].BaseGlyph == "g" assert baseGlyphs.BaseGlyphV1Record[2].BaseGlyph == "g"
baseGlyphArray = builder.buildBaseGlyphV1Array(colorGlyphs) baseGlyphs = builder.buildBaseGlyphV1List(colorGlyphs)
assert baseGlyphArray.BaseGlyphCount == len(colorGlyphs) assert baseGlyphs.BaseGlyphCount == len(colorGlyphs)
assert baseGlyphArray.BaseGlyphV1Record[0].BaseGlyph == "a" assert baseGlyphs.BaseGlyphV1Record[0].BaseGlyph == "a"
assert baseGlyphArray.BaseGlyphV1Record[1].BaseGlyph == "d" assert baseGlyphs.BaseGlyphV1Record[1].BaseGlyph == "d"
assert baseGlyphArray.BaseGlyphV1Record[2].BaseGlyph == "g" assert baseGlyphs.BaseGlyphV1Record[2].BaseGlyph == "g"
def test_splitSolidAndGradientGlyphs(): def test_splitSolidAndGradientGlyphs():
@ -581,7 +556,7 @@ def test_splitSolidAndGradientGlyphs():
assert not colorGlyphsV1 assert not colorGlyphsV1
colorGlyphs = { colorGlyphs = {
"a": [("b", builder.buildSolidColorPaint(paletteIndex=0, transparency=1.0))] "a": [("b", builder.buildSolidColorPaint(paletteIndex=0, alpha=0.0))]
} }
colorGlyphsV0, colorGlyphsV1 = builder._splitSolidAndGradientGlyphs(colorGlyphs) colorGlyphsV0, colorGlyphsV1 = builder._splitSolidAndGradientGlyphs(colorGlyphs)
@ -649,7 +624,7 @@ class BuildCOLRTest(object):
"r1": 2, "r1": 2,
}, },
), ),
("c", {"format": 1, "paletteIndex": 2, "transparency": 0.8}), ("c", {"format": 1, "paletteIndex": 2, "alpha": 0.8}),
], ],
"d": [ "d": [
( (
@ -706,19 +681,18 @@ class BuildCOLRTest(object):
assert colr.table.LayerRecordCount == 2 assert colr.table.LayerRecordCount == 2
assert isinstance(colr.table.LayerRecordArray, ot.LayerRecordArray) assert isinstance(colr.table.LayerRecordArray, ot.LayerRecordArray)
assert isinstance(colr.table.BaseGlyphV1Array, ot.BaseGlyphV1Array) assert isinstance(colr.table.BaseGlyphV1List, ot.BaseGlyphV1List)
assert colr.table.BaseGlyphV1Array.BaseGlyphCount == 1 assert colr.table.BaseGlyphV1List.BaseGlyphCount == 1
assert isinstance( assert isinstance(
colr.table.BaseGlyphV1Array.BaseGlyphV1Record[0], ot.BaseGlyphV1Record colr.table.BaseGlyphV1List.BaseGlyphV1Record[0], ot.BaseGlyphV1Record
) )
assert colr.table.BaseGlyphV1Array.BaseGlyphV1Record[0].BaseGlyph == "d" assert colr.table.BaseGlyphV1List.BaseGlyphV1Record[0].BaseGlyph == "d"
assert isinstance( assert isinstance(
colr.table.BaseGlyphV1Array.BaseGlyphV1Record[0].LayerV1Array, colr.table.BaseGlyphV1List.BaseGlyphV1Record[0].LayerV1List, ot.LayerV1List
ot.LayerV1Array,
) )
assert ( assert (
colr.table.BaseGlyphV1Array.BaseGlyphV1Record[0] colr.table.BaseGlyphV1List.BaseGlyphV1Record[0]
.LayerV1Array.LayerV1Record[0] .LayerV1List.LayerV1Record[0]
.LayerGlyph .LayerGlyph
== "e" == "e"
) )

View File

@ -71,7 +71,7 @@ COLR_V1_DATA = (
b"\x00\x00\x00\x16" # Offset to BaseGlyphRecordArray from beginning of table (22) b"\x00\x00\x00\x16" # Offset to BaseGlyphRecordArray from beginning of table (22)
b"\x00\x00\x00\x1c" # Offset to LayerRecordArray from beginning of table (28) b"\x00\x00\x00\x1c" # Offset to LayerRecordArray from beginning of table (28)
b"\x00\x03" # LayerRecordCount (3) b"\x00\x03" # LayerRecordCount (3)
b"\x00\x00\x00(" # Offset to BaseGlyphV1Array from beginning of table (40) b"\x00\x00\x00(" # Offset to BaseGlyphV1List from beginning of table (40)
b"\x00\x00\x00\x00" # Offset to VarStore (NULL) b"\x00\x00\x00\x00" # Offset to VarStore (NULL)
b"\x00\x06" # BaseGlyphRecord[0].BaseGlyph (6) b"\x00\x06" # BaseGlyphRecord[0].BaseGlyph (6)
b"\x00\x00" # BaseGlyphRecord[0].FirstLayerIndex (0) b"\x00\x00" # BaseGlyphRecord[0].FirstLayerIndex (0)
@ -82,62 +82,62 @@ COLR_V1_DATA = (
b"\x00\x01" # LayerRecord[1].PaletteIndex (1) b"\x00\x01" # LayerRecord[1].PaletteIndex (1)
b"\x00\t" # LayerRecord[2].LayerGlyph (9) b"\x00\t" # LayerRecord[2].LayerGlyph (9)
b"\x00\x02" # LayerRecord[2].PaletteIndex (2) b"\x00\x02" # LayerRecord[2].PaletteIndex (2)
b"\x00\x00\x00\x01" # BaseGlyphV1Array.BaseGlyphCount (1) b"\x00\x00\x00\x01" # BaseGlyphV1List.BaseGlyphCount (1)
b"\x00\n" # BaseGlyphV1Array.BaseGlyphV1Record[0].BaseGlyph (10) b"\x00\n" # BaseGlyphV1List.BaseGlyphV1Record[0].BaseGlyph (10)
b"\x00\x00\x00\n" # Offset to LayerV1Array from beginning of BaseGlyphV1Array (10) b"\x00\x00\x00\n" # Offset to LayerV1List from beginning of BaseGlyphV1List (10)
b"\x00\x00\x00\x03" # LayerV1Array.LayerCount (3) b"\x00\x00\x00\x03" # LayerV1List.LayerCount (3)
b"\x00\x0b" # LayerV1Array.LayerV1Record[0].LayerGlyph (11) b"\x00\x0b" # LayerV1List.LayerV1Record[0].LayerGlyph (11)
b"\x00\x00\x00\x16" # Offset to Paint from beginning of LayerV1Array (22) b"\x00\x00\x00\x16" # Offset to Paint from beginning of LayerV1List (22)
b"\x00\x0c" # LayerV1Array.LayerV1Record[1].LayerGlyph (12) b"\x00\x0c" # LayerV1List.LayerV1Record[1].LayerGlyph (12)
b"\x00\x00\x00 " # Offset to Paint from beginning of LayerV1Array (32) b"\x00\x00\x00 " # Offset to Paint from beginning of LayerV1List (32)
b"\x00\r" # LayerV1Array.LayerV1Record[2].LayerGlyph (13) b"\x00\r" # LayerV1List.LayerV1Record[2].LayerGlyph (13)
b"\x00\x00\x00x" # Offset to Paint from beginning of LayerV1Array (120) b"\x00\x00\x00x" # Offset to Paint from beginning of LayerV1List (120)
b"\x00\x01" # Paint.Format (1) b"\x00\x01" # Paint.Format (1)
b"\x00\x02" # Paint.Color.PaletteIndex (2) b"\x00\x02" # Paint.Color.PaletteIndex (2)
b" \x00" # Paint.Color.Transparency.value (0.5) b" \x00" # Paint.Color.Alpha.value (0.5)
b"\x00\x00\x00\x00" # Paint.Color.Transparency.varIdx (0) b"\x00\x00\x00\x00" # Paint.Color.Alpha.varIdx (0)
b"\x00\x02" # Paint.Format (2) b"\x00\x02" # Paint.Format (2)
b"\x00\x00\x00*" # Offset to ColorLine from beginning of Paint (42) b"\x00\x00\x00*" # Offset to ColorLine from beginning of Paint (42)
b"\x00\x01" # Paint.p0.x.value (1) b"\x00\x01" # Paint.x0.value (1)
b"\x00\x00\x00\x00" # Paint.p0.x.varIdx (0) b"\x00\x00\x00\x00" # Paint.x0.varIdx (0)
b"\x00\x02" # Paint.p0.y.value (2) b"\x00\x02" # Paint.y0.value (2)
b"\x00\x00\x00\x00" # Paint.p0.y.varIdx (0) b"\x00\x00\x00\x00" # Paint.y0.varIdx (0)
b"\xff\xfd" # Paint.p1.x.value (-3) b"\xff\xfd" # Paint.x1.value (-3)
b"\x00\x00\x00\x00" # Paint.p1.x.varIdx (0) b"\x00\x00\x00\x00" # Paint.x1.varIdx (0)
b"\xff\xfc" # Paint.p1.y.value (-4) b"\xff\xfc" # Paint.y1.value (-4)
b"\x00\x00\x00\x00" # Paint.p1.y.varIdx (0) b"\x00\x00\x00\x00" # Paint.y1.varIdx (0)
b"\x00\x05" # Paint.p2.x.value (5) b"\x00\x05" # Paint.x2.value (5)
b"\x00\x00\x00\x00" # Paint.p2.y.varIdx (0) b"\x00\x00\x00\x00" # Paint.x2.varIdx (0)
b"\x00\x06" # Paint.p2.y.value (5) b"\x00\x06" # Paint.y2.value (5)
b"\x00\x00\x00\x00" # Paint.p2.y.varIdx (0) b"\x00\x00\x00\x00" # Paint.y2.varIdx (0)
b"\x00\x01" # ColorLine.Extend (1 or "repeat") b"\x00\x01" # ColorLine.Extend (1 or "repeat")
b"\x00\x03" # ColorLine.StopCount (3) b"\x00\x03" # ColorLine.StopCount (3)
b"\x00\x00" # ColorLine.ColorStop[0].StopOffset.value (0.0) b"\x00\x00" # ColorLine.ColorStop[0].StopOffset.value (0.0)
b"\x00\x00\x00\x00" # ColorLine.ColorStop[0].StopOffset.varIdx (0) b"\x00\x00\x00\x00" # ColorLine.ColorStop[0].StopOffset.varIdx (0)
b"\x00\x03" # ColorLine.ColorStop[0].Color.PaletteIndex (3) b"\x00\x03" # ColorLine.ColorStop[0].Color.PaletteIndex (3)
b"\x00\x00" # ColorLine.ColorStop[0].Color.Transparency.value (0.0) b"@\x00" # ColorLine.ColorStop[0].Color.Alpha.value (1.0)
b"\x00\x00\x00\x00" # ColorLine.ColorStop[0].Color.Transparency.varIdx (0) b"\x00\x00\x00\x00" # ColorLine.ColorStop[0].Color.Alpha.varIdx (0)
b" \x00" # ColorLine.ColorStop[1].StopOffset.value (0.5) b" \x00" # ColorLine.ColorStop[1].StopOffset.value (0.5)
b"\x00\x00\x00\x00" # ColorLine.ColorStop[1].StopOffset.varIdx (0) b"\x00\x00\x00\x00" # ColorLine.ColorStop[1].StopOffset.varIdx (0)
b"\x00\x04" # ColorLine.ColorStop[1].Color.PaletteIndex (4) b"\x00\x04" # ColorLine.ColorStop[1].Color.PaletteIndex (4)
b"\x00\x00" # ColorLine.ColorStop[1].Color.Transparency.value (0.0) b"@\x00" # ColorLine.ColorStop[1].Color.Alpha.value (1.0)
b"\x00\x00\x00\x00" # ColorLine.ColorStop[1].Color.Transparency.varIdx (0) b"\x00\x00\x00\x00" # ColorLine.ColorStop[1].Color.Alpha.varIdx (0)
b"@\x00" # ColorLine.ColorStop[2].StopOffset.value (1.0) b"@\x00" # ColorLine.ColorStop[2].StopOffset.value (1.0)
b"\x00\x00\x00\x00" # ColorLine.ColorStop[2].StopOffset.varIdx (0) b"\x00\x00\x00\x00" # ColorLine.ColorStop[2].StopOffset.varIdx (0)
b"\x00\x05" # ColorLine.ColorStop[2].Color.PaletteIndex (5) b"\x00\x05" # ColorLine.ColorStop[2].Color.PaletteIndex (5)
b"\x00\x00" # ColorLine.ColorStop[2].Color.Transparency.value (0.0) b"@\x00" # ColorLine.ColorStop[2].Color.Alpha.value (1.0)
b"\x00\x00\x00\x00" # ColorLine.ColorStop[2].Color.Transparency.varIdx (0) b"\x00\x00\x00\x00" # ColorLine.ColorStop[2].Color.Alpha.varIdx (0)
b"\x00\x03" # Paint.Format (3) b"\x00\x03" # Paint.Format (3)
b"\x00\x00\x00." # Offset to ColorLine from beginning of Paint (46) b"\x00\x00\x00." # Offset to ColorLine from beginning of Paint (46)
b"\x00\x07" # Paint.c0.x.value (7) b"\x00\x07" # Paint.x0.value (7)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
b"\x00\x08" # Paint.c0.y.value (8) b"\x00\x08" # Paint.y0.value (8)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
b"\x00\t" # Paint.c1.x.value (9) b"\x00\t" # Paint.r0.value (9)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
b"\x00\n" # Paint.c1.y.value (10) b"\x00\n" # Paint.x1.value (10)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
b"\x00\x0b" # Paint.r0.value (11) b"\x00\x0b" # Paint.y1.value (11)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
b"\x00\x0c" # Paint.r1.value (12) b"\x00\x0c" # Paint.r1.value (12)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
@ -147,12 +147,12 @@ COLR_V1_DATA = (
b"\x00\x00" # ColorLine.ColorStop[0].StopOffset.value (0.0) b"\x00\x00" # ColorLine.ColorStop[0].StopOffset.value (0.0)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
b"\x00\x06" # ColorLine.ColorStop[0].Color.PaletteIndex (6) b"\x00\x06" # ColorLine.ColorStop[0].Color.PaletteIndex (6)
b"\x00\x00" b"@\x00" # ColorLine.ColorStop[0].Color.Alpha.value (1.0)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
b"@\x00" # ColorLine.ColorStop[1].StopOffset.value (1.0) b"@\x00" # ColorLine.ColorStop[1].StopOffset.value (1.0)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
b"\x00\x07" # ColorLine.ColorStop[1].Color.PaletteIndex (7) b"\x00\x07" # ColorLine.ColorStop[1].Color.PaletteIndex (7)
b"\x19\x9a" # ColorLine.ColorStop[1].Color.Transparency.value (0.4) b"\x19\x9a" # ColorLine.ColorStop[1].Color.Alpha.value (0.4)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
b"\xff\xf3\x00\x00" # Affine2x2.xx.value (-13) b"\xff\xf3\x00\x00" # Affine2x2.xx.value (-13)
b"\x00\x00\x00\x00" b"\x00\x00\x00\x00"
@ -190,18 +190,18 @@ COLR_V1_XML = [
" </LayerRecord>", " </LayerRecord>",
"</LayerRecordArray>", "</LayerRecordArray>",
"<!-- LayerRecordCount=3 -->", "<!-- LayerRecordCount=3 -->",
"<BaseGlyphV1Array>", "<BaseGlyphV1List>",
" <!-- BaseGlyphCount=1 -->", " <!-- BaseGlyphCount=1 -->",
' <BaseGlyphV1Record index="0">', ' <BaseGlyphV1Record index="0">',
' <BaseGlyph value="glyph00010"/>', ' <BaseGlyph value="glyph00010"/>',
" <LayerV1Array>", " <LayerV1List>",
" <!-- LayerCount=3 -->", " <!-- LayerCount=3 -->",
' <LayerV1Record index="0">', ' <LayerV1Record index="0">',
' <LayerGlyph value="glyph00011"/>', ' <LayerGlyph value="glyph00011"/>',
' <Paint Format="1">', ' <Paint Format="1">',
" <Color>", " <Color>",
' <PaletteIndex value="2"/>', ' <PaletteIndex value="2"/>',
' <Transparency value="0.5"/>', ' <Alpha value="0.5"/>',
" </Color>", " </Color>",
" </Paint>", " </Paint>",
" </LayerV1Record>", " </LayerV1Record>",
@ -215,36 +215,30 @@ COLR_V1_XML = [
' <StopOffset value="0.0"/>', ' <StopOffset value="0.0"/>',
" <Color>", " <Color>",
' <PaletteIndex value="3"/>', ' <PaletteIndex value="3"/>',
' <Transparency value="0.0"/>', ' <Alpha value="1.0"/>',
" </Color>", " </Color>",
" </ColorStop>", " </ColorStop>",
' <ColorStop index="1">', ' <ColorStop index="1">',
' <StopOffset value="0.5"/>', ' <StopOffset value="0.5"/>',
" <Color>", " <Color>",
' <PaletteIndex value="4"/>', ' <PaletteIndex value="4"/>',
' <Transparency value="0.0"/>', ' <Alpha value="1.0"/>',
" </Color>", " </Color>",
" </ColorStop>", " </ColorStop>",
' <ColorStop index="2">', ' <ColorStop index="2">',
' <StopOffset value="1.0"/>', ' <StopOffset value="1.0"/>',
" <Color>", " <Color>",
' <PaletteIndex value="5"/>', ' <PaletteIndex value="5"/>',
' <Transparency value="0.0"/>', ' <Alpha value="1.0"/>',
" </Color>", " </Color>",
" </ColorStop>", " </ColorStop>",
" </ColorLine>", " </ColorLine>",
" <p0>", ' <x0 value="1"/>',
' <x value="1"/>', ' <y0 value="2"/>',
' <y value="2"/>', ' <x1 value="-3"/>',
" </p0>", ' <y1 value="-4"/>',
" <p1>", ' <x2 value="5"/>',
' <x value="-3"/>', ' <y2 value="6"/>',
' <y value="-4"/>',
" </p1>",
" <p2>",
' <x value="5"/>',
' <y value="6"/>',
" </p2>",
" </Paint>", " </Paint>",
" </LayerV1Record>", " </LayerV1Record>",
' <LayerV1Record index="2">', ' <LayerV1Record index="2">',
@ -257,38 +251,34 @@ COLR_V1_XML = [
' <StopOffset value="0.0"/>', ' <StopOffset value="0.0"/>',
" <Color>", " <Color>",
' <PaletteIndex value="6"/>', ' <PaletteIndex value="6"/>',
' <Transparency value="0.0"/>', ' <Alpha value="1.0"/>',
" </Color>", " </Color>",
" </ColorStop>", " </ColorStop>",
' <ColorStop index="1">', ' <ColorStop index="1">',
' <StopOffset value="1.0"/>', ' <StopOffset value="1.0"/>',
" <Color>", " <Color>",
' <PaletteIndex value="7"/>', ' <PaletteIndex value="7"/>',
' <Transparency value="0.4"/>', ' <Alpha value="0.4"/>',
" </Color>", " </Color>",
" </ColorStop>", " </ColorStop>",
" </ColorLine>", " </ColorLine>",
" <c0>", ' <x0 value="7"/>',
' <x value="7"/>', ' <y0 value="8"/>',
' <y value="8"/>', ' <r0 value="9"/>',
" </c0>", ' <x1 value="10"/>',
" <c1>", ' <y1 value="11"/>',
' <x value="9"/>',
' <y value="10"/>',
" </c1>",
' <r0 value="11"/>',
' <r1 value="12"/>', ' <r1 value="12"/>',
" <Affine>", " <Transform>",
' <xx value="-13.0"/>', ' <xx value="-13.0"/>',
' <xy value="14.0"/>', ' <xy value="14.0"/>',
' <yx value="15.0"/>', ' <yx value="15.0"/>',
' <yy value="-17.0"/>', ' <yy value="-17.0"/>',
" </Affine>", " </Transform>",
" </Paint>", " </Paint>",
" </LayerV1Record>", " </LayerV1Record>",
" </LayerV1Array>", " </LayerV1List>",
" </BaseGlyphV1Record>", " </BaseGlyphV1Record>",
"</BaseGlyphV1Array>", "</BaseGlyphV1List>",
] ]