def test_rulesConditions(tmpdir): # tests of rules, conditionsets and conditions r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=0, maximum=1000), dict(name='axisName_b', minimum=0, maximum=3000) ]) r1.subs.append(("a", "a.alt")) assert evaluateRule(r1, dict(axisName_a=500, axisName_b=0)) == True assert evaluateRule(r1, dict(axisName_a=0, axisName_b=0)) == True assert evaluateRule(r1, dict(axisName_a=1000, axisName_b=0)) == True assert evaluateRule(r1, dict(axisName_a=1000, axisName_b=-100)) == False assert evaluateRule(r1, dict(axisName_a=1000.0001, axisName_b=0)) == False assert evaluateRule(r1, dict(axisName_a=-0.0001, axisName_b=0)) == False assert evaluateRule(r1, dict(axisName_a=-100, axisName_b=0)) == False assert processRules([r1], dict(axisName_a=500, axisName_b=0), ["a", "b", "c"]) == ['a.alt', 'b', 'c'] assert processRules([r1], dict(axisName_a=500, axisName_b=0), ["a.alt", "b", "c"]) == ['a.alt', 'b', 'c'] assert processRules([r1], dict(axisName_a=2000, axisName_b=0), ["a", "b", "c"]) == ['a', 'b', 'c'] # rule with only a maximum r2 = RuleDescriptor() r2.name = "named.rule.2" r2.conditionSets.append([dict(name='axisName_a', maximum=500)]) r2.subs.append(("b", "b.alt")) assert evaluateRule(r2, dict(axisName_a=0)) == True assert evaluateRule(r2, dict(axisName_a=-500)) == True assert evaluateRule(r2, dict(axisName_a=1000)) == False # rule with only a minimum r3 = RuleDescriptor() r3.name = "named.rule.3" r3.conditionSets.append([dict(name='axisName_a', minimum=500)]) r3.subs.append(("c", "c.alt")) assert evaluateRule(r3, dict(axisName_a=0)) == False assert evaluateRule(r3, dict(axisName_a=1000)) == True assert evaluateRule(r3, dict(axisName_a=1000)) == True # rule with only a minimum, maximum in separate conditions r4 = RuleDescriptor() r4.name = "named.rule.4" r4.conditionSets.append([ dict(name='axisName_a', minimum=500), dict(name='axisName_b', maximum=500) ]) r4.subs.append(("c", "c.alt")) assert evaluateRule(r4, dict(axisName_a=1000, axisName_b=0)) == True assert evaluateRule(r4, dict(axisName_a=0, axisName_b=0)) == False assert evaluateRule(r4, dict(axisName_a=1000, axisName_b=1000)) == False
def test_rulesConditions(tmpdir): # tests of rules, conditionsets and conditions r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=0, maximum=1000), dict(name='axisName_b', minimum=0, maximum=3000) ]) r1.subs.append(("a", "a.alt")) assert evaluateRule(r1, dict(axisName_a = 500, axisName_b = 0)) == True assert evaluateRule(r1, dict(axisName_a = 0, axisName_b = 0)) == True assert evaluateRule(r1, dict(axisName_a = 1000, axisName_b = 0)) == True assert evaluateRule(r1, dict(axisName_a = 1000, axisName_b = -100)) == False assert evaluateRule(r1, dict(axisName_a = 1000.0001, axisName_b = 0)) == False assert evaluateRule(r1, dict(axisName_a = -0.0001, axisName_b = 0)) == False assert evaluateRule(r1, dict(axisName_a = -100, axisName_b = 0)) == False assert processRules([r1], dict(axisName_a = 500, axisName_b = 0), ["a", "b", "c"]) == ['a.alt', 'b', 'c'] assert processRules([r1], dict(axisName_a = 500, axisName_b = 0), ["a.alt", "b", "c"]) == ['a.alt', 'b', 'c'] assert processRules([r1], dict(axisName_a = 2000, axisName_b = 0), ["a", "b", "c"]) == ['a', 'b', 'c'] # rule with only a maximum r2 = RuleDescriptor() r2.name = "named.rule.2" r2.conditionSets.append([dict(name='axisName_a', maximum=500)]) r2.subs.append(("b", "b.alt")) assert evaluateRule(r2, dict(axisName_a = 0)) == True assert evaluateRule(r2, dict(axisName_a = -500)) == True assert evaluateRule(r2, dict(axisName_a = 1000)) == False # rule with only a minimum r3 = RuleDescriptor() r3.name = "named.rule.3" r3.conditionSets.append([dict(name='axisName_a', minimum=500)]) r3.subs.append(("c", "c.alt")) assert evaluateRule(r3, dict(axisName_a = 0)) == False assert evaluateRule(r3, dict(axisName_a = 1000)) == True assert evaluateRule(r3, dict(axisName_a = 1000)) == True # rule with only a minimum, maximum in separate conditions r4 = RuleDescriptor() r4.name = "named.rule.4" r4.conditionSets.append([ dict(name='axisName_a', minimum=500), dict(name='axisName_b', maximum=500) ]) r4.subs.append(("c", "c.alt")) assert evaluateRule(r4, dict(axisName_a = 1000, axisName_b = 0)) == True assert evaluateRule(r4, dict(axisName_a = 0, axisName_b = 0)) == False assert evaluateRule(r4, dict(axisName_a = 1000, axisName_b = 1000)) == False
def test_rulesDocument(tmpdir): # tests of rules in a document, roundtripping. tmpdir = str(tmpdir) testDocPath = os.path.join(tmpdir, "testRules.designspace") testDocPath2 = os.path.join(tmpdir, "testRules_roundtrip.designspace") doc = DesignSpaceDocument() a1 = AxisDescriptor() a1.minimum = 0 a1.maximum = 1000 a1.default = 0 a1.name = "axisName_a" a1.tag = "TAGA" b1 = AxisDescriptor() b1.minimum = 2000 b1.maximum = 3000 b1.default = 2000 b1.name = "axisName_b" b1.tag = "TAGB" doc.addAxis(a1) doc.addAxis(b1) r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=0, maximum=1000), dict(name='axisName_b', 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].conditionSets) == 1 assert len(doc.rules[0].conditionSets[0]) == 2 assert _axesAsDict(doc.axes) == {'axisName_a': {'map': [], 'name': 'axisName_a', 'default': 0, 'minimum': 0, 'maximum': 1000, 'tag': 'TAGA'}, 'axisName_b': {'map': [], 'name': 'axisName_b', 'default': 2000, 'minimum': 2000, 'maximum': 3000, 'tag': 'TAGB'}} assert doc.rules[0].conditionSets == [[ {'minimum': 0, 'maximum': 1000, 'name': 'axisName_a'}, {'minimum': 0, 'maximum': 3000, 'name': 'axisName_b'}]] assert doc.rules[0].subs == [('a', 'a.alt')] doc.normalize() assert doc.rules[0].name == 'named.rule.1' assert doc.rules[0].conditionSets == [[ {'minimum': 0.0, 'maximum': 1.0, 'name': 'axisName_a'}, {'minimum': 0.0, 'maximum': 1.0, 'name': 'axisName_b'}]] # still one conditionset assert len(doc.rules[0].conditionSets) == 1 doc.write(testDocPath) # add a stray conditionset _addUnwrappedCondition(testDocPath) doc2 = DesignSpaceDocument() doc2.read(testDocPath) assert len(doc2.axes) == 2 assert len(doc2.rules) == 1 assert len(doc2.rules[0].conditionSets) == 2 doc2.write(testDocPath2) # verify these results # make sure the stray condition is now neatly wrapped in a conditionset. doc3 = DesignSpaceDocument() doc3.read(testDocPath2) assert len(doc3.rules) == 1 assert len(doc3.rules[0].conditionSets) == 2
def applyConditionsToRules(doc, condition_list, replacement_list): rules = [] for i, condition in enumerate(condition_list): r = RuleDescriptor() r.name = "Rule %s" % str(i + 1) r.conditionSets.append(condition) for sub in replacement_list[i]: r.subs.append(sub) rules.append(r) doc.rules = rules
def test_incompleteRule(tmpdir): tmpdir = str(tmpdir) testDocPath1 = os.path.join(tmpdir, "testIncompleteRule.designspace") doc = DesignSpaceDocument() r1 = RuleDescriptor() r1.name = "incomplete.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=100), dict(name='axisName_b', maximum=200) ]) r1.subs.append(("c", "c.alt")) doc.addRule(r1) doc.write(testDocPath1) __removeConditionMinimumMaximumDesignSpace(testDocPath1) new = DesignSpaceDocument() with pytest.raises(DesignSpaceDocumentError) as excinfo: new.read(testDocPath1) assert "No minimum or maximum defined in rule" in str(excinfo.value)
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() # 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 = 15 a2.name = "width" a2.tag = "wdth" a2.map = [(0.0, 10.0), (15.0, 20.0), (401.0, 66.0), (1000.0, 990.0)] a2.hidden = True a2.labelNames[u'fr'] = u"Chasse" doc.addAxis(a2) # add master 1 s1 = SourceDescriptor() s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath)) assert s1.font is None 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 master 3 from a different layer s3 = SourceDescriptor() s3.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s3.name = "master.ufo2" s3.copyLib = False s3.copyInfo = False s3.copyFeatures = False s3.muteKerning = False s3.layerName = "supports" s3.location = dict(weight=1000) s3.familyName = "MasterFamilyName" s3.styleName = "Supports" doc.addSource(s3) # 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 i1.lib['com.coolDesignspaceApp.binaryData'] = plistlib.Data(b'<binary gunk>') i1.lib['com.coolDesignspaceApp.specimenText'] = "Hamburgerwhatever" 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) doc.filename = "suggestedFileName.designspace" doc.lib['com.coolDesignspaceApp.previewSize'] = 30 # write some rules r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=0, maximum=1), dict(name='axisName_b', minimum=2, maximum=3) ]) r1.subs.append(("a", "a.alt")) doc.addRule(r1) # write the document doc.write(testDocPath) assert os.path.exists(testDocPath) assert_equals_test_file(testDocPath, 'data/test.designspace') # import it again new = DesignSpaceDocument() new.read(testDocPath) assert new.default.location == {'width': 20.0, 'weight': 0.0} assert new.filename == 'test.designspace' assert new.lib == doc.lib assert new.instances[0].lib == doc.instances[0].lib # 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_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.conditionSets.append([ dict(name='weight', minimum=200, maximum=500), dict(name='width', minimum=0, maximum=150) ]) 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) with open(testDocPath, 'r', encoding='utf-8') as f1: t1 = f1.read() with open(testDocPath2, 'r', encoding='utf-8') as f2: t2 = f2.read() assert t1 == t2
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 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() # 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']) 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_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() # 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"Chasse" doc.addAxis(a2) # add master 1 s1 = SourceDescriptor() s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath)) assert s1.font is None 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 master 3 from a different layer s3 = SourceDescriptor() s3.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s3.name = "master.ufo2" s3.copyLib = False s3.copyInfo = False s3.copyFeatures = False s3.muteKerning = False s3.layerName = "supports" s3.location = dict(weight=1000) s3.familyName = "MasterFamilyName" s3.styleName = "Supports" doc.addSource(s3) # 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 i1.lib['com.coolDesignspaceApp.binaryData'] = plistlib.Data(b'<binary gunk>') i1.lib['com.coolDesignspaceApp.specimenText'] = "Hamburgerwhatever" 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) doc.filename = "suggestedFileName.designspace" doc.lib['com.coolDesignspaceApp.previewSize'] = 30 # write some rules r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=0, maximum=1), dict(name='axisName_b', minimum=2, maximum=3) ]) r1.subs.append(("a", "a.alt")) doc.addRule(r1) # write the document doc.write(testDocPath) assert os.path.exists(testDocPath) assert_equals_test_file(testDocPath, 'data/test.designspace') # import it again new = DesignSpaceDocument() new.read(testDocPath) assert new.default.location == {'width': 20.0, 'weight': 0.0} assert new.filename == 'test.designspace' assert new.lib == doc.lib assert new.instances[0].lib == doc.instances[0].lib # 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
fontmake.__main__.main( ["-m", str(minPath), "-o", "ufo", "-i", "--verbose", "WARNING"]) print() print("Resetting and processing rules") doc.rules = [] firstMaster = doc.sources[0] font = OpenFont(firstMaster.path) for glyph in font: if ".rl" in glyph.name: r = parseRule(glyph.name) # create rule rule = RuleDescriptor() rule.name = r['target'] # add conditions for condition in r['conditions']: rule.conditionSets.append([ dict(name=condition[0], minimum=float(condition[1]), maximum=float(condition[2])) ]) # add replacement rule.subs.append((r['source'], r['target'])) doc.addRule(rule) print(" - Adding rule for %s -> %s" % (r['source'], r['target']))
i0 = InstanceDescriptor() i0.name = 'instance_LightCondensed' i0.familyName = familyName i0.styleName = "Medium" i0.path = os.path.join(root, "instances", "MutatorSansTest-Medium.ufo") i0.location = dict(weight=500, width=327) i0.kerning = True i0.info = True doc.addInstance(i0) #------- # rules #------- rd = RuleDescriptor() rd.name = 'fold_I_serifs' rd.conditionSets = [[{'minimum': 0.0, 'maximum': 328.0, 'name': 'width'}]] rd.subs = [('I', 'I.narrow')] doc.addRule(rd) rd = RuleDescriptor() rd.name = 'fold_S_terminals' rd.conditionSets = [[{ 'minimum': 0.0, 'maximum': 1000.0, 'name': 'width' }, { 'minimum': 0.0, 'maximum': 500.0, 'name': 'weight' }]]
i3 = InstanceDescriptor() i3.name = 'instance_Bold' i3.familyName = familyName i3.styleName = "Bold" i3.path = os.path.join(root, "instances", "NotoSerifTagalog-Bold.ufo") i3.location = dict(weight=700) i3.kerning = True i3.info = True doc.addInstance(i3) #------- # rules #------- r1 = RuleDescriptor() r1.name = "ra_crossing" r1.conditionSets.append( [dict(name="weight", minimum=(300 * .75) + 400, maximum=700)]) r1.subs.append(("uni170D", "uni170D.avar")) doc.addRule(r1) r2 = RuleDescriptor() r2.name = "ya_gap" r2.conditionSets.append( [dict(name="weight", minimum=(300 * .75) + 400, maximum=700)]) r2.subs.append(("uni170C", "uni170C.avar")) doc.addRule(r2) #-------- # saving #--------