blob: 2366c5e632b7921a90bc56c6e90007309f7a2c2d [file] [log] [blame]
# Copyright 2013 Google, Inc. All Rights Reserved.
#
# Google Author(s): Behdad Esfahbod
from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval
from . import DefaultTable
class table_C_O_L_R_(DefaultTable.DefaultTable):
""" This table is structured so that you can treat it like a dictionary keyed by glyph name.
ttFont['COLR'][<glyphName>] will return the color layers for any glyph
ttFont['COLR'][<glyphName>] = <value> will set the color layers for any glyph.
"""
def _fromOTTable(self, table):
self.version = 0
self.ColorLayers = colorLayerLists = {}
layerRecords = table.LayerRecordArray.LayerRecord
numLayerRecords = len(layerRecords)
for baseRec in table.BaseGlyphRecordArray.BaseGlyphRecord:
baseGlyph = baseRec.BaseGlyph
firstLayerIndex = baseRec.FirstLayerIndex
numLayers = baseRec.NumLayers
assert (firstLayerIndex + numLayers <= numLayerRecords)
layers = []
for i in range(firstLayerIndex, firstLayerIndex+numLayers):
layerRec = layerRecords[i]
layers.append(
LayerRecord(layerRec.LayerGlyph, layerRec.PaletteIndex)
)
colorLayerLists[baseGlyph] = layers
def _toOTTable(self, ttFont):
from . import otTables
from fontTools.colorLib.builder import populateCOLRv0
tableClass = getattr(otTables, self.tableTag)
table = tableClass()
table.Version = self.version
populateCOLRv0(
table,
{
baseGlyph: [(layer.name, layer.colorID) for layer in layers]
for baseGlyph, layers in self.ColorLayers.items()
},
glyphMap=ttFont.getReverseGlyphMap(rebuild=True),
)
return table
def decompile(self, data, ttFont):
from .otBase import OTTableReader
from . import otTables
# We use otData to decompile, but we adapt the decompiled otTables to the
# existing COLR v0 API for backward compatibility.
reader = OTTableReader(data, tableTag=self.tableTag)
tableClass = getattr(otTables, self.tableTag)
table = tableClass()
table.decompile(reader, ttFont)
if table.Version == 0:
self._fromOTTable(table)
else:
# for new versions, keep the raw otTables around
self.table = table
def compile(self, ttFont):
from .otBase import OTTableWriter
if hasattr(self, "table"):
table = self.table
else:
table = self._toOTTable(ttFont)
writer = OTTableWriter(tableTag=self.tableTag)
table.compile(writer, ttFont)
return writer.getAllData()
def toXML(self, writer, ttFont):
if hasattr(self, "table"):
self.table.toXML2(writer, ttFont)
else:
writer.simpletag("version", value=self.version)
writer.newline()
for baseGlyph in sorted(self.ColorLayers.keys(), key=ttFont.getGlyphID):
writer.begintag("ColorGlyph", name=baseGlyph)
writer.newline()
for layer in self.ColorLayers[baseGlyph]:
layer.toXML(writer, ttFont)
writer.endtag("ColorGlyph")
writer.newline()
def fromXML(self, name, attrs, content, ttFont):
if name == "version": # old COLR v0 API
setattr(self, name, safeEval(attrs["value"]))
elif name == "ColorGlyph":
if not hasattr(self, "ColorLayers"):
self.ColorLayers = {}
glyphName = attrs["name"]
for element in content:
if isinstance(element, basestring):
continue
layers = []
for element in content:
if isinstance(element, basestring):
continue
layer = LayerRecord()
layer.fromXML(element[0], element[1], element[2], ttFont)
layers.append (layer)
self.ColorLayers[glyphName] = layers
else: # new COLR v1 API
from . import otTables
if not hasattr(self, "table"):
tableClass = getattr(otTables, self.tableTag)
self.table = tableClass()
self.table.fromXML(name, attrs, content, ttFont)
self.table.populateDefaults()
def __getitem__(self, glyphName):
if not isinstance(glyphName, str):
raise TypeError(f"expected str, found {type(glyphName).__name__}")
return self.ColorLayers[glyphName]
def __setitem__(self, glyphName, value):
if not isinstance(glyphName, str):
raise TypeError(f"expected str, found {type(glyphName).__name__}")
if value is not None:
self.ColorLayers[glyphName] = value
elif glyphName in self.ColorLayers:
del self.ColorLayers[glyphName]
def __delitem__(self, glyphName):
del self.ColorLayers[glyphName]
class LayerRecord(object):
def __init__(self, name=None, colorID=None):
self.name = name
self.colorID = colorID
def toXML(self, writer, ttFont):
writer.simpletag("layer", name=self.name, colorID=self.colorID)
writer.newline()
def fromXML(self, eltname, attrs, content, ttFont):
for (name, value) in attrs.items():
if name == "name":
setattr(self, name, value)
else:
setattr(self, name, safeEval(value))