Merge branch 'master' of https://github.com/LettError/designSpaceDocument
# Conflicts: # Lib/designSpaceDocument/__init__.py
This commit is contained in:
commit
079771dd76
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,6 @@
|
|||||||
test.designspace
|
test.designspace
|
||||||
Lib/DesignSpaceDocument.egg-info
|
Lib/DesignSpaceDocument.egg-info
|
||||||
|
.cache
|
||||||
|
__pycache__
|
||||||
|
*.py[co]
|
||||||
|
.DS_Store
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import print_function, unicode_literals
|
||||||
import os
|
import os
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
@ -19,13 +20,16 @@ __all__ = [
|
|||||||
'SourceDescriptor', 'InstanceDescriptor',
|
'SourceDescriptor', 'InstanceDescriptor',
|
||||||
'AxisDescriptor', 'BaseDocReader', 'BaseDocWriter']
|
'AxisDescriptor', 'BaseDocReader', 'BaseDocWriter']
|
||||||
|
|
||||||
|
|
||||||
class DesignSpaceDocumentError(Exception):
|
class DesignSpaceDocumentError(Exception):
|
||||||
def __init__(self, msg, obj=None):
|
def __init__(self, msg, obj=None):
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return repr(self.msg) + repr(self.obj)
|
return repr(self.msg) + repr(self.obj)
|
||||||
|
|
||||||
|
|
||||||
def _indent(elem, whitespace=" ", level=0):
|
def _indent(elem, whitespace=" ", level=0):
|
||||||
# taken from http://effbot.org/zone/element-lib.htm#prettyprint
|
# taken from http://effbot.org/zone/element-lib.htm#prettyprint
|
||||||
i = "\n" + level * whitespace
|
i = "\n" + level * whitespace
|
||||||
@ -42,26 +46,28 @@ def _indent(elem, whitespace=" ", level=0):
|
|||||||
if level and (not elem.tail or not elem.tail.strip()):
|
if level and (not elem.tail or not elem.tail.strip()):
|
||||||
elem.tail = i
|
elem.tail = i
|
||||||
|
|
||||||
|
|
||||||
class SimpleDescriptor(object):
|
class SimpleDescriptor(object):
|
||||||
""" Containers for a bunch of attributes"""
|
""" Containers for a bunch of attributes"""
|
||||||
def compare(self, other):
|
def compare(self, other):
|
||||||
# test if this object contains the same data as the other
|
# test if this object contains the same data as the other
|
||||||
for attr in self._attrs:
|
for attr in self._attrs:
|
||||||
try:
|
try:
|
||||||
#print getattr(self, attr), getattr(other, attr)
|
assert(getattr(self, attr) == getattr(other, attr))
|
||||||
assert(getattr(self,attr) == getattr(other,attr))
|
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
print "failed attribute", attr, getattr(self, attr), "!=", getattr(other, attr)
|
print("failed attribute", attr, getattr(self, attr), "!=", getattr(other, attr))
|
||||||
|
|
||||||
|
|
||||||
class SourceDescriptor(SimpleDescriptor):
|
class SourceDescriptor(SimpleDescriptor):
|
||||||
"""Simple container for data related to the source"""
|
"""Simple container for data related to the source"""
|
||||||
flavor="source"
|
flavor = "source"
|
||||||
_attrs = [ 'path', 'name',
|
_attrs = ['path', 'name',
|
||||||
'location', 'copyLib',
|
'location', 'copyLib',
|
||||||
'copyGroups', 'copyFeatures',
|
'copyGroups', 'copyFeatures',
|
||||||
'muteKerning', 'muteInfo',
|
'muteKerning', 'muteInfo',
|
||||||
'mutedGlyphNames',
|
'mutedGlyphNames',
|
||||||
'familyName', 'styleName']
|
'familyName', 'styleName']
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.path = None
|
self.path = None
|
||||||
self.name = None
|
self.name = None
|
||||||
@ -79,13 +85,14 @@ class SourceDescriptor(SimpleDescriptor):
|
|||||||
|
|
||||||
class InstanceDescriptor(SimpleDescriptor):
|
class InstanceDescriptor(SimpleDescriptor):
|
||||||
"""Simple container for data related to the instance"""
|
"""Simple container for data related to the instance"""
|
||||||
flavor="instance"
|
flavor = "instance"
|
||||||
_attrs = [ 'path', 'name',
|
_attrs = ['path', 'name',
|
||||||
'location', 'familyName',
|
'location', 'familyName',
|
||||||
'styleName', 'postScriptFontName',
|
'styleName', 'postScriptFontName',
|
||||||
'styleMapFamilyName',
|
'styleMapFamilyName',
|
||||||
'styleMapStyleName',
|
'styleMapStyleName',
|
||||||
'kerning', 'info']
|
'kerning', 'info']
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.path = None
|
self.path = None
|
||||||
self.name = None
|
self.name = None
|
||||||
@ -102,19 +109,20 @@ class InstanceDescriptor(SimpleDescriptor):
|
|||||||
|
|
||||||
class AxisDescriptor(SimpleDescriptor):
|
class AxisDescriptor(SimpleDescriptor):
|
||||||
"""Simple container for the axis data"""
|
"""Simple container for the axis data"""
|
||||||
flavor="axis"
|
flavor = "axis"
|
||||||
_attrs = ['tag', 'name', 'maximum', 'minimum', 'default', 'map']
|
_attrs = ['tag', 'name', 'maximum', 'minimum', 'default', 'map']
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.tag = None # opentype tag for this axis
|
self.tag = None # opentype tag for this axis
|
||||||
self.name = None # name of the axis used in locations
|
self.name = None # name of the axis used in locations
|
||||||
self.labelNames = {} # names for UI purposes, if this is not a standard axis,
|
self.labelNames = {} # names for UI purposes, if this is not a standard axis,
|
||||||
self.minimum = None
|
self.minimum = None
|
||||||
self.maximum = None
|
self.maximum = None
|
||||||
self.default = None
|
self.default = None
|
||||||
self.map = []
|
self.map = []
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
# output to a dict
|
# output to a dict, used in testing
|
||||||
d = dict(tag = self.tag,
|
d = dict(tag = self.tag,
|
||||||
name = self.name,
|
name = self.name,
|
||||||
labelNames = self.labelNames,
|
labelNames = self.labelNames,
|
||||||
@ -131,12 +139,13 @@ class BaseDocWriter(object):
|
|||||||
axisDescriptorClass = AxisDescriptor
|
axisDescriptorClass = AxisDescriptor
|
||||||
sourceDescriptorClass = SourceDescriptor
|
sourceDescriptorClass = SourceDescriptor
|
||||||
instanceDescriptorClass = InstanceDescriptor
|
instanceDescriptorClass = InstanceDescriptor
|
||||||
|
|
||||||
def __init__(self, documentPath, documentObject):
|
def __init__(self, documentPath, documentObject):
|
||||||
self.path = documentPath
|
self.path = documentPath
|
||||||
self.documentObject = documentObject
|
self.documentObject = documentObject
|
||||||
self.toolVersion = 3
|
self.toolVersion = 3
|
||||||
self.root = ET.Element("designspace")
|
self.root = ET.Element("designspace")
|
||||||
self.root.attrib['format'] = "%d"%self.toolVersion
|
self.root.attrib['format'] = "%d" % self.toolVersion
|
||||||
self.root.append(ET.Element("axes"))
|
self.root.append(ET.Element("axes"))
|
||||||
self.root.append(ET.Element("sources"))
|
self.root.append(ET.Element("sources"))
|
||||||
self.root.append(ET.Element("instances"))
|
self.root.append(ET.Element("instances"))
|
||||||
@ -158,13 +167,13 @@ class BaseDocWriter(object):
|
|||||||
if pretty:
|
if pretty:
|
||||||
_indent(self.root, whitespace=self._whiteSpace)
|
_indent(self.root, whitespace=self._whiteSpace)
|
||||||
tree = ET.ElementTree(self.root)
|
tree = ET.ElementTree(self.root)
|
||||||
tree.write(self.path, encoding=u"utf-8", method='xml', xml_declaration=True)
|
tree.write(self.path, encoding="utf-8", method='xml', xml_declaration=True)
|
||||||
|
|
||||||
def _makeLocationElement(self, locationObject, name=None):
|
def _makeLocationElement(self, locationObject, name=None):
|
||||||
""" Convert Location dict to a locationElement."""
|
""" Convert Location dict to a locationElement."""
|
||||||
locElement = ET.Element("location")
|
locElement = ET.Element("location")
|
||||||
if name is not None:
|
if name is not None:
|
||||||
locElement.attrib['name'] = name
|
locElement.attrib['name'] = name
|
||||||
defaultLoc = self.newDefaultLocation()
|
defaultLoc = self.newDefaultLocation()
|
||||||
validatedLocation = {}
|
validatedLocation = {}
|
||||||
for axisName, axisValue in defaultLoc.items():
|
for axisName, axisValue in defaultLoc.items():
|
||||||
@ -174,20 +183,20 @@ class BaseDocWriter(object):
|
|||||||
else:
|
else:
|
||||||
validatedLocation[axisName] = locationObject[axisName]
|
validatedLocation[axisName] = locationObject[axisName]
|
||||||
for dimensionName, dimensionValue in validatedLocation.items():
|
for dimensionName, dimensionValue in validatedLocation.items():
|
||||||
dimElement = ET.Element('dimension')
|
dimElement = ET.Element('dimension')
|
||||||
dimElement.attrib['name'] = dimensionName
|
dimElement.attrib['name'] = dimensionName
|
||||||
if type(dimensionValue)==tuple:
|
if type(dimensionValue) == tuple:
|
||||||
dimElement.attrib['xvalue'] = self.intOrFloat(dimensionValue[0])
|
dimElement.attrib['xvalue'] = self.intOrFloat(dimensionValue[0])
|
||||||
dimElement.attrib['yvalue'] = self.intOrFloat(dimensionValue[1])
|
dimElement.attrib['yvalue'] = self.intOrFloat(dimensionValue[1])
|
||||||
else:
|
else:
|
||||||
dimElement.attrib['xvalue'] = self.intOrFloat(dimensionValue)
|
dimElement.attrib['xvalue'] = self.intOrFloat(dimensionValue)
|
||||||
locElement.append(dimElement)
|
locElement.append(dimElement)
|
||||||
return locElement, validatedLocation
|
return locElement, validatedLocation
|
||||||
|
|
||||||
def intOrFloat(self, num):
|
def intOrFloat(self, num):
|
||||||
if int(num) == num:
|
if int(num) == num:
|
||||||
return "%d"%num
|
return "%d" % num
|
||||||
return "%f"%num
|
return "%f" % num
|
||||||
|
|
||||||
def _addAxis(self, axisObject):
|
def _addAxis(self, axisObject):
|
||||||
self.axes.append(axisObject)
|
self.axes.append(axisObject)
|
||||||
@ -319,10 +328,12 @@ class BaseDocWriter(object):
|
|||||||
glyphElement.append(mastersElement)
|
glyphElement.append(mastersElement)
|
||||||
return glyphElement
|
return glyphElement
|
||||||
|
|
||||||
|
|
||||||
class BaseDocReader(object):
|
class BaseDocReader(object):
|
||||||
axisDescriptorClass = AxisDescriptor
|
axisDescriptorClass = AxisDescriptor
|
||||||
sourceDescriptorClass = SourceDescriptor
|
sourceDescriptorClass = SourceDescriptor
|
||||||
instanceDescriptorClass = InstanceDescriptor
|
instanceDescriptorClass = InstanceDescriptor
|
||||||
|
|
||||||
def __init__(self, documentPath, documentObject):
|
def __init__(self, documentPath, documentObject):
|
||||||
self.path = documentPath
|
self.path = documentPath
|
||||||
self.documentObject = documentObject
|
self.documentObject = documentObject
|
||||||
@ -566,9 +577,9 @@ class BaseDocReader(object):
|
|||||||
if masterGlyphName is None:
|
if masterGlyphName is None:
|
||||||
# if we don't read a glyphname, use the one we have
|
# if we don't read a glyphname, use the one we have
|
||||||
masterGlyphName = glyphName
|
masterGlyphName = glyphName
|
||||||
d = dict( font=fontSourceName,
|
d = dict(font=fontSourceName,
|
||||||
location=sourceLocation,
|
location=sourceLocation,
|
||||||
glyphName=masterGlyphName)
|
glyphName=masterGlyphName)
|
||||||
if glyphSources is None:
|
if glyphSources is None:
|
||||||
glyphSources = []
|
glyphSources = []
|
||||||
glyphSources.append(d)
|
glyphSources.append(d)
|
||||||
@ -620,14 +631,10 @@ class DesignSpaceDocument(object):
|
|||||||
return loc
|
return loc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
u"""
|
"""
|
||||||
>>> import os
|
>>> import os
|
||||||
>>> testDocPath = os.path.join(os.getcwd(), "test.designspace")
|
>>> testDocPath = os.path.join(os.getcwd(), "test.designspace")
|
||||||
>>> masterPath1 = os.path.join(os.getcwd(), "masters", "masterTest1.ufo")
|
>>> masterPath1 = os.path.join(os.getcwd(), "masters", "masterTest1.ufo")
|
||||||
@ -753,5 +760,4 @@ if __name__ == "__main__":
|
|||||||
def _test():
|
def _test():
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod()
|
doctest.testmod()
|
||||||
|
|
||||||
_test()
|
_test()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user