[designspaceLib] Add properties to designspace documents

This commit is contained in:
Jany Belluz 2018-02-12 12:25:12 +00:00
parent 007a72ac29
commit 4c91f51aed

View File

@ -5,6 +5,7 @@ import collections
import logging
import os
import posixpath
import plistlib
import xml.etree.ElementTree as ET
# from mutatorMath.objects.location import biasFromLocations, Location
@ -16,7 +17,35 @@ import xml.etree.ElementTree as ET
- warpmap is stored in its axis element
"""
__all__ = [ 'DesignSpaceDocumentError', 'DesignSpaceDocument', 'SourceDescriptor', 'InstanceDescriptor', 'AxisDescriptor', 'RuleDescriptor', 'BaseDocReader', 'BaseDocWriter']
__all__ = [
'DesignSpaceDocumentError', 'DesignSpaceDocument', 'SourceDescriptor',
'InstanceDescriptor', 'AxisDescriptor', 'RuleDescriptor', 'BaseDocReader',
'BaseDocWriter'
]
def to_plist(value):
try:
# Python 2
string = plistlib.writePlistToString(value)
except AttributeError:
# Python 3
string = plistlib.dumps(value).decode()
return ET.fromstring(string).getchildren()[0]
def from_plist(element):
if element is None:
return {}
plist = ET.Element('plist')
plist.append(element)
string = ET.tostring(plist)
try:
# Python 2
return plistlib.readPlistFromString(string)
except AttributeError:
# Python 3
return plistlib.loads(string, fmt=plistlib.FMT_XML)
def posix(path):
@ -92,6 +121,7 @@ class SourceDescriptor(SimpleDescriptor):
def __init__(self):
self.filename = None # the original path as found in the document
self.path = None # the absolute path, calculated from filename
self.font = None # optional: an instance of defcon.Font
self.name = None
self.location = None
self.copyLib = False
@ -185,7 +215,8 @@ class InstanceDescriptor(SimpleDescriptor):
'styleMapFamilyName',
'styleMapStyleName',
'kerning',
'info']
'info',
'lib']
def __init__(self):
self.filename = None # the original path as found in the document
@ -205,6 +236,7 @@ class InstanceDescriptor(SimpleDescriptor):
self.mutedGlyphNames = []
self.kerning = True
self.info = True
self.lib = {}
path = posixpath_property("_path")
filename = posixpath_property("_filename")
@ -340,6 +372,10 @@ class BaseDocWriter(object):
self.root.append(ET.Element("instances"))
for instanceObject in self.documentObject.instances:
self._addInstance(instanceObject)
if self.documentObject.lib:
self._addLib(self.documentObject.lib)
if pretty:
_indent(self.root, whitespace=self._whiteSpace)
tree = ET.ElementTree(self.root)
@ -493,6 +529,10 @@ class BaseDocWriter(object):
if instanceObject.info:
infoElement = ET.Element('info')
instanceElement.append(infoElement)
if instanceObject.lib:
libElement = ET.Element('lib')
libElement.append(to_plist(instanceObject.lib))
instanceElement.append(libElement)
self.root.findall('.instances')[0].append(instanceElement)
def _addSource(self, sourceObject):
@ -540,6 +580,11 @@ class BaseDocWriter(object):
sourceElement.append(locationElement)
self.root.findall('.sources')[0].append(sourceElement)
def _addLib(self, dict):
libElement = ET.Element('lib')
libElement.append(to_plist(dict))
self.root.append(libElement)
def _writeGlyphElement(self, instanceElement, instanceObject, glyphName, data):
glyphElement = ET.Element('glyph')
if data.get('mute'):
@ -596,6 +641,7 @@ class BaseDocReader(object):
self.readRules()
self.readSources()
self.readInstances()
self.readLib()
def getSourcePaths(self, makeGlyphs=True, makeKerning=True, makeInfo=True):
paths = []
@ -874,8 +920,14 @@ class BaseDocReader(object):
self.readGlyphElement(glyphElement, instanceObject)
for infoElement in instanceElement.findall("info"):
self.readInfoElement(infoElement, instanceObject)
for libElement in instanceElement.findall('lib'):
self.readLibElement(libElement, instanceObject)
self.documentObject.instances.append(instanceObject)
def readLibElement(self, libElement, instanceObject):
"""Read the lib element for the given instance."""
instanceObject.lib = from_plist(libElement.getchildren()[0])
def readInfoElement(self, infoElement, instanceObject):
""" Read the info element.
@ -962,12 +1014,18 @@ class BaseDocReader(object):
glyphData['masters'] = glyphSources
instanceObject.glyphs[glyphName] = glyphData
def readLib(self):
"""Read the lib element for the whole document."""
for libElement in self.root.findall(".lib"):
self.documentObject.lib = from_plist(libElement.getchildren()[0])
class DesignSpaceDocument(object):
""" Read, write data from the designspace file"""
def __init__(self, readerClass=None, writerClass=None):
self.logger = logging.getLogger("DesignSpaceDocumentLog")
self.path = None
self.filename = None
self.formatVersion = None
self.sources = []
self.instances = []
@ -975,6 +1033,7 @@ class DesignSpaceDocument(object):
self.rules = []
self.default = None # name of the default master
self.defaultLoc = None
self.lib = {}
#
if readerClass is not None:
self.readerClass = readerClass