def buildDesignSpace(sources, instances, axes): # use DesignSpaceDocument because it supports axis labelNames doc = DesignSpaceDocument() for source in sources: s = SourceDescriptor() s.path = source["path"] s.name = source["name"] s.copyInfo = source["copyInfo"] s.location = source["location"] s.familyName = source["familyName"] s.styleName = source["styleName"] doc.addSource(s) for instance in instances: i = InstanceDescriptor() i.location = instance["location"] i.familyName = instance["familyName"] i.styleName = instance["styleName"] doc.addInstance(i) for axis in axes: a = AxisDescriptor() a.minimum = axis["minimum"] a.maximum = axis["maximum"] a.default = axis["default"] a.name = axis["name"] a.tag = axis["tag"] for languageCode, labelName in axis["labelNames"].items(): a.labelNames[languageCode] = labelName a.map = axis["map"] doc.addAxis(a) return doc
def testDocument(docPath): # make the test fonts and a test document testFontPath = os.path.join(os.getcwd(), "automatic_testfonts") m1, m2, i1, i2, i3 = makeTestFonts(testFontPath) d = DesignSpaceProcessor() a = AxisDescriptor() a.name = "pop" a.minimum = 50 a.maximum = 1000 a.default = 0 a.tag = "pop*" d.addAxis(a) s1 = SourceDescriptor() s1.path = m1 s1.location = dict(pop=a.minimum) s1.name = "test.master.1" s1.copyInfo = True s1.copyFeatures = True s1.copyLib = True d.addSource(s1) s2 = SourceDescriptor() s2.path = m2 s2.location = dict(pop=1000) s2.name = "test.master.2" #s2.copyInfo = True d.addSource(s2) for counter in range(3): factor = counter / 2 i = InstanceDescriptor() v = a.minimum + factor * (a.maximum - a.minimum) i.path = i1 % v i.familyName = "TestFamily" i.styleName = "TestStyle_pop%3.3f" % (v) i.name = "%s-%s" % (i.familyName, i.styleName) i.location = dict(pop=v) i.info = True i.kerning = True if counter == 2: i.glyphs['glyphTwo'] = dict(name="glyphTwo", mute=True) i.copyLib = True if counter == 2: i.glyphs['narrow'] = dict(instanceLocation=dict(pop=400), unicodes=[0x123, 0x124, 0x125]) d.addInstance(i) d.write(docPath)
def __init__(self, font): self.font = font self.designSpaceModel = self.font.lib.get(self.designSpaceModelLibKey, "twobytwo") #if self.designSpaceModel is None: # print("This font is probably not a Responsive Lettering project?") # return if self.designSpaceModel == "twobytwo": self.masterNames = [ 'narrow-thin', 'wide-thin', 'narrow-bold', 'wide-bold' ] self.fontNames = { 'narrow-thin': 'NarrowThin', 'wide-thin': 'WideThin', 'narrow-bold': 'NarrowBold', 'wide-bold': 'WideBold' } self.axes = ['width', 'weight'] self.locations = { 'narrow-thin': dict(weight=0, width=0), 'wide-thin': dict(width=1000, weight=0), 'narrow-bold': dict(width=0, weight=1000), 'wide-bold': dict(width=1000, weight=1000) } elif self.designSpaceModel == "twobyone": self.masterNames = ['narrow-thin', 'wide-thin'] self.fontNames = { 'narrow-thin': 'NarrowThin', 'wide-thin': 'WideThin' } self.axes = ['width'] self.locations = { 'narrow-thin': dict(weight=0), 'wide-thin': dict(weight=1000) } elif self.designSpaceModel == "threebyone": self.masterNames = ['narrow-thin', 'wide-thin', 'medium-thin'] self.fontNames = { 'narrow-thin': 'NarrowThin', 'wide-thin': 'WideThin', 'medium-thin': 'MediumThin' } self.axes = ['width'] self.locations = { 'narrow-thin': dict(weight=0), 'medium-thin': dict(weight=500), 'wide-thin': dict(weight=1000) } projectRoot = os.path.join( os.path.dirname(self.font.path), "%s_variableFont" % self.font.info.styleName) docPath = os.path.join( projectRoot, "%s_variableFont.designspace" % self.font.info.styleName) if not os.path.exists(projectRoot): os.makedirs(projectRoot) widthMinimum = self.font['narrow-thin'].width widthMaximum = self.font['wide-thin'].width for k, v in self.locations.items(): new = {} for axisName, axisValue in v.items(): if axisName == "width": if axisValue == 1000: new[axisName] = widthMaximum elif axisValue == 0: new[axisName] = widthMinimum else: new[axisName] = axisValue self.locations[k] = new doc = DesignSpaceDocument() for name in self.axes: if name == "width": a = AxisDescriptor() a.minimum = widthMinimum a.maximum = widthMaximum a.default = widthMinimum a.name = "width" a.tag = "wdth" #a.labelNames['en'] = "Width" doc.addAxis(a) elif name == "weight": a = AxisDescriptor() a.minimum = 0 a.maximum = 1000 a.default = 0 a.name = "weight" a.tag = "wght" #a.labelNames['en'] = "Weight" doc.addAxis(a) print "projectRoot", projectRoot masterCount = 0 for name in self.masterNames: if name in self.font: masterCount += 1 if masterCount != len(self.masterNames): print "missing glyphs, can't generate" return closers = [] for name in self.masterNames: print "processing", name, self.locations[name] m = RFont() m.info.unitsPerEm = self.font.info.unitsPerEm m.info.ascender = self.font.info.ascender m.info.descender = self.font.info.descender if self.font.info.familyName in ["MathShape", "Responsive"]: m.info.familyName = self.font.info.styleName else: m.info.familyName = "ResponsiveLettering" m.info.styleName = self.fontNames[name] m.info.copyright = "Generated from Responsive Lettering project %s" % ( os.path.basename(self.font.path)) m.info.openTypeNameSampleText = "A" fontPath = os.path.join(projectRoot, "master_%s.ufo" % (m.info.styleName)) instancePath = os.path.join( projectRoot, "instance_%s%s.ufo" % (m.info.familyName, m.info.styleName)) m.save(fontPath) m.newGlyph("A") g = m['A'] pen = g.getPointPen() self.font[name].drawPoints(pen) #g.appendGlyph(self.font[name]) g.width = self.font[name].width g.clearImage() g.update() m.save() m.newGlyph("space") g = m['space'] g.clearImage() g.width = self.font[name].width #g.note = "test" #g.appendGlyph(self.font[name]) m.newGlyph(".notdef") g = m['.notdef'] g.clearImage() g.width = self.font[name].width #g.note = "test" g.update() m.save() s = SourceDescriptor() s.path = fontPath s.location = self.locations[name] if name == 'narrow-thin': s.copyLib = True s.copyInfo = True doc.addSource(s) # add some instances i = InstanceDescriptor() i.path = instancePath i.location = self.locations[name] i.copyLib = True i.copyInfo = True i.copyFeatures = True i.familyName = "ResponsiveLetteringVariable" i.styleName = m.info.styleName #i.kerning = True doc.addInstance(i) closers.append(m) doc.write(docPath) for m in closers: m.save() m.close()
s3 = SourceDescriptor() s3.path = "MutatorSansBoldWide.ufo" s3.name = "master.MutatorMathTest.BoldWide.3" s3.familyName = familyName s3.styleName = "BoldWide" s3.location = dict(weight=1000, width=1000) doc.addSource(s3) #----------- # instances #----------- 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 #------- # TODO: add rules to match the contents of `MutatorSans.designspace` # http://github.com/LettError/mutatorSans/blob/master/MutatorSans.designspace #-------- # saving
for source in sources: s = SourceDescriptor() s.path = source["path"] s.name = source["name"] s.copyInfo = source["copyInfo"] s.location = source["location"] s.familyName = source["familyName"] s.styleName = source["styleName"] doc.addSource(s) for instance in instances: i = InstanceDescriptor() i.location = instance["location"] i.familyName = instance["familyName"] i.styleName = instance["styleName"] doc.addInstance(i) for axis in axes: a = AxisDescriptor() a.minimum = axis["minimum"] a.maximum = axis["maximum"] a.default = axis["default"] a.name = axis["name"] a.tag = axis["tag"] for languageCode, labelName in axis["labelNames"].items(): a.labelNames[languageCode] = labelName a.map = axis["map"] doc.addAxis(a) #doc.checkAxes()