Merge pull request #3241 from fonttools/better-packer
[otBase/packer] Allow sharing tables reached by different offset sizes
This commit is contained in:
commit
a8d5d45b39
@ -376,28 +376,32 @@ class OTTableReader(object):
|
|||||||
return self.localState and name in self.localState
|
return self.localState and name in self.localState
|
||||||
|
|
||||||
|
|
||||||
|
class OffsetToWriter(object):
|
||||||
|
def __init__(self, subWriter, offsetSize):
|
||||||
|
self.subWriter = subWriter
|
||||||
|
self.offsetSize = offsetSize
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if type(self) != type(other):
|
||||||
|
return NotImplemented
|
||||||
|
return self.subWriter == other.subWriter and self.offsetSize == other.offsetSize
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
# only works after self._doneWriting() has been called
|
||||||
|
return hash((self.subWriter, self.offsetSize))
|
||||||
|
|
||||||
|
|
||||||
class OTTableWriter(object):
|
class OTTableWriter(object):
|
||||||
|
|
||||||
"""Helper class to gather and assemble data for OpenType tables."""
|
"""Helper class to gather and assemble data for OpenType tables."""
|
||||||
|
|
||||||
def __init__(self, localState=None, tableTag=None, offsetSize=2):
|
def __init__(self, localState=None, tableTag=None):
|
||||||
self.items = []
|
self.items = []
|
||||||
self.pos = None
|
self.pos = None
|
||||||
self.localState = localState
|
self.localState = localState
|
||||||
self.tableTag = tableTag
|
self.tableTag = tableTag
|
||||||
self.offsetSize = offsetSize
|
|
||||||
self.parent = None
|
self.parent = None
|
||||||
|
|
||||||
# DEPRECATED: 'longOffset' is kept as a property for backward compat with old code.
|
|
||||||
# You should use 'offsetSize' instead (2, 3 or 4 bytes).
|
|
||||||
@property
|
|
||||||
def longOffset(self):
|
|
||||||
return self.offsetSize == 4
|
|
||||||
|
|
||||||
@longOffset.setter
|
|
||||||
def longOffset(self, value):
|
|
||||||
self.offsetSize = 4 if value else 2
|
|
||||||
|
|
||||||
def __setitem__(self, name, value):
|
def __setitem__(self, name, value):
|
||||||
state = self.localState.copy() if self.localState else dict()
|
state = self.localState.copy() if self.localState else dict()
|
||||||
state[name] = value
|
state[name] = value
|
||||||
@ -417,7 +421,7 @@ class OTTableWriter(object):
|
|||||||
for item in self.items:
|
for item in self.items:
|
||||||
if hasattr(item, "getCountData"):
|
if hasattr(item, "getCountData"):
|
||||||
l += item.size
|
l += item.size
|
||||||
elif hasattr(item, "getData"):
|
elif hasattr(item, "subWriter"):
|
||||||
l += item.offsetSize
|
l += item.offsetSize
|
||||||
else:
|
else:
|
||||||
l = l + len(item)
|
l = l + len(item)
|
||||||
@ -431,19 +435,19 @@ class OTTableWriter(object):
|
|||||||
for i in range(numItems):
|
for i in range(numItems):
|
||||||
item = items[i]
|
item = items[i]
|
||||||
|
|
||||||
if hasattr(item, "getData"):
|
if hasattr(item, "subWriter"):
|
||||||
if item.offsetSize == 4:
|
if item.offsetSize == 4:
|
||||||
items[i] = packULong(item.pos - pos)
|
items[i] = packULong(item.subWriter.pos - pos)
|
||||||
elif item.offsetSize == 2:
|
elif item.offsetSize == 2:
|
||||||
try:
|
try:
|
||||||
items[i] = packUShort(item.pos - pos)
|
items[i] = packUShort(item.subWriter.pos - pos)
|
||||||
except struct.error:
|
except struct.error:
|
||||||
# provide data to fix overflow problem.
|
# provide data to fix overflow problem.
|
||||||
overflowErrorRecord = self.getOverflowErrorRecord(item)
|
overflowErrorRecord = self.getOverflowErrorRecord(item)
|
||||||
|
|
||||||
raise OTLOffsetOverflowError(overflowErrorRecord)
|
raise OTLOffsetOverflowError(overflowErrorRecord)
|
||||||
elif item.offsetSize == 3:
|
elif item.offsetSize == 3:
|
||||||
items[i] = packUInt24(item.pos - pos)
|
items[i] = packUInt24(item.subWriter.pos - pos)
|
||||||
else:
|
else:
|
||||||
raise ValueError(item.offsetSize)
|
raise ValueError(item.offsetSize)
|
||||||
|
|
||||||
@ -454,7 +458,7 @@ class OTTableWriter(object):
|
|||||||
items = list(self.items)
|
items = list(self.items)
|
||||||
packFuncs = {2: packUShort, 3: packUInt24, 4: packULong}
|
packFuncs = {2: packUShort, 3: packUInt24, 4: packULong}
|
||||||
for i, item in enumerate(items):
|
for i, item in enumerate(items):
|
||||||
if hasattr(item, "getData"):
|
if hasattr(item, "subWriter"):
|
||||||
# Offset value is not needed in harfbuzz repacker, so setting offset to 0 to avoid overflow here
|
# Offset value is not needed in harfbuzz repacker, so setting offset to 0 to avoid overflow here
|
||||||
if item.offsetSize in packFuncs:
|
if item.offsetSize in packFuncs:
|
||||||
items[i] = packFuncs[item.offsetSize](0)
|
items[i] = packFuncs[item.offsetSize](0)
|
||||||
@ -474,7 +478,7 @@ class OTTableWriter(object):
|
|||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if type(self) != type(other):
|
if type(self) != type(other):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
return self.offsetSize == other.offsetSize and self.items == other.items
|
return self.items == other.items
|
||||||
|
|
||||||
def _doneWriting(self, internedTables, shareExtension=False):
|
def _doneWriting(self, internedTables, shareExtension=False):
|
||||||
# Convert CountData references to data string items
|
# Convert CountData references to data string items
|
||||||
@ -500,8 +504,10 @@ class OTTableWriter(object):
|
|||||||
item = items[i]
|
item = items[i]
|
||||||
if hasattr(item, "getCountData"):
|
if hasattr(item, "getCountData"):
|
||||||
items[i] = item.getCountData()
|
items[i] = item.getCountData()
|
||||||
elif hasattr(item, "getData"):
|
elif hasattr(item, "subWriter"):
|
||||||
item._doneWriting(internedTables, shareExtension=shareExtension)
|
item.subWriter._doneWriting(
|
||||||
|
internedTables, shareExtension=shareExtension
|
||||||
|
)
|
||||||
# At this point, all subwriters are hashable based on their items.
|
# At this point, all subwriters are hashable based on their items.
|
||||||
# (See hash and comparison magic methods above.) So the ``setdefault``
|
# (See hash and comparison magic methods above.) So the ``setdefault``
|
||||||
# call here will return the first writer object we've seen with
|
# call here will return the first writer object we've seen with
|
||||||
@ -509,7 +515,9 @@ class OTTableWriter(object):
|
|||||||
# seen yet. We therefore replace the subwriter object with an equivalent
|
# seen yet. We therefore replace the subwriter object with an equivalent
|
||||||
# object, which deduplicates the tree.
|
# object, which deduplicates the tree.
|
||||||
if not dontShare:
|
if not dontShare:
|
||||||
items[i] = item = internedTables.setdefault(item, item)
|
items[i].subWriter = internedTables.setdefault(
|
||||||
|
item.subWriter, item.subWriter
|
||||||
|
)
|
||||||
self.items = tuple(items)
|
self.items = tuple(items)
|
||||||
|
|
||||||
def _gatherTables(self, tables, extTables, done):
|
def _gatherTables(self, tables, extTables, done):
|
||||||
@ -543,30 +551,33 @@ class OTTableWriter(object):
|
|||||||
# Find coverage table
|
# Find coverage table
|
||||||
for i in range(numItems):
|
for i in range(numItems):
|
||||||
item = self.items[i]
|
item = self.items[i]
|
||||||
if getattr(item, "name", None) == "Coverage":
|
if (
|
||||||
|
hasattr(item, "subWriter")
|
||||||
|
and getattr(item.subWriter, "name", None) == "Coverage"
|
||||||
|
):
|
||||||
sortCoverageLast = True
|
sortCoverageLast = True
|
||||||
break
|
break
|
||||||
if id(item) not in done:
|
if id(item.subWriter) not in done:
|
||||||
item._gatherTables(tables, extTables, done)
|
item.subWriter._gatherTables(tables, extTables, done)
|
||||||
else:
|
else:
|
||||||
# We're a new parent of item
|
# We're a new parent of item
|
||||||
pass
|
pass
|
||||||
|
|
||||||
for i in iRange:
|
for i in iRange:
|
||||||
item = self.items[i]
|
item = self.items[i]
|
||||||
if not hasattr(item, "getData"):
|
if not hasattr(item, "subWriter"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (
|
if (
|
||||||
sortCoverageLast
|
sortCoverageLast
|
||||||
and (i == 1)
|
and (i == 1)
|
||||||
and getattr(item, "name", None) == "Coverage"
|
and getattr(item.subWriter, "name", None) == "Coverage"
|
||||||
):
|
):
|
||||||
# we've already 'gathered' it above
|
# we've already 'gathered' it above
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if id(item) not in done:
|
if id(item.subWriter) not in done:
|
||||||
item._gatherTables(tables, extTables, done)
|
item.subWriter._gatherTables(tables, extTables, done)
|
||||||
else:
|
else:
|
||||||
# Item is already written out by other parent
|
# Item is already written out by other parent
|
||||||
pass
|
pass
|
||||||
@ -601,7 +612,7 @@ class OTTableWriter(object):
|
|||||||
child_idx = 0
|
child_idx = 0
|
||||||
offset_pos = 0
|
offset_pos = 0
|
||||||
for i, item in enumerate(self.items):
|
for i, item in enumerate(self.items):
|
||||||
if hasattr(item, "getData"):
|
if hasattr(item, "subWriter"):
|
||||||
pos = offset_pos
|
pos = offset_pos
|
||||||
elif hasattr(item, "getCountData"):
|
elif hasattr(item, "getCountData"):
|
||||||
offset_pos += item.size
|
offset_pos += item.size
|
||||||
@ -610,12 +621,12 @@ class OTTableWriter(object):
|
|||||||
offset_pos = offset_pos + len(item)
|
offset_pos = offset_pos + len(item)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if id(item) not in done:
|
if id(item.subWriter) not in done:
|
||||||
child_idx = item_idx = item._gatherGraphForHarfbuzz(
|
child_idx = item_idx = item.subWriter._gatherGraphForHarfbuzz(
|
||||||
tables, obj_list, done, item_idx, virtual_edges
|
tables, obj_list, done, item_idx, virtual_edges
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
child_idx = done[id(item)]
|
child_idx = done[id(item.subWriter)]
|
||||||
|
|
||||||
real_edge = (pos, item.offsetSize, child_idx)
|
real_edge = (pos, item.offsetSize, child_idx)
|
||||||
real_links.append(real_edge)
|
real_links.append(real_edge)
|
||||||
@ -698,10 +709,8 @@ class OTTableWriter(object):
|
|||||||
|
|
||||||
# interface for gathering data, as used by table.compile()
|
# interface for gathering data, as used by table.compile()
|
||||||
|
|
||||||
def getSubWriter(self, offsetSize=2):
|
def getSubWriter(self):
|
||||||
subwriter = self.__class__(
|
subwriter = self.__class__(self.localState, self.tableTag)
|
||||||
self.localState, self.tableTag, offsetSize=offsetSize
|
|
||||||
)
|
|
||||||
subwriter.parent = (
|
subwriter.parent = (
|
||||||
self # because some subtables have idential values, we discard
|
self # because some subtables have idential values, we discard
|
||||||
)
|
)
|
||||||
@ -773,8 +782,8 @@ class OTTableWriter(object):
|
|||||||
assert len(tag) == 4, tag
|
assert len(tag) == 4, tag
|
||||||
self.items.append(tag)
|
self.items.append(tag)
|
||||||
|
|
||||||
def writeSubTable(self, subWriter):
|
def writeSubTable(self, subWriter, offsetSize):
|
||||||
self.items.append(subWriter)
|
self.items.append(OffsetToWriter(subWriter, offsetSize))
|
||||||
|
|
||||||
def writeCountReference(self, table, name, size=2, value=None):
|
def writeCountReference(self, table, name, size=2, value=None):
|
||||||
ref = CountReference(table, name, size=size, value=value)
|
ref = CountReference(table, name, size=size, value=value)
|
||||||
@ -1365,7 +1374,7 @@ class ValueRecordFactory(object):
|
|||||||
if isDevice:
|
if isDevice:
|
||||||
if value:
|
if value:
|
||||||
subWriter = writer.getSubWriter()
|
subWriter = writer.getSubWriter()
|
||||||
writer.writeSubTable(subWriter)
|
writer.writeSubTable(subWriter, offsetSize=2)
|
||||||
value.compile(subWriter, font)
|
value.compile(subWriter, font)
|
||||||
else:
|
else:
|
||||||
writer.writeUShort(0)
|
writer.writeUShort(0)
|
||||||
@ -1376,7 +1385,6 @@ class ValueRecordFactory(object):
|
|||||||
|
|
||||||
|
|
||||||
class ValueRecord(object):
|
class ValueRecord(object):
|
||||||
|
|
||||||
# see ValueRecordFactory
|
# see ValueRecordFactory
|
||||||
|
|
||||||
def __init__(self, valueFormat=None, src=None):
|
def __init__(self, valueFormat=None, src=None):
|
||||||
|
@ -720,7 +720,6 @@ class StructWithLength(Struct):
|
|||||||
|
|
||||||
|
|
||||||
class Table(Struct):
|
class Table(Struct):
|
||||||
|
|
||||||
staticSize = 2
|
staticSize = 2
|
||||||
|
|
||||||
def readOffset(self, reader):
|
def readOffset(self, reader):
|
||||||
@ -746,16 +745,15 @@ class Table(Struct):
|
|||||||
if value is None:
|
if value is None:
|
||||||
self.writeNullOffset(writer)
|
self.writeNullOffset(writer)
|
||||||
else:
|
else:
|
||||||
subWriter = writer.getSubWriter(offsetSize=self.staticSize)
|
subWriter = writer.getSubWriter()
|
||||||
subWriter.name = self.name
|
subWriter.name = self.name
|
||||||
if repeatIndex is not None:
|
if repeatIndex is not None:
|
||||||
subWriter.repeatIndex = repeatIndex
|
subWriter.repeatIndex = repeatIndex
|
||||||
writer.writeSubTable(subWriter)
|
writer.writeSubTable(subWriter, offsetSize=self.staticSize)
|
||||||
value.compile(subWriter, font)
|
value.compile(subWriter, font)
|
||||||
|
|
||||||
|
|
||||||
class LTable(Table):
|
class LTable(Table):
|
||||||
|
|
||||||
staticSize = 4
|
staticSize = 4
|
||||||
|
|
||||||
def readOffset(self, reader):
|
def readOffset(self, reader):
|
||||||
@ -767,7 +765,6 @@ class LTable(Table):
|
|||||||
|
|
||||||
# Table pointed to by a 24-bit, 3-byte long offset
|
# Table pointed to by a 24-bit, 3-byte long offset
|
||||||
class Table24(Table):
|
class Table24(Table):
|
||||||
|
|
||||||
staticSize = 3
|
staticSize = 3
|
||||||
|
|
||||||
def readOffset(self, reader):
|
def readOffset(self, reader):
|
||||||
@ -1147,13 +1144,13 @@ class AATLookupWithDataOffset(BaseConverter):
|
|||||||
offsetByGlyph[glyph] = offset
|
offsetByGlyph[glyph] = offset
|
||||||
# For calculating the offsets to our AATLookup and data table,
|
# For calculating the offsets to our AATLookup and data table,
|
||||||
# we can use the regular OTTableWriter infrastructure.
|
# we can use the regular OTTableWriter infrastructure.
|
||||||
lookupWriter = writer.getSubWriter(offsetSize=4)
|
lookupWriter = writer.getSubWriter()
|
||||||
lookup = AATLookup("DataOffsets", None, None, UShort)
|
lookup = AATLookup("DataOffsets", None, None, UShort)
|
||||||
lookup.write(lookupWriter, font, tableDict, offsetByGlyph, None)
|
lookup.write(lookupWriter, font, tableDict, offsetByGlyph, None)
|
||||||
|
|
||||||
dataWriter = writer.getSubWriter(offsetSize=4)
|
dataWriter = writer.getSubWriter()
|
||||||
writer.writeSubTable(lookupWriter)
|
writer.writeSubTable(lookupWriter, offsetSize=4)
|
||||||
writer.writeSubTable(dataWriter)
|
writer.writeSubTable(dataWriter, offsetSize=4)
|
||||||
for d in compiledData:
|
for d in compiledData:
|
||||||
dataWriter.writeData(d)
|
dataWriter.writeData(d)
|
||||||
|
|
||||||
@ -1483,9 +1480,9 @@ class STXHeader(BaseConverter):
|
|||||||
)
|
)
|
||||||
writer = OTTableWriter()
|
writer = OTTableWriter()
|
||||||
for lookup in table.PerGlyphLookups:
|
for lookup in table.PerGlyphLookups:
|
||||||
lookupWriter = writer.getSubWriter(offsetSize=4)
|
lookupWriter = writer.getSubWriter()
|
||||||
self.perGlyphLookup.write(lookupWriter, font, {}, lookup, None)
|
self.perGlyphLookup.write(lookupWriter, font, {}, lookup, None)
|
||||||
writer.writeSubTable(lookupWriter)
|
writer.writeSubTable(lookupWriter, offsetSize=4)
|
||||||
return writer.getAllData()
|
return writer.getAllData()
|
||||||
|
|
||||||
def _compileLigComponents(self, table, font):
|
def _compileLigComponents(self, table, font):
|
||||||
|
@ -116,7 +116,7 @@ COLR_V1_SAMPLE = (
|
|||||||
(b"\x00\x03", "LayerRecordCount (3)"),
|
(b"\x00\x03", "LayerRecordCount (3)"),
|
||||||
(b"\x00\x00\x00\x34", "Offset to BaseGlyphList from beginning of table (52)"),
|
(b"\x00\x00\x00\x34", "Offset to BaseGlyphList from beginning of table (52)"),
|
||||||
(b"\x00\x00\x00\x9f", "Offset to LayerList from beginning of table (159)"),
|
(b"\x00\x00\x00\x9f", "Offset to LayerList from beginning of table (159)"),
|
||||||
(b"\x00\x00\x01\x62", "Offset to ClipList (354)"),
|
(b"\x00\x00\x01\x66", "Offset to ClipList (358)"),
|
||||||
(b"\x00\x00\x00\x00", "Offset to DeltaSetIndexMap (NULL)"),
|
(b"\x00\x00\x00\x00", "Offset to DeltaSetIndexMap (NULL)"),
|
||||||
(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)"),
|
||||||
@ -187,22 +187,26 @@ COLR_V1_SAMPLE = (
|
|||||||
(b"\x00\x05", "ColorLine.ColorStop[1].PaletteIndex (5)"),
|
(b"\x00\x05", "ColorLine.ColorStop[1].PaletteIndex (5)"),
|
||||||
(b"@\x00", "ColorLine.ColorStop[1].Alpha (1.0)"),
|
(b"@\x00", "ColorLine.ColorStop[1].Alpha (1.0)"),
|
||||||
# LayerList
|
# LayerList
|
||||||
(b"\x00\x00\x00\x04", "LayerList.LayerCount (4)"),
|
(b"\x00\x00\x00\x05", "LayerList.LayerCount (5)"),
|
||||||
(
|
(
|
||||||
b"\x00\x00\x00\x14",
|
b"\x00\x00\x00\x18",
|
||||||
"First Offset to Paint table from beginning of LayerList (20)",
|
"First Offset to Paint table from beginning of LayerList (24)",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
b"\x00\x00\x00\x23",
|
b"\x00\x00\x00\x27",
|
||||||
"Second Offset to Paint table from beginning of LayerList (35)",
|
"Second Offset to Paint table from beginning of LayerList (39)",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
b"\x00\x00\x00\x4e",
|
b"\x00\x00\x00\x52",
|
||||||
"Third Offset to Paint table from beginning of LayerList (78)",
|
"Third Offset to Paint table from beginning of LayerList (82)",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
b"\x00\x00\x00\x9e",
|
b"\x00\x00\x00\xa2",
|
||||||
"Fourth Offset to Paint table from beginning of LayerList (158)",
|
"Fourth Offset to Paint table from beginning of LayerList (162)",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
b"\x00\x00\x00\xbc",
|
||||||
|
"Fifth Offset to Paint table from beginning of LayerList (188)",
|
||||||
),
|
),
|
||||||
# BaseGlyphPaintRecord[2]
|
# BaseGlyphPaintRecord[2]
|
||||||
(b"\x0a", "BaseGlyphPaintRecord[2].Paint.Format (10)"),
|
(b"\x0a", "BaseGlyphPaintRecord[2].Paint.Format (10)"),
|
||||||
@ -296,7 +300,7 @@ COLR_V1_SAMPLE = (
|
|||||||
),
|
),
|
||||||
(b"\xfc\x17", "xSkewAngle (-0.0611)"),
|
(b"\xfc\x17", "xSkewAngle (-0.0611)"),
|
||||||
(b"\x01\xc7", "ySkewAngle (0.0278)"),
|
(b"\x01\xc7", "ySkewAngle (0.0278)"),
|
||||||
# PaintGlyph
|
# PaintGlyph glyph00011 (pointed to by both PaintSkew above and by LayerList[4] offset)
|
||||||
(b"\x0a", "LayerList.Paint[3].Paint.Paint.Paint.Format (10)"),
|
(b"\x0a", "LayerList.Paint[3].Paint.Paint.Paint.Format (10)"),
|
||||||
(b"\x00\x00\x06", "Offset to Paint subtable from beginning of PaintGlyph (6)"),
|
(b"\x00\x00\x06", "Offset to Paint subtable from beginning of PaintGlyph (6)"),
|
||||||
(b"\x00\x0b", "LayerList.Paint[2].Glyph (11)"),
|
(b"\x00\x0b", "LayerList.Paint[2].Glyph (11)"),
|
||||||
@ -413,7 +417,7 @@ COLR_V1_XML = [
|
|||||||
" </BaseGlyphPaintRecord>",
|
" </BaseGlyphPaintRecord>",
|
||||||
"</BaseGlyphList>",
|
"</BaseGlyphList>",
|
||||||
"<LayerList>",
|
"<LayerList>",
|
||||||
" <!-- LayerCount=4 -->",
|
" <!-- LayerCount=5 -->",
|
||||||
' <Paint index="0" Format="10"><!-- PaintGlyph -->',
|
' <Paint index="0" Format="10"><!-- PaintGlyph -->',
|
||||||
' <Paint Format="3"><!-- PaintVarSolid -->',
|
' <Paint Format="3"><!-- PaintVarSolid -->',
|
||||||
' <PaletteIndex value="2"/>',
|
' <PaletteIndex value="2"/>',
|
||||||
@ -510,6 +514,13 @@ COLR_V1_XML = [
|
|||||||
' <dx value="257"/>',
|
' <dx value="257"/>',
|
||||||
' <dy value="258"/>',
|
' <dy value="258"/>',
|
||||||
" </Paint>",
|
" </Paint>",
|
||||||
|
' <Paint index="4" Format="10"><!-- PaintGlyph -->',
|
||||||
|
' <Paint Format="2"><!-- PaintSolid -->',
|
||||||
|
' <PaletteIndex value="2"/>',
|
||||||
|
' <Alpha value="0.5"/>',
|
||||||
|
" </Paint>",
|
||||||
|
' <Glyph value="glyph00011"/>',
|
||||||
|
" </Paint>",
|
||||||
"</LayerList>",
|
"</LayerList>",
|
||||||
'<ClipList Format="1">',
|
'<ClipList Format="1">',
|
||||||
" <Clip>",
|
" <Clip>",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user