From 6d421e08717162b1ecf21be9bb458a535c3cb01e Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 6 Jan 2017 17:37:29 +0100 Subject: [PATCH] Use the axis map when generating ufos. --- Lib/designSpaceDocument/__init__.py | 67 ++++++++++++++++--- Lib/designSpaceDocument/testRules.designspace | 2 + .../testRules_roundtrip.designspace | 2 + Lib/designSpaceDocument/ufoProcessor.py | 17 +++-- 4 files changed, 73 insertions(+), 15 deletions(-) diff --git a/Lib/designSpaceDocument/__init__.py b/Lib/designSpaceDocument/__init__.py index 6176e868a..3eb15768a 100644 --- a/Lib/designSpaceDocument/__init__.py +++ b/Lib/designSpaceDocument/__init__.py @@ -112,7 +112,6 @@ def evaluateRule(rule, location): """ for cd in rule.conditions: if not cd['name'] in location: - #print("skipping", cd['name']) continue if cd.get('minimum') is None: if not location[cd['name']] <= cd['maximum']: @@ -902,6 +901,22 @@ class DesignSpaceDocument(object): self.defaultLoc = self.default.location self.default.copyInfo = True + def _prepAxesForBender(self): + """ + Make the axis data we have available in + """ + benderAxes = {} + for axisDescriptor in self.axes: + d = { + 'name': axisDescriptor.name, + 'tag': axisDescriptor.tag, + 'minimum': axisDescriptor.minimum, + 'maximum': axisDescriptor.maximum, + 'default': axisDescriptor.default, + 'map': axisDescriptor.map, + } + benderAxes[axisDescriptor.name] = d + return benderAxes def checkAxes(self, overwrite=False): """ @@ -1023,6 +1038,23 @@ class DesignSpaceDocument(object): rule.conditions = newConditions +def rulesToFeature(doc, whiteSpace="\t", newLine="\n"): + """ Showing how rules could be expressed as FDK feature text. + Speculative. Experimental. + """ + axisNames = {axis.name: axis.tag for axis in doc.axes} + axisDims = {axis.tag: (axis.minimum, axis.maximum) for axis in doc.axes} + text = [] + for rule in doc.rules: + text.append("rule %s{"%rule.name) + for cd in rule.conditions: + axisTag = axisNames.get(cd.get('name'), "****") + axisMinimum = cd.get('minimum', axisDims.get(axisTag, [0,0])[0]) + axisMaximum = cd.get('maximum', axisDims.get(axisTag, [0,0])[1]) + text.append("%s%s %f %f;"%(whiteSpace, axisTag, axisMinimum, axisMaximum)) + text.append("} %s;"%rule.name) + return newLine.join(text) + if __name__ == "__main__": def __removeAxesFromDesignSpace(path): @@ -1038,12 +1070,6 @@ if __name__ == "__main__": f.write(n) f.close() - # print(tagForAxisName('weight')) - # print(tagForAxisName('width')) - # print(tagForAxisName('Optical')) - # print(tagForAxisName('Poids')) - # print(tagForAxisName('wt')) - def test(): """ >>> import os @@ -1428,6 +1454,21 @@ if __name__ == "__main__": >>> testDocPath2 = os.path.join(os.getcwd(), "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)) @@ -1459,6 +1500,13 @@ if __name__ == "__main__": >>> processRules([r1], dict(aaaa = 2000), ["a", "b", "c"]) ['a', 'b', 'c'] + >>> r = rulesToFeature(doc) + >>> str(r) + 'rule named.rule.1 { + taga 0.000000 1000.000000; + tagb 0.000000 3000.000000; + }named.rule.1;' + >>> # rule with only a maximum >>> r2 = RuleDescriptor() >>> r2.name = "named.rule.2" @@ -1515,6 +1563,9 @@ if __name__ == "__main__": >>> b1.tag = "bbbb" >>> doc.addAxis(a1) >>> doc.addAxis(b1) + >>> 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'}} + >>> doc.rules[0].conditions [{'minimum': 0, 'maximum': 1000, 'name': 'aaaa'}, {'minimum': 0, 'maximum': 3000, 'name': 'bbbb'}] @@ -1533,7 +1584,7 @@ if __name__ == "__main__": >>> new.read(testDocPath) >>> len(new.axes) - 2 + 4 >>> len(new.rules) 1 >>> new.write(testDocPath2) diff --git a/Lib/designSpaceDocument/testRules.designspace b/Lib/designSpaceDocument/testRules.designspace index 0564a1fa3..6670a2643 100644 --- a/Lib/designSpaceDocument/testRules.designspace +++ b/Lib/designSpaceDocument/testRules.designspace @@ -1,6 +1,8 @@ + + diff --git a/Lib/designSpaceDocument/testRules_roundtrip.designspace b/Lib/designSpaceDocument/testRules_roundtrip.designspace index 0564a1fa3..6670a2643 100644 --- a/Lib/designSpaceDocument/testRules_roundtrip.designspace +++ b/Lib/designSpaceDocument/testRules_roundtrip.designspace @@ -1,6 +1,8 @@ + + diff --git a/Lib/designSpaceDocument/ufoProcessor.py b/Lib/designSpaceDocument/ufoProcessor.py index 4bb8c5b3e..572c93b99 100644 --- a/Lib/designSpaceDocument/ufoProcessor.py +++ b/Lib/designSpaceDocument/ufoProcessor.py @@ -23,8 +23,6 @@ from mutatorMath.objects.mutator import buildMutator from mutatorMath.objects.location import biasFromLocations, Location import os -#print("ufoProcessor reloads") - """ Swap the contents of two glyphs. @@ -147,6 +145,7 @@ class DesignSpaceProcessor(DesignSpaceDocument): self._glyphMutators = {} self._infoMutator = None self._kerningMutator = None + self._preppedAxes = None self.fonts = {} self.glyphNames = [] # list of all glyphnames self.processRules = True @@ -154,7 +153,7 @@ class DesignSpaceProcessor(DesignSpaceDocument): def generateUFO(self, processRules=True): # makes the instances # option to execute the rules - self.checkAxes() + #self.checkAxes() self.checkDefault() self.loadFonts() for instanceDescriptor in self.instances: @@ -174,7 +173,7 @@ class DesignSpaceProcessor(DesignSpaceDocument): loc = Location(sourceDescriptor.location) sourceFont = self.fonts[sourceDescriptor.name] infoItems.append((loc, self.mathInfoClass(sourceFont.info))) - bias, self._infoMutator = buildMutator(infoItems, bias=self.defaultLoc) + bias, self._infoMutator = buildMutator(infoItems, axes=self._preppedAxes, bias=self.defaultLoc) return self._infoMutator def getKerningMutator(self): @@ -186,7 +185,7 @@ class DesignSpaceProcessor(DesignSpaceDocument): loc = Location(sourceDescriptor.location) sourceFont = self.fonts[sourceDescriptor.name] kerningItems.append((loc, self.mathKerningClass(sourceFont.kerning, sourceFont.groups))) - bias, self._kerningMutator = buildMutator(kerningItems, bias=self.defaultLoc) + bias, self._kerningMutator = buildMutator(kerningItems, axes=self._preppedAxes, bias=self.defaultLoc) return self._kerningMutator def getGlyphMutator(self, glyphName): @@ -203,7 +202,7 @@ class DesignSpaceProcessor(DesignSpaceDocument): # log this> continue items.append((loc, self.mathGlyphClass(f[glyphName]))) - bias, self._glyphMutators[glyphName] = buildMutator(items, bias=self.defaultLoc) + bias, self._glyphMutators[glyphName] = buildMutator(items, axes=self._preppedAxes, bias=self.defaultLoc) return self._glyphMutators[glyphName] def loadFonts(self): @@ -218,6 +217,7 @@ class DesignSpaceProcessor(DesignSpaceDocument): def makeInstance(self, instanceDescriptor, doRules=False): """ Generate a font object for this instance """ font = self._instantiateFont(None) + self._preppedAxes = self._prepAxesForBender() # make fonty things here loc = Location(instanceDescriptor.location) # make the kerning @@ -300,7 +300,7 @@ class DesignSpaceProcessor(DesignSpaceDocument): sourceGlyph = MathGlyph(m[sourceGlyphName]) sourceGlyphLocation = Location(glyphMaster.get("location")) items.append((sourceGlyphLocation, sourceGlyph)) - bias, glyphMutator = buildMutator(items, bias=self.defaultLoc) + bias, glyphMutator = buildMutator(items, axes=self._preppedAxes, bias=self.defaultLoc) try: glyphInstanceObject = glyphMutator.makeInstance(glyphInstanceLocation) except IndexError: @@ -397,6 +397,9 @@ class DesignSpaceProcessor(DesignSpaceDocument): setattr(targetInfo, infoAttribute, value) + + + if __name__ == "__main__": # standalone test import shutil