2017-11-29 17:08:23 +00:00
|
|
|
# coding=utf-8
|
|
|
|
|
|
|
|
from __future__ import (print_function, division, absolute_import,
|
|
|
|
unicode_literals)
|
|
|
|
|
|
|
|
import os
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
from fontTools.misc.py23 import open
|
|
|
|
from fontTools.designspaceLib import (
|
|
|
|
DesignSpaceDocument, SourceDescriptor, AxisDescriptor, RuleDescriptor,
|
|
|
|
InstanceDescriptor, evaluateRule, processRules, posix)
|
|
|
|
|
|
|
|
|
|
|
|
def test_fill_document(tmpdir):
|
|
|
|
tmpdir = str(tmpdir)
|
|
|
|
testDocPath = os.path.join(tmpdir, "test.designspace")
|
|
|
|
masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
|
|
|
|
masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
|
|
|
|
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
|
|
|
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# add master 1
|
|
|
|
s1 = SourceDescriptor()
|
|
|
|
s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
|
|
|
|
s1.name = "master.ufo1"
|
|
|
|
s1.copyLib = True
|
|
|
|
s1.copyInfo = True
|
|
|
|
s1.copyFeatures = True
|
|
|
|
s1.location = dict(weight=0)
|
|
|
|
s1.familyName = "MasterFamilyName"
|
|
|
|
s1.styleName = "MasterStyleNameOne"
|
|
|
|
s1.mutedGlyphNames.append("A")
|
|
|
|
s1.mutedGlyphNames.append("Z")
|
|
|
|
doc.addSource(s1)
|
|
|
|
# add master 2
|
|
|
|
s2 = SourceDescriptor()
|
|
|
|
s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
|
|
|
|
s2.name = "master.ufo2"
|
|
|
|
s2.copyLib = False
|
|
|
|
s2.copyInfo = False
|
|
|
|
s2.copyFeatures = False
|
|
|
|
s2.muteKerning = True
|
|
|
|
s2.location = dict(weight=1000)
|
|
|
|
s2.familyName = "MasterFamilyName"
|
|
|
|
s2.styleName = "MasterStyleNameTwo"
|
|
|
|
doc.addSource(s2)
|
|
|
|
# add instance 1
|
|
|
|
i1 = InstanceDescriptor()
|
|
|
|
i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
|
|
|
|
i1.familyName = "InstanceFamilyName"
|
|
|
|
i1.styleName = "InstanceStyleName"
|
|
|
|
i1.name = "instance.ufo1"
|
|
|
|
i1.location = dict(weight=500, spooky=666) # this adds a dimension that is not defined.
|
|
|
|
i1.postScriptFontName = "InstancePostscriptName"
|
|
|
|
i1.styleMapFamilyName = "InstanceStyleMapFamilyName"
|
|
|
|
i1.styleMapStyleName = "InstanceStyleMapStyleName"
|
|
|
|
glyphData = dict(name="arrow", mute=True, unicodes=[0x123, 0x124, 0x125])
|
|
|
|
i1.glyphs['arrow'] = glyphData
|
|
|
|
doc.addInstance(i1)
|
|
|
|
# add instance 2
|
|
|
|
i2 = InstanceDescriptor()
|
|
|
|
i2.filename = os.path.relpath(instancePath2, os.path.dirname(testDocPath))
|
|
|
|
i2.familyName = "InstanceFamilyName"
|
|
|
|
i2.styleName = "InstanceStyleName"
|
|
|
|
i2.name = "instance.ufo2"
|
|
|
|
# anisotropic location
|
|
|
|
i2.location = dict(weight=500, width=(400,300))
|
|
|
|
i2.postScriptFontName = "InstancePostscriptName"
|
|
|
|
i2.styleMapFamilyName = "InstanceStyleMapFamilyName"
|
|
|
|
i2.styleMapStyleName = "InstanceStyleMapStyleName"
|
|
|
|
glyphMasters = [dict(font="master.ufo1", glyphName="BB", location=dict(width=20,weight=20)), dict(font="master.ufo2", glyphName="CC", location=dict(width=900,weight=900))]
|
|
|
|
glyphData = dict(name="arrow", unicodes=[101, 201, 301])
|
|
|
|
glyphData['masters'] = glyphMasters
|
|
|
|
glyphData['note'] = "A note about this glyph"
|
|
|
|
glyphData['instanceLocation'] = dict(width=100, weight=120)
|
|
|
|
i2.glyphs['arrow'] = glyphData
|
|
|
|
i2.glyphs['arrow2'] = dict(mute=False)
|
|
|
|
doc.addInstance(i2)
|
|
|
|
|
|
|
|
# now we have sources and instances, but no axes yet.
|
|
|
|
doc.check()
|
|
|
|
|
2017-11-30 12:21:29 +00:00
|
|
|
# Here, since the axes are not defined in the document, but instead are
|
|
|
|
# infered from the locations of the instances, we cannot guarantee the
|
|
|
|
# order in which they will be created by the `check()` method.
|
|
|
|
assert set(doc.getAxisOrder()) == set(['spooky', 'weight', 'width'])
|
2017-11-29 17:08:23 +00:00
|
|
|
doc.axes = [] # clear the axes
|
|
|
|
|
|
|
|
# write some axes
|
|
|
|
a1 = AxisDescriptor()
|
|
|
|
a1.minimum = 0
|
|
|
|
a1.maximum = 1000
|
|
|
|
a1.default = 0
|
|
|
|
a1.name = "weight"
|
|
|
|
a1.tag = "wght"
|
|
|
|
# note: just to test the element language, not an actual label name recommendations.
|
|
|
|
a1.labelNames[u'fa-IR'] = u"قطر"
|
|
|
|
a1.labelNames[u'en'] = u"Wéíght"
|
|
|
|
doc.addAxis(a1)
|
|
|
|
a2 = AxisDescriptor()
|
|
|
|
a2.minimum = 0
|
|
|
|
a2.maximum = 1000
|
|
|
|
a2.default = 20
|
|
|
|
a2.name = "width"
|
|
|
|
a2.tag = "wdth"
|
|
|
|
a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
|
|
|
|
a2.hidden = True
|
|
|
|
a2.labelNames[u'fr'] = u"Poids"
|
|
|
|
doc.addAxis(a2)
|
|
|
|
# add an axis that is not part of any location to see if that works
|
|
|
|
a3 = AxisDescriptor()
|
|
|
|
a3.minimum = 333
|
|
|
|
a3.maximum = 666
|
|
|
|
a3.default = 444
|
|
|
|
a3.name = "spooky"
|
|
|
|
a3.tag = "spok"
|
|
|
|
a3.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
|
|
|
|
#doc.addAxis(a3) # uncomment this line to test the effects of default axes values
|
|
|
|
# write some rules
|
|
|
|
r1 = RuleDescriptor()
|
|
|
|
r1.name = "named.rule.1"
|
|
|
|
r1.conditions.append(dict(name='aaaa', minimum=0, maximum=1))
|
|
|
|
r1.conditions.append(dict(name='bbbb', minimum=2, maximum=3))
|
|
|
|
r1.subs.append(("a", "a.alt"))
|
|
|
|
doc.addRule(r1)
|
|
|
|
# write the document
|
|
|
|
doc.write(testDocPath)
|
|
|
|
assert os.path.exists(testDocPath)
|
|
|
|
# import it again
|
|
|
|
new = DesignSpaceDocument()
|
|
|
|
new.read(testDocPath)
|
|
|
|
|
|
|
|
new.check()
|
|
|
|
assert new.default.location == {'width': 20.0, 'weight': 0.0}
|
|
|
|
|
|
|
|
# >>> for a, b in zip(doc.instances, new.instances):
|
|
|
|
# ... a.compare(b)
|
|
|
|
# >>> for a, b in zip(doc.sources, new.sources):
|
|
|
|
# ... a.compare(b)
|
|
|
|
# >>> for a, b in zip(doc.axes, new.axes):
|
|
|
|
# ... a.compare(b)
|
|
|
|
# >>> [n.mutedGlyphNames for n in new.sources]
|
|
|
|
# [['A', 'Z'], []]
|
|
|
|
# >>> doc.getFonts()
|
|
|
|
# []
|
|
|
|
|
|
|
|
# test roundtrip for the axis attributes and data
|
|
|
|
axes = {}
|
|
|
|
for axis in doc.axes:
|
|
|
|
if axis.tag not in axes:
|
|
|
|
axes[axis.tag] = []
|
|
|
|
axes[axis.tag].append(axis.serialize())
|
|
|
|
for axis in new.axes:
|
|
|
|
if axis.tag[0] == "_":
|
|
|
|
continue
|
|
|
|
if axis.tag not in axes:
|
|
|
|
axes[axis.tag] = []
|
|
|
|
axes[axis.tag].append(axis.serialize())
|
|
|
|
for v in axes.values():
|
|
|
|
a, b = v
|
|
|
|
assert a == b
|
|
|
|
|
|
|
|
|
|
|
|
def test_adjustAxisDefaultToNeutral(tmpdir):
|
|
|
|
tmpdir = str(tmpdir)
|
|
|
|
testDocPath = os.path.join(tmpdir, "testAdjustAxisDefaultToNeutral.designspace")
|
|
|
|
masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
|
|
|
|
masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
|
|
|
|
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
|
|
|
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# add master 1
|
|
|
|
s1 = SourceDescriptor()
|
|
|
|
s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
|
|
|
|
s1.name = "master.ufo1"
|
|
|
|
s1.copyInfo = True
|
|
|
|
s1.copyFeatures = True
|
|
|
|
s1.location = dict(weight=55, width=1000)
|
|
|
|
doc.addSource(s1)
|
|
|
|
# write some axes
|
|
|
|
a1 = AxisDescriptor()
|
|
|
|
a1.minimum = 0
|
|
|
|
a1.maximum = 1000
|
|
|
|
a1.default = 0 # the wrong value
|
|
|
|
a1.name = "weight"
|
|
|
|
a1.tag = "wght"
|
|
|
|
doc.addAxis(a1)
|
|
|
|
a2 = AxisDescriptor()
|
|
|
|
a2.minimum = -10
|
|
|
|
a2.maximum = 10
|
|
|
|
a2.default = 0 # the wrong value
|
|
|
|
a2.name = "width"
|
|
|
|
a2.tag = "wdth"
|
|
|
|
doc.addAxis(a2)
|
|
|
|
# write the document
|
|
|
|
doc.write(testDocPath)
|
|
|
|
assert os.path.exists(testDocPath)
|
|
|
|
# import it again
|
|
|
|
new = DesignSpaceDocument()
|
|
|
|
new.read(testDocPath)
|
|
|
|
new.check()
|
|
|
|
loc = new.default.location
|
|
|
|
for axisObj in new.axes:
|
|
|
|
n = axisObj.name
|
|
|
|
assert axisObj.default == loc.get(n)
|
|
|
|
|
|
|
|
|
|
|
|
def test_unicodes(tmpdir):
|
|
|
|
tmpdir = str(tmpdir)
|
|
|
|
testDocPath = os.path.join(tmpdir, "testUnicodes.designspace")
|
|
|
|
testDocPath2 = os.path.join(tmpdir, "testUnicodes_roundtrip.designspace")
|
|
|
|
masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
|
|
|
|
masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
|
|
|
|
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
|
|
|
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# add master 1
|
|
|
|
s1 = SourceDescriptor()
|
|
|
|
s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
|
|
|
|
s1.name = "master.ufo1"
|
|
|
|
s1.copyInfo = True
|
|
|
|
s1.location = dict(weight=0)
|
|
|
|
doc.addSource(s1)
|
|
|
|
# add master 2
|
|
|
|
s2 = SourceDescriptor()
|
|
|
|
s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
|
|
|
|
s2.name = "master.ufo2"
|
|
|
|
s2.location = dict(weight=1000)
|
|
|
|
doc.addSource(s2)
|
|
|
|
# add instance 1
|
|
|
|
i1 = InstanceDescriptor()
|
|
|
|
i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
|
|
|
|
i1.name = "instance.ufo1"
|
|
|
|
i1.location = dict(weight=500)
|
|
|
|
glyphData = dict(name="arrow", mute=True, unicodes=[100, 200, 300])
|
|
|
|
i1.glyphs['arrow'] = glyphData
|
|
|
|
doc.addInstance(i1)
|
|
|
|
# now we have sources and instances, but no axes yet.
|
|
|
|
doc.axes = [] # clear the axes
|
|
|
|
# write some axes
|
|
|
|
a1 = AxisDescriptor()
|
|
|
|
a1.minimum = 0
|
|
|
|
a1.maximum = 1000
|
|
|
|
a1.default = 0
|
|
|
|
a1.name = "weight"
|
|
|
|
a1.tag = "wght"
|
|
|
|
doc.addAxis(a1)
|
|
|
|
# write the document
|
|
|
|
doc.write(testDocPath)
|
|
|
|
assert os.path.exists(testDocPath)
|
|
|
|
# import it again
|
|
|
|
new = DesignSpaceDocument()
|
|
|
|
new.read(testDocPath)
|
|
|
|
new.write(testDocPath2)
|
|
|
|
# compare the file contents
|
|
|
|
f1 = open(testDocPath, 'r', encoding='utf-8')
|
|
|
|
t1 = f1.read()
|
|
|
|
f1.close()
|
|
|
|
f2 = open(testDocPath2, 'r', encoding='utf-8')
|
|
|
|
t2 = f2.read()
|
|
|
|
f2.close()
|
|
|
|
assert t1 == t2
|
|
|
|
# check the unicode values read from the document
|
|
|
|
assert new.instances[0].glyphs['arrow']['unicodes'] == [100,200,300]
|
|
|
|
|
|
|
|
|
|
|
|
def test_localisedNames(tmpdir):
|
|
|
|
tmpdir = str(tmpdir)
|
|
|
|
testDocPath = os.path.join(tmpdir, "testLocalisedNames.designspace")
|
|
|
|
testDocPath2 = os.path.join(tmpdir, "testLocalisedNames_roundtrip.designspace")
|
|
|
|
masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
|
|
|
|
masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
|
|
|
|
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
|
|
|
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# add master 1
|
|
|
|
s1 = SourceDescriptor()
|
|
|
|
s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
|
|
|
|
s1.name = "master.ufo1"
|
|
|
|
s1.copyInfo = True
|
|
|
|
s1.location = dict(weight=0)
|
|
|
|
doc.addSource(s1)
|
|
|
|
# add master 2
|
|
|
|
s2 = SourceDescriptor()
|
|
|
|
s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
|
|
|
|
s2.name = "master.ufo2"
|
|
|
|
s2.location = dict(weight=1000)
|
|
|
|
doc.addSource(s2)
|
|
|
|
# add instance 1
|
|
|
|
i1 = InstanceDescriptor()
|
|
|
|
i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
|
|
|
|
i1.familyName = "Montserrat"
|
|
|
|
i1.styleName = "SemiBold"
|
|
|
|
i1.styleMapFamilyName = "Montserrat SemiBold"
|
|
|
|
i1.styleMapStyleName = "Regular"
|
|
|
|
i1.setFamilyName("Montserrat", "fr")
|
|
|
|
i1.setFamilyName(u"モンセラート", "ja")
|
|
|
|
i1.setStyleName("Demigras", "fr")
|
|
|
|
i1.setStyleName(u"半ば", "ja")
|
|
|
|
i1.setStyleMapStyleName(u"Standard", "de")
|
|
|
|
i1.setStyleMapFamilyName("Montserrat Halbfett", "de")
|
|
|
|
i1.setStyleMapFamilyName(u"モンセラート SemiBold", "ja")
|
|
|
|
i1.name = "instance.ufo1"
|
|
|
|
i1.location = dict(weight=500, spooky=666) # this adds a dimension that is not defined.
|
|
|
|
i1.postScriptFontName = "InstancePostscriptName"
|
|
|
|
glyphData = dict(name="arrow", mute=True, unicodes=[0x123])
|
|
|
|
i1.glyphs['arrow'] = glyphData
|
|
|
|
doc.addInstance(i1)
|
|
|
|
# now we have sources and instances, but no axes yet.
|
|
|
|
doc.axes = [] # clear the axes
|
|
|
|
# write some axes
|
|
|
|
a1 = AxisDescriptor()
|
|
|
|
a1.minimum = 0
|
|
|
|
a1.maximum = 1000
|
|
|
|
a1.default = 0
|
|
|
|
a1.name = "weight"
|
|
|
|
a1.tag = "wght"
|
|
|
|
# note: just to test the element language, not an actual label name recommendations.
|
|
|
|
a1.labelNames[u'fa-IR'] = u"قطر"
|
|
|
|
a1.labelNames[u'en'] = u"Wéíght"
|
|
|
|
doc.addAxis(a1)
|
|
|
|
a2 = AxisDescriptor()
|
|
|
|
a2.minimum = 0
|
|
|
|
a2.maximum = 1000
|
|
|
|
a2.default = 0
|
|
|
|
a2.name = "width"
|
|
|
|
a2.tag = "wdth"
|
|
|
|
a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
|
|
|
|
a2.labelNames[u'fr'] = u"Poids"
|
|
|
|
doc.addAxis(a2)
|
|
|
|
# add an axis that is not part of any location to see if that works
|
|
|
|
a3 = AxisDescriptor()
|
|
|
|
a3.minimum = 333
|
|
|
|
a3.maximum = 666
|
|
|
|
a3.default = 444
|
|
|
|
a3.name = "spooky"
|
|
|
|
a3.tag = "spok"
|
|
|
|
a3.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
|
|
|
|
#doc.addAxis(a3) # uncomment this line to test the effects of default axes values
|
|
|
|
# write some rules
|
|
|
|
r1 = RuleDescriptor()
|
|
|
|
r1.name = "named.rule.1"
|
|
|
|
r1.conditions.append(dict(name='aaaa', minimum=0, maximum=1))
|
|
|
|
r1.conditions.append(dict(name='bbbb', minimum=2, maximum=3))
|
|
|
|
r1.subs.append(("a", "a.alt"))
|
|
|
|
doc.addRule(r1)
|
|
|
|
# write the document
|
|
|
|
doc.write(testDocPath)
|
|
|
|
assert os.path.exists(testDocPath)
|
|
|
|
# import it again
|
|
|
|
new = DesignSpaceDocument()
|
|
|
|
new.read(testDocPath)
|
|
|
|
new.write(testDocPath2)
|
|
|
|
f1 = open(testDocPath, 'r', encoding='utf-8')
|
|
|
|
t1 = f1.read()
|
|
|
|
f1.close()
|
|
|
|
f2 = open(testDocPath2, 'r', encoding='utf-8')
|
|
|
|
t2 = f2.read()
|
|
|
|
f2.close()
|
|
|
|
assert t1 == t2
|
|
|
|
|
|
|
|
|
|
|
|
def test_handleNoAxes(tmpdir):
|
|
|
|
tmpdir = str(tmpdir)
|
|
|
|
# test what happens if the designspacedocument has no axes element.
|
|
|
|
testDocPath = os.path.join(tmpdir, "testNoAxes_source.designspace")
|
|
|
|
testDocPath2 = os.path.join(tmpdir, "testNoAxes_recontructed.designspace")
|
|
|
|
masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
|
|
|
|
masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
|
|
|
|
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
|
|
|
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
|
|
|
|
|
|
|
# Case 1: No axes element in the document, but there are sources and instances
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
|
|
|
|
for name, value in [('One', 1),('Two', 2),('Three', 3)]:
|
|
|
|
a = AxisDescriptor()
|
|
|
|
a.minimum = 0
|
|
|
|
a.maximum = 1000
|
|
|
|
a.default = 0
|
|
|
|
a.name = "axisName%s"%(name)
|
|
|
|
a.tag = "ax_%d"%(value)
|
|
|
|
doc.addAxis(a)
|
|
|
|
|
|
|
|
# add master 1
|
|
|
|
s1 = SourceDescriptor()
|
|
|
|
s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
|
|
|
|
s1.name = "master.ufo1"
|
|
|
|
s1.copyLib = True
|
|
|
|
s1.copyInfo = True
|
|
|
|
s1.copyFeatures = True
|
|
|
|
s1.location = dict(axisNameOne=-1000, axisNameTwo=0, axisNameThree=1000)
|
|
|
|
s1.familyName = "MasterFamilyName"
|
|
|
|
s1.styleName = "MasterStyleNameOne"
|
|
|
|
doc.addSource(s1)
|
|
|
|
|
|
|
|
# add master 2
|
|
|
|
s2 = SourceDescriptor()
|
|
|
|
s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
|
|
|
|
s2.name = "master.ufo1"
|
|
|
|
s2.copyLib = False
|
|
|
|
s2.copyInfo = False
|
|
|
|
s2.copyFeatures = False
|
|
|
|
s2.location = dict(axisNameOne=1000, axisNameTwo=1000, axisNameThree=0)
|
|
|
|
s2.familyName = "MasterFamilyName"
|
|
|
|
s2.styleName = "MasterStyleNameTwo"
|
|
|
|
doc.addSource(s2)
|
|
|
|
|
|
|
|
# add instance 1
|
|
|
|
i1 = InstanceDescriptor()
|
|
|
|
i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
|
|
|
|
i1.familyName = "InstanceFamilyName"
|
|
|
|
i1.styleName = "InstanceStyleName"
|
|
|
|
i1.name = "instance.ufo1"
|
|
|
|
i1.location = dict(axisNameOne=(-1000,500), axisNameTwo=100)
|
|
|
|
i1.postScriptFontName = "InstancePostscriptName"
|
|
|
|
i1.styleMapFamilyName = "InstanceStyleMapFamilyName"
|
|
|
|
i1.styleMapStyleName = "InstanceStyleMapStyleName"
|
|
|
|
doc.addInstance(i1)
|
|
|
|
|
|
|
|
doc.write(testDocPath)
|
|
|
|
__removeAxesFromDesignSpace(testDocPath)
|
|
|
|
verify = DesignSpaceDocument()
|
|
|
|
verify.read(testDocPath)
|
|
|
|
verify.write(testDocPath2)
|
|
|
|
|
|
|
|
|
|
|
|
def test_pathNameResolve(tmpdir):
|
|
|
|
tmpdir = str(tmpdir)
|
|
|
|
# test how descriptor.path and descriptor.filename are resolved
|
|
|
|
testDocPath1 = os.path.join(tmpdir, "testPathName_case1.designspace")
|
|
|
|
testDocPath2 = os.path.join(tmpdir, "testPathName_case2.designspace")
|
|
|
|
testDocPath3 = os.path.join(tmpdir, "testPathName_case3.designspace")
|
|
|
|
testDocPath4 = os.path.join(tmpdir, "testPathName_case4.designspace")
|
|
|
|
testDocPath5 = os.path.join(tmpdir, "testPathName_case5.designspace")
|
|
|
|
testDocPath6 = os.path.join(tmpdir, "testPathName_case6.designspace")
|
|
|
|
masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
|
|
|
|
masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
|
|
|
|
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
|
|
|
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
|
|
|
|
|
|
|
# Case 1: filename and path are both empty. Nothing to calculate, nothing to put in the file.
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
s = SourceDescriptor()
|
|
|
|
s.filename = None
|
|
|
|
s.path = None
|
|
|
|
s.copyInfo = True
|
|
|
|
s.location = dict(weight=0)
|
|
|
|
s.familyName = "MasterFamilyName"
|
|
|
|
s.styleName = "MasterStyleNameOne"
|
|
|
|
doc.addSource(s)
|
|
|
|
doc.write(testDocPath1)
|
|
|
|
verify = DesignSpaceDocument()
|
|
|
|
verify.read(testDocPath1)
|
|
|
|
assert verify.sources[0].filename == None
|
|
|
|
assert verify.sources[0].path == None
|
|
|
|
|
|
|
|
# Case 2: filename is empty, path points somewhere: calculate a new filename.
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
s = SourceDescriptor()
|
|
|
|
s.filename = None
|
|
|
|
s.path = masterPath1
|
|
|
|
s.copyInfo = True
|
|
|
|
s.location = dict(weight=0)
|
|
|
|
s.familyName = "MasterFamilyName"
|
|
|
|
s.styleName = "MasterStyleNameOne"
|
|
|
|
doc.addSource(s)
|
|
|
|
doc.write(testDocPath2)
|
|
|
|
verify = DesignSpaceDocument()
|
|
|
|
verify.read(testDocPath2)
|
|
|
|
assert verify.sources[0].filename == "masters/masterTest1.ufo"
|
|
|
|
assert verify.sources[0].path == posix(masterPath1)
|
|
|
|
|
|
|
|
# Case 3: the filename is set, the path is None.
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
s = SourceDescriptor()
|
|
|
|
s.filename = "../somewhere/over/the/rainbow.ufo"
|
|
|
|
s.path = None
|
|
|
|
s.copyInfo = True
|
|
|
|
s.location = dict(weight=0)
|
|
|
|
s.familyName = "MasterFamilyName"
|
|
|
|
s.styleName = "MasterStyleNameOne"
|
|
|
|
doc.addSource(s)
|
|
|
|
doc.write(testDocPath3)
|
|
|
|
verify = DesignSpaceDocument()
|
|
|
|
verify.read(testDocPath3)
|
|
|
|
assert verify.sources[0].filename == "../somewhere/over/the/rainbow.ufo"
|
|
|
|
# make the absolute path for filename so we can see if it matches the path
|
|
|
|
p = os.path.abspath(os.path.join(os.path.dirname(testDocPath3), verify.sources[0].filename))
|
|
|
|
assert verify.sources[0].path == posix(p)
|
|
|
|
|
|
|
|
# Case 4: the filename points to one file, the path points to another. The path takes precedence.
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
s = SourceDescriptor()
|
|
|
|
s.filename = "../somewhere/over/the/rainbow.ufo"
|
|
|
|
s.path = masterPath1
|
|
|
|
s.copyInfo = True
|
|
|
|
s.location = dict(weight=0)
|
|
|
|
s.familyName = "MasterFamilyName"
|
|
|
|
s.styleName = "MasterStyleNameOne"
|
|
|
|
doc.addSource(s)
|
|
|
|
doc.write(testDocPath4)
|
|
|
|
verify = DesignSpaceDocument()
|
|
|
|
verify.read(testDocPath4)
|
|
|
|
assert verify.sources[0].filename == "masters/masterTest1.ufo"
|
|
|
|
|
|
|
|
# Case 5: the filename is None, path has a value, update the filename
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
s = SourceDescriptor()
|
|
|
|
s.filename = None
|
|
|
|
s.path = masterPath1
|
|
|
|
s.copyInfo = True
|
|
|
|
s.location = dict(weight=0)
|
|
|
|
s.familyName = "MasterFamilyName"
|
|
|
|
s.styleName = "MasterStyleNameOne"
|
|
|
|
doc.addSource(s)
|
|
|
|
doc.write(testDocPath5) # so that the document has a path
|
|
|
|
doc.updateFilenameFromPath()
|
|
|
|
assert doc.sources[0].filename == "masters/masterTest1.ufo"
|
|
|
|
|
|
|
|
# Case 6: the filename has a value, path has a value, update the filenames with force
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
s = SourceDescriptor()
|
|
|
|
s.filename = "../somewhere/over/the/rainbow.ufo"
|
|
|
|
s.path = masterPath1
|
|
|
|
s.copyInfo = True
|
|
|
|
s.location = dict(weight=0)
|
|
|
|
s.familyName = "MasterFamilyName"
|
|
|
|
s.styleName = "MasterStyleNameOne"
|
|
|
|
doc.write(testDocPath5) # so that the document has a path
|
|
|
|
doc.addSource(s)
|
|
|
|
assert doc.sources[0].filename == "../somewhere/over/the/rainbow.ufo"
|
|
|
|
doc.updateFilenameFromPath(force=True)
|
|
|
|
assert doc.sources[0].filename == "masters/masterTest1.ufo"
|
|
|
|
|
|
|
|
|
|
|
|
def test_normalise():
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# write some axes
|
|
|
|
a1 = AxisDescriptor()
|
|
|
|
a1.minimum = -1000
|
|
|
|
a1.maximum = 1000
|
|
|
|
a1.default = 0
|
|
|
|
a1.name = "aaa"
|
|
|
|
a1.tag = "aaaa"
|
|
|
|
doc.addAxis(a1)
|
|
|
|
|
|
|
|
assert doc.normalizeLocation(dict(aaa=0)) == {'aaa': 0.0}
|
|
|
|
assert doc.normalizeLocation(dict(aaa=1000)) == {'aaa': 1.0}
|
|
|
|
|
|
|
|
# clipping beyond max values:
|
|
|
|
assert doc.normalizeLocation(dict(aaa=1001)) == {'aaa': 1.0}
|
|
|
|
assert doc.normalizeLocation(dict(aaa=500)) == {'aaa': 0.5}
|
|
|
|
assert doc.normalizeLocation(dict(aaa=-1000)) == {'aaa': -1.0}
|
|
|
|
assert doc.normalizeLocation(dict(aaa=-1001)) == {'aaa': -1.0}
|
|
|
|
# anisotropic coordinates normalise to isotropic
|
|
|
|
assert doc.normalizeLocation(dict(aaa=(1000, -1000))) == {'aaa': 1.0}
|
|
|
|
doc.normalize()
|
|
|
|
r = []
|
|
|
|
for axis in doc.axes:
|
|
|
|
r.append((axis.name, axis.minimum, axis.default, axis.maximum))
|
|
|
|
r.sort()
|
|
|
|
assert r == [('aaa', -1.0, 0.0, 1.0)]
|
|
|
|
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# write some axes
|
|
|
|
a2 = AxisDescriptor()
|
|
|
|
a2.minimum = 100
|
|
|
|
a2.maximum = 1000
|
|
|
|
a2.default = 100
|
|
|
|
a2.name = "bbb"
|
|
|
|
doc.addAxis(a2)
|
|
|
|
assert doc.normalizeLocation(dict(bbb=0)) == {'bbb': 0.0}
|
|
|
|
assert doc.normalizeLocation(dict(bbb=1000)) == {'bbb': 1.0}
|
|
|
|
# clipping beyond max values:
|
|
|
|
assert doc.normalizeLocation(dict(bbb=1001)) == {'bbb': 1.0}
|
|
|
|
assert doc.normalizeLocation(dict(bbb=500)) == {'bbb': 0.4444444444444444}
|
|
|
|
assert doc.normalizeLocation(dict(bbb=-1000)) == {'bbb': 0.0}
|
|
|
|
assert doc.normalizeLocation(dict(bbb=-1001)) == {'bbb': 0.0}
|
|
|
|
# anisotropic coordinates normalise to isotropic
|
|
|
|
assert doc.normalizeLocation(dict(bbb=(1000,-1000))) == {'bbb': 1.0}
|
|
|
|
assert doc.normalizeLocation(dict(bbb=1001)) == {'bbb': 1.0}
|
|
|
|
doc.normalize()
|
|
|
|
r = []
|
|
|
|
for axis in doc.axes:
|
|
|
|
r.append((axis.name, axis.minimum, axis.default, axis.maximum))
|
|
|
|
r.sort()
|
|
|
|
assert r == [('bbb', 0.0, 0.0, 1.0)]
|
|
|
|
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# write some axes
|
|
|
|
a3 = AxisDescriptor()
|
|
|
|
a3.minimum = -1000
|
|
|
|
a3.maximum = 0
|
|
|
|
a3.default = 0
|
|
|
|
a3.name = "ccc"
|
|
|
|
doc.addAxis(a3)
|
|
|
|
assert doc.normalizeLocation(dict(ccc=0)) == {'ccc': 0.0}
|
|
|
|
assert doc.normalizeLocation(dict(ccc=1)) == {'ccc': 0.0}
|
|
|
|
assert doc.normalizeLocation(dict(ccc=-1000)) == {'ccc': -1.0}
|
|
|
|
assert doc.normalizeLocation(dict(ccc=-1001)) == {'ccc': -1.0}
|
|
|
|
|
|
|
|
doc.normalize()
|
|
|
|
r = []
|
|
|
|
for axis in doc.axes:
|
|
|
|
r.append((axis.name, axis.minimum, axis.default, axis.maximum))
|
|
|
|
r.sort()
|
|
|
|
assert r == [('ccc', -1.0, 0.0, 0.0)]
|
|
|
|
|
|
|
|
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# write some axes
|
|
|
|
a3 = AxisDescriptor()
|
|
|
|
a3.minimum = 2000
|
|
|
|
a3.maximum = 3000
|
|
|
|
a3.default = 2000
|
|
|
|
a3.name = "ccc"
|
|
|
|
doc.addAxis(a3)
|
|
|
|
assert doc.normalizeLocation(dict(ccc=0)) == {'ccc': 0.0}
|
|
|
|
assert doc.normalizeLocation(dict(ccc=1)) == {'ccc': 0.0}
|
|
|
|
assert doc.normalizeLocation(dict(ccc=-1000)) == {'ccc': 0.0}
|
|
|
|
assert doc.normalizeLocation(dict(ccc=-1001)) == {'ccc': 0.0}
|
|
|
|
|
|
|
|
doc.normalize()
|
|
|
|
r = []
|
|
|
|
for axis in doc.axes:
|
|
|
|
r.append((axis.name, axis.minimum, axis.default, axis.maximum))
|
|
|
|
r.sort()
|
|
|
|
assert r == [('ccc', 0.0, 0.0, 1.0)]
|
|
|
|
|
|
|
|
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# write some axes
|
|
|
|
a4 = AxisDescriptor()
|
|
|
|
a4.minimum = 0
|
|
|
|
a4.maximum = 1000
|
|
|
|
a4.default = 0
|
|
|
|
a4.name = "ddd"
|
|
|
|
a4.map = [(0,100), (300, 500), (600, 500), (1000,900)]
|
|
|
|
doc.addAxis(a4)
|
|
|
|
doc.normalize()
|
|
|
|
r = []
|
|
|
|
for axis in doc.axes:
|
|
|
|
r.append((axis.name, axis.map))
|
|
|
|
r.sort()
|
|
|
|
assert r == [('ddd', [(0, 0.1), (300, 0.5), (600, 0.5), (1000, 0.9)])]
|
|
|
|
|
|
|
|
|
|
|
|
def test_rules(tmpdir):
|
|
|
|
tmpdir = str(tmpdir)
|
|
|
|
testDocPath = os.path.join(tmpdir, "testRules.designspace")
|
|
|
|
testDocPath2 = os.path.join(tmpdir, "testRules_roundtrip.designspace")
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# write some axes
|
|
|
|
a1 = AxisDescriptor()
|
|
|
|
a1.tag = "taga"
|
|
|
|
a1.name = "aaaa"
|
|
|
|
a1.minimum = 0
|
|
|
|
a1.maximum = 1000
|
|
|
|
a1.default = 0
|
|
|
|
doc.addAxis(a1)
|
|
|
|
a2 = AxisDescriptor()
|
|
|
|
a2.tag = "tagb"
|
|
|
|
a2.name = "bbbb"
|
|
|
|
a2.minimum = 0
|
|
|
|
a2.maximum = 3000
|
|
|
|
a2.default = 0
|
|
|
|
doc.addAxis(a2)
|
|
|
|
|
|
|
|
r1 = RuleDescriptor()
|
|
|
|
r1.name = "named.rule.1"
|
|
|
|
r1.conditions.append(dict(name='aaaa', minimum=0, maximum=1000))
|
|
|
|
r1.conditions.append(dict(name='bbbb', minimum=0, maximum=3000))
|
|
|
|
r1.subs.append(("a", "a.alt"))
|
|
|
|
|
|
|
|
# rule with minium and maximum
|
|
|
|
doc.addRule(r1)
|
|
|
|
assert len(doc.rules) == 1
|
|
|
|
assert len(doc.rules[0].conditions) == 2
|
|
|
|
assert evaluateRule(r1, dict(aaaa = 500, bbbb = 0)) == True
|
|
|
|
assert evaluateRule(r1, dict(aaaa = 0, bbbb = 0)) == True
|
|
|
|
assert evaluateRule(r1, dict(aaaa = 1000, bbbb = 0)) == True
|
|
|
|
assert evaluateRule(r1, dict(aaaa = 1000, bbbb = -100)) == False
|
|
|
|
assert evaluateRule(r1, dict(aaaa = 1000.0001, bbbb = 0)) == False
|
|
|
|
assert evaluateRule(r1, dict(aaaa = -0.0001, bbbb = 0)) == False
|
|
|
|
assert evaluateRule(r1, dict(aaaa = -100, bbbb = 0)) == False
|
|
|
|
assert processRules([r1], dict(aaaa = 500), ["a", "b", "c"]) == ['a.alt', 'b', 'c']
|
|
|
|
assert processRules([r1], dict(aaaa = 500), ["a.alt", "b", "c"]) == ['a.alt', 'b', 'c']
|
|
|
|
assert processRules([r1], dict(aaaa = 2000), ["a", "b", "c"]) == ['a', 'b', 'c']
|
|
|
|
|
|
|
|
# rule with only a maximum
|
|
|
|
r2 = RuleDescriptor()
|
|
|
|
r2.name = "named.rule.2"
|
|
|
|
r2.conditions.append(dict(name='aaaa', maximum=500))
|
|
|
|
r2.subs.append(("b", "b.alt"))
|
|
|
|
|
|
|
|
assert evaluateRule(r2, dict(aaaa = 0)) == True
|
|
|
|
assert evaluateRule(r2, dict(aaaa = -500)) == True
|
|
|
|
assert evaluateRule(r2, dict(aaaa = 1000)) == False
|
|
|
|
|
|
|
|
# rule with only a minimum
|
|
|
|
r3 = RuleDescriptor()
|
|
|
|
r3.name = "named.rule.3"
|
|
|
|
r3.conditions.append(dict(name='aaaa', minimum=500))
|
|
|
|
r3.subs.append(("c", "c.alt"))
|
|
|
|
|
|
|
|
assert evaluateRule(r3, dict(aaaa = 0)) == False
|
|
|
|
assert evaluateRule(r3, dict(aaaa = 1000)) == True
|
|
|
|
assert evaluateRule(r3, dict(bbbb = 1000)) == True
|
|
|
|
|
|
|
|
# rule with only a minimum, maximum in separate conditions
|
|
|
|
r4 = RuleDescriptor()
|
|
|
|
r4.name = "named.rule.4"
|
|
|
|
r4.conditions.append(dict(name='aaaa', minimum=500))
|
|
|
|
r4.conditions.append(dict(name='bbbb', maximum=500))
|
|
|
|
r4.subs.append(("c", "c.alt"))
|
|
|
|
|
|
|
|
assert evaluateRule(r4, dict()) == True # is this what we expect though?
|
|
|
|
assert evaluateRule(r4, dict(aaaa = 1000, bbbb = 0)) == True
|
|
|
|
assert evaluateRule(r4, dict(aaaa = 0, bbbb = 0)) == False
|
|
|
|
assert evaluateRule(r4, dict(aaaa = 1000, bbbb = 1000)) == False
|
|
|
|
|
|
|
|
a1 = AxisDescriptor()
|
|
|
|
a1.minimum = 0
|
|
|
|
a1.maximum = 1000
|
|
|
|
a1.default = 0
|
|
|
|
a1.name = "aaaa"
|
|
|
|
a1.tag = "aaaa"
|
|
|
|
b1 = AxisDescriptor()
|
|
|
|
b1.minimum = 2000
|
|
|
|
b1.maximum = 3000
|
|
|
|
b1.default = 2000
|
|
|
|
b1.name = "bbbb"
|
|
|
|
b1.tag = "bbbb"
|
|
|
|
doc.addAxis(a1)
|
|
|
|
doc.addAxis(b1)
|
|
|
|
assert doc._prepAxesForBender() == {'aaaa': {'map': [], 'name': 'aaaa', 'default': 0, 'minimum': 0, 'maximum': 1000, 'tag': 'aaaa'}, 'bbbb': {'map': [], 'name': 'bbbb', 'default': 2000, 'minimum': 2000, 'maximum': 3000, 'tag': 'bbbb'}}
|
|
|
|
|
|
|
|
assert doc.rules[0].conditions == [{'minimum': 0, 'maximum': 1000, 'name': 'aaaa'}, {'minimum': 0, 'maximum': 3000, 'name': 'bbbb'}]
|
|
|
|
|
|
|
|
assert doc.rules[0].subs == [('a', 'a.alt')]
|
|
|
|
|
|
|
|
doc.normalize()
|
|
|
|
assert doc.rules[0].name == 'named.rule.1'
|
|
|
|
assert doc.rules[0].conditions == [{'minimum': 0.0, 'maximum': 1.0, 'name': 'aaaa'}, {'minimum': 0.0, 'maximum': 1.0, 'name': 'bbbb'}]
|
|
|
|
|
|
|
|
doc.write(testDocPath)
|
|
|
|
new = DesignSpaceDocument()
|
|
|
|
|
|
|
|
new.read(testDocPath)
|
|
|
|
assert len(new.axes) == 4
|
|
|
|
assert len(new.rules) == 1
|
|
|
|
new.write(testDocPath2)
|
|
|
|
|
|
|
|
|
|
|
|
def __removeAxesFromDesignSpace(path):
|
|
|
|
# only for testing, so we can make an invalid designspace file
|
|
|
|
# without making the designSpaceDocument also support it.
|
|
|
|
f = open(path, 'r', encoding='utf-8')
|
|
|
|
d = f.read()
|
|
|
|
f.close()
|
|
|
|
start = d.find("<axes>")
|
|
|
|
end = d.find("</axes>")+len("</axes>")
|
|
|
|
n = d[0:start] + d[end:]
|
|
|
|
f = open(path, 'w', encoding='utf-8')
|
|
|
|
f.write(n)
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def invalid_designspace():
|
|
|
|
p = "testCheck.designspace"
|
|
|
|
__removeAxesFromDesignSpace(p)
|
|
|
|
yield p
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.xfail(reason="The check method requires MutatorMath")
|
|
|
|
def test_check(invalid_designspace, tmpdir):
|
|
|
|
tmpdir = str(tmpdir)
|
|
|
|
# check if the checks are checking
|
|
|
|
testDocPath = os.path.join(tmpdir, invalid_designspace)
|
|
|
|
masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
|
|
|
|
masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
|
|
|
|
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
|
|
|
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
|
|
|
|
|
|
|
# no default selected
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# add master 1
|
|
|
|
s1 = SourceDescriptor()
|
|
|
|
s1.path = masterPath1
|
|
|
|
s1.name = "master.ufo1"
|
|
|
|
s1.location = dict(snap=0, pop=10)
|
|
|
|
s1.familyName = "MasterFamilyName"
|
|
|
|
s1.styleName = "MasterStyleNameOne"
|
|
|
|
doc.addSource(s1)
|
|
|
|
# add master 2
|
|
|
|
s2 = SourceDescriptor()
|
|
|
|
s2.path = masterPath2
|
|
|
|
s2.name = "master.ufo2"
|
|
|
|
s2.location = dict(snap=1000, pop=20)
|
|
|
|
s2.familyName = "MasterFamilyName"
|
|
|
|
s2.styleName = "MasterStyleNameTwo"
|
|
|
|
doc.addSource(s2)
|
|
|
|
doc.checkAxes()
|
|
|
|
doc.getAxisOrder() == ['snap', 'pop']
|
|
|
|
assert doc.default == None
|
|
|
|
doc.checkDefault()
|
|
|
|
assert doc.default.name == 'master.ufo1'
|
|
|
|
|
|
|
|
# default selected
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# add master 1
|
|
|
|
s1 = SourceDescriptor()
|
|
|
|
s1.path = masterPath1
|
|
|
|
s1.name = "master.ufo1"
|
|
|
|
s1.location = dict(snap=0, pop=10)
|
|
|
|
s1.familyName = "MasterFamilyName"
|
|
|
|
s1.styleName = "MasterStyleNameOne"
|
|
|
|
doc.addSource(s1)
|
|
|
|
# add master 2
|
|
|
|
s2 = SourceDescriptor()
|
|
|
|
s2.path = masterPath2
|
|
|
|
s2.name = "master.ufo2"
|
|
|
|
s2.copyInfo = True
|
|
|
|
s2.location = dict(snap=1000, pop=20)
|
|
|
|
s2.familyName = "MasterFamilyName"
|
|
|
|
s2.styleName = "MasterStyleNameTwo"
|
|
|
|
doc.addSource(s2)
|
|
|
|
doc.checkAxes()
|
|
|
|
assert doc.getAxisOrder() == ['snap', 'pop']
|
|
|
|
assert doc.default == None
|
|
|
|
doc.checkDefault()
|
|
|
|
assert doc.default.name == 'master.ufo2'
|
|
|
|
|
|
|
|
# generate a doc without axes, save and read again
|
|
|
|
doc = DesignSpaceDocument()
|
|
|
|
# add master 1
|
|
|
|
s1 = SourceDescriptor()
|
|
|
|
s1.path = masterPath1
|
|
|
|
s1.name = "master.ufo1"
|
|
|
|
s1.location = dict(snap=0, pop=10)
|
|
|
|
s1.familyName = "MasterFamilyName"
|
|
|
|
s1.styleName = "MasterStyleNameOne"
|
|
|
|
doc.addSource(s1)
|
|
|
|
# add master 2
|
|
|
|
s2 = SourceDescriptor()
|
|
|
|
s2.path = masterPath2
|
|
|
|
s2.name = "master.ufo2"
|
|
|
|
s2.location = dict(snap=1000, pop=20)
|
|
|
|
s2.familyName = "MasterFamilyName"
|
|
|
|
s2.styleName = "MasterStyleNameTwo"
|
|
|
|
doc.addSource(s2)
|
|
|
|
doc.checkAxes()
|
|
|
|
doc.write(testDocPath)
|
|
|
|
__removeAxesFromDesignSpace(testDocPath)
|
|
|
|
|
|
|
|
new = DesignSpaceDocument()
|
|
|
|
new.read(testDocPath)
|
|
|
|
assert len(new.axes) == 2
|
|
|
|
new.checkAxes()
|
|
|
|
assert len(new.axes) == 2
|
|
|
|
assert print([a.name for a in new.axes]) == ['snap', 'pop']
|
|
|
|
new.write(testDocPath)
|