def test__ne__(self): glyph1 = self._setupTestGlyph() glyph2 = MathGlyph(None) glyph2.width = 1 glyph2.name = 'a' self.assertNotEqual(glyph1, glyph2) self.assertNotEqual(glyph1, 'foo')
def test__eq__(self): glyph1 = self._setupTestGlyph() glyph2 = self._setupTestGlyph() self.assertEqual(glyph1, glyph2) glyph2.width = 1 self.assertFalse(glyph1 == glyph2) nonglyph = object() self.assertFalse(glyph1 == nonglyph) glyph1 = MathGlyph(None) glyph1.name = 'space' glyph1.width = 100 class MyGlyph(object): pass other = MyGlyph() other.name = 'space' other.width = 100 other.height = None other.contours = [] other.components = [] other.anchors = [] other.guidelines = [] other.image = { 'fileName': None, 'transformation': (1, 0, 0, 1, 0, 0), 'color': None } other.lib = {} other.unicodes = None other.note = None self.assertEqual(glyph1, other)
def test__eq__(self): glyph1 = self._setupTestGlyph() glyph2 = self._setupTestGlyph() self.assertEqual(glyph1, glyph2) glyph2.width = 1 self.assertFalse(glyph1 == glyph2) nonglyph = object() self.assertFalse(glyph1 == nonglyph) glyph1 = MathGlyph(None) glyph1.name = 'space' glyph1.width = 100 class MyGlyph(object): pass other = MyGlyph() other.name = 'space' other.width = 100 other.height = None other.contours = [] other.components = [] other.anchors = [] other.guidelines = [] other.image = {'fileName': None, 'transformation': (1, 0, 0, 1, 0, 0), 'color': None} other.lib = {} other.unicodes = None other.note = None self.assertEqual(glyph1, other)
def _calculateGlyph(self, targetGlyphObject, instanceLocationObject, glyphMasters): """ Build a Mutator object for this glyph. * name: glyphName * location: Location object * glyphMasters: dict with font objects. """ sources = None items = [] for item in glyphMasters: locationObject = item['location'] fontObject = item['font'] glyphName = item['glyphName'] if not glyphName in fontObject: continue glyphObject = MathGlyph(fontObject[glyphName]) items.append((locationObject, glyphObject)) bias, m = buildMutator(items) instanceObject = m.makeInstance(instanceLocationObject) if self.roundGeometry: try: instanceObject = instanceObject.round() except AttributeError: self.logger.info("MathGlyph object missing round() method.") try: instanceObject.extractGlyph(targetGlyphObject, onlyGeometry=True) except TypeError: self.logger.info( "MathGlyph object extractGlyph() does not support onlyGeometry attribute." ) instanceObject.extractGlyph(targetGlyphObject)
def _calculateGlyph(self, targetGlyphObject, instanceLocationObject, glyphMasters): """ Build a Mutator object for this glyph. * name: glyphName * location: Location object * glyphMasters: dict with font objects. """ sources = None items = [] for item in glyphMasters: locationObject = item['location'] fontObject = item['font'] glyphName = item['glyphName'] if not glyphName in fontObject: continue glyphObject = MathGlyph(fontObject[glyphName]) items.append((locationObject, glyphObject)) bias, m = buildMutator(items) instanceObject = m.makeInstance(instanceLocationObject) if self.roundGeometry: instanceObject = instanceObject.round() instanceObject.extractGlyph(targetGlyphObject, onlyGeometry=True)
def _calculateGlyph(self, targetGlyphObject, instanceLocationObject, glyphMasters): # Search for a glyphMaster with the same location as instanceLocationObject found = False if not calc_glyphs: # i.e. if copying glyphs for item in glyphMasters: locationObject = item['location'] # mutatorMath Location if locationObject.sameAs(instanceLocationObject) == 0: found = True fontObject = item['font'] # defcon Font glyphName = item['glyphName'] # string glyphObject = MathGlyph(fontObject[glyphName]) glyphObject.extractGlyph(targetGlyphObject, onlyGeometry=True) break if not found: # includes case of calc_glyphs == True super(LocalInstanceWriter, self)._calculateGlyph(targetGlyphObject, instanceLocationObject, glyphMasters)
def _calculateGlyph(self, targetGlyphObject, instanceLocationObject, glyphMasters): """ Build a Mutator object for this glyph. * name: glyphName * location: Location object * glyphMasters: dict with font objects. """ sources = None items = [] for item in glyphMasters: locationObject = item['location'] fontObject = item['font'] glyphName = item['glyphName'] if not glyphName in fontObject: continue glyphObject = MathGlyph(fontObject[glyphName]) items.append((locationObject, glyphObject)) bias, m = buildMutator(items, axes=self.axes) instanceObject = m.makeInstance(instanceLocationObject, bend=self.bendLocations) if self.roundGeometry: try: instanceObject = instanceObject.round() except AttributeError: if self.verbose and self.logger: self.logger.info( "MathGlyph object missing round() method.") try: instanceObject.extractGlyph(targetGlyphObject, onlyGeometry=True) except TypeError: # this causes ruled glyphs to end up in the wrong glyphname # but defcon2 objects don't support it pPen = targetGlyphObject.getPointPen() targetGlyphObject.clear() instanceObject.drawPoints(pPen) targetGlyphObject.width = instanceObject.width
def _setupTestGlyph(self): glyph = MathGlyph(None) glyph.width = 0 glyph.height = 0 return glyph
def makeInstance(self, instanceDescriptor, doRules=False, glyphNames=None): """ Generate a font object for this instance """ font = self._instantiateFont(None) self._preppedAxes = self._prepAxesForBender() # make fonty things here loc = Location(instanceDescriptor.location) # groups, if hasattr(self.fonts[self.default.name], "kerningGroupConversionRenameMaps"): renameMap = self.fonts[ self.default.name].kerningGroupConversionRenameMaps self.problems.append("renameMap %s" % renameMap) else: renameMap = {} font.kerningGroupConversionRenameMaps = renameMap # make the kerning if instanceDescriptor.kerning: try: self.getKerningMutator().makeInstance(loc).extractKerning(font) except: self.problems.append("Could not make kerning for %s" % loc) # make the info if instanceDescriptor.info: try: self.getInfoMutator().makeInstance(loc).extractInfo(font.info) info = self._infoMutator.makeInstance(loc) info.extractInfo(font.info) font.info.familyName = instanceDescriptor.familyName font.info.styleName = instanceDescriptor.styleName font.info.postScriptFontName = instanceDescriptor.postScriptFontName font.info.styleMapFamilyName = instanceDescriptor.styleMapFamilyName font.info.styleMapStyleName = instanceDescriptor.styleMapStyleName # localised names need to go to the right openTypeNameRecords # records = [] # nameID = 1 # platformID = # for languageCode, name in instanceDescriptor.localisedStyleMapFamilyName.items(): # # Name ID 1 (font family name) is found at the generic styleMapFamily attribute. # records.append((nameID, )) except: self.problems.append("Could not make fontinfo for %s" % loc) # copied info for sourceDescriptor in self.sources: if sourceDescriptor.copyInfo: # this is the source self._copyFontInfo(self.fonts[sourceDescriptor.name].info, font.info) if sourceDescriptor.copyLib: # excplicitly copy the font.lib items for key, value in self.fonts[ sourceDescriptor.name].lib.items(): font.lib[key] = value if sourceDescriptor.copyFeatures: featuresText = self.fonts[sourceDescriptor.name].features.text if isinstance(featuresText, str): font.features.text = u"" + featuresText elif isinstance(featuresText, unicode): font.features.text = featuresText # glyphs if glyphNames: selectedGlyphNames = glyphNames else: selectedGlyphNames = self.glyphNames # add the glyphnames to the font.lib['public.glyphOrder'] if not 'public.glyphOrder' in font.lib.keys(): font.lib['public.glyphOrder'] = selectedGlyphNames for glyphName in selectedGlyphNames: try: glyphMutator = self.getGlyphMutator(glyphName) except: self.problems.append("Could not make mutator for glyph %s" % glyphName) continue if glyphName in instanceDescriptor.glyphs.keys(): # reminder: this is what the glyphData can look like # {'instanceLocation': {'custom': 0.0, 'weight': 824.0}, # 'masters': [{'font': 'master.Adobe VF Prototype.Master_0.0', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 0.0, 'weight': 0.0}}, # {'font': 'master.Adobe VF Prototype.Master_1.1', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 0.0, 'weight': 368.0}}, # {'font': 'master.Adobe VF Prototype.Master_2.2', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 0.0, 'weight': 1000.0}}, # {'font': 'master.Adobe VF Prototype.Master_3.3', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 100.0, 'weight': 1000.0}}, # {'font': 'master.Adobe VF Prototype.Master_0.4', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 100.0, 'weight': 0.0}}, # {'font': 'master.Adobe VF Prototype.Master_4.5', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 100.0, 'weight': 368.0}}], # 'unicodes': [36]} glyphData = instanceDescriptor.glyphs[glyphName] else: glyphData = {} font.newGlyph(glyphName) font[glyphName].clear() if glyphData.get('mute', False): # mute this glyph, skip continue glyphInstanceLocation = Location( glyphData.get("instanceLocation", instanceDescriptor.location)) try: uniValues = glyphMutator[()][0].unicodes except IndexError: uniValues = [] glyphInstanceUnicodes = glyphData.get("unicodes", uniValues) note = glyphData.get("note") if note: font[glyphName] = note masters = glyphData.get("masters", None) if masters: items = [] for glyphMaster in masters: sourceGlyphFont = glyphMaster.get("font") sourceGlyphName = glyphMaster.get("glyphName", glyphName) m = self.fonts.get(sourceGlyphFont) if not sourceGlyphName in m: continue sourceGlyph = MathGlyph(m[sourceGlyphName]) sourceGlyphLocation = Location(glyphMaster.get("location")) items.append((sourceGlyphLocation, sourceGlyph)) bias, glyphMutator = buildMutator(items, axes=self._preppedAxes, bias=self.defaultLoc) try: glyphInstanceObject = glyphMutator.makeInstance( glyphInstanceLocation) except IndexError: # alignment problem with the data? print("Error making instance %s" % glyphName) continue font.newGlyph(glyphName) font[glyphName].clear() if self.roundGeometry: try: glyphInstanceObject = glyphInstanceObject.round() except AttributeError: pass try: glyphInstanceObject.extractGlyph(font[glyphName], onlyGeometry=True) except TypeError: # this causes ruled glyphs to end up in the wrong glyphname # but defcon2 objects don't support it pPen = font[glyphName].getPointPen() font[glyphName].clear() glyphInstanceObject.drawPoints(pPen) font[glyphName].width = glyphInstanceObject.width font[glyphName].unicodes = glyphInstanceUnicodes if doRules: resultNames = processRules(self.rules, loc, self.glyphNames) for oldName, newName in zip(self.glyphNames, resultNames): if oldName != newName: swapGlyphNames(font, oldName, newName) # copy the glyph lib? #for sourceDescriptor in self.sources: # if sourceDescriptor.copyLib: # pass # pass # store designspace location in the font.lib font.lib['designspace'] = list(instanceDescriptor.location.items()) return font
def makeInstance(self, instanceDescriptor, doRules=False, glyphNames=None): """ Generate a font object for this instance """ font = self._instantiateFont(None) # make fonty things here loc = instanceDescriptor.location anisotropic = False locHorizontal = locVertical = loc if self.isAnisotropic(loc): anisotropic = True locHorizontal, locVertical = self.splitAnisotropic(loc) # groups if hasattr(self.fonts[self.default.name], "kerningGroupConversionRenameMaps"): renameMap = self.fonts[ self.default.name].kerningGroupConversionRenameMaps else: renameMap = {} font.kerningGroupConversionRenameMaps = renameMap # make the kerning # this kerning is always horizontal. We can take the horizontal location if instanceDescriptor.kerning: try: kerningMutator = self.getKerningMutator() kerningObject = kerningMutator.makeInstance(locHorizontal) kerningObject.extractKerning(font) except: self.problems.append("Could not make kerning for %s. %s" % (loc, traceback.format_exc())) # make the info try: infoMutator = self.getInfoMutator() if not anisotropic: infoInstanceObject = infoMutator.makeInstance(loc) else: horizontalInfoInstanceObject = infoMutator.makeInstance( locHorizontal) verticalInfoInstanceObject = infoMutator.makeInstance( locVertical) # merge them again infoInstanceObject = (1, 0) * horizontalInfoInstanceObject + ( 0, 1) * verticalInfoInstanceObject infoInstanceObject.extractInfo(font.info) font.info.familyName = instanceDescriptor.familyName font.info.styleName = instanceDescriptor.styleName font.info.postScriptFontName = instanceDescriptor.postScriptFontName font.info.styleMapFamilyName = instanceDescriptor.styleMapFamilyName font.info.styleMapStyleName = instanceDescriptor.styleMapStyleName # NEED SOME HELP WITH THIS # localised names need to go to the right openTypeNameRecords # records = [] # nameID = 1 # platformID = # for languageCode, name in instanceDescriptor.localisedStyleMapFamilyName.items(): # # Name ID 1 (font family name) is found at the generic styleMapFamily attribute. # records.append((nameID, )) except: self.problems.append("Could not make fontinfo for %s. %s" % (loc, traceback.format_exc())) for sourceDescriptor in self.sources: if sourceDescriptor.copyInfo: # this is the source self._copyFontInfo(self.fonts[sourceDescriptor.name].info, font.info) if sourceDescriptor.copyLib: # excplicitly copy the font.lib items for key, value in self.fonts[ sourceDescriptor.name].lib.items(): font.lib[key] = value if sourceDescriptor.copyFeatures: featuresText = self.fonts[sourceDescriptor.name].features.text if isinstance(featuresText, str): font.features.text = u"" + featuresText elif isinstance(featuresText, unicode): font.features.text = featuresText # glyphs if glyphNames: selectedGlyphNames = glyphNames else: selectedGlyphNames = self.glyphNames # add the glyphnames to the font.lib['public.glyphOrder'] if not 'public.glyphOrder' in font.lib.keys(): font.lib['public.glyphOrder'] = selectedGlyphNames for glyphName in selectedGlyphNames: try: glyphMutator = self.getGlyphMutator(glyphName) if glyphMutator is None: continue except: self.problems.append("Could not make mutator for glyph %s %s" % (glyphName, traceback.format_exc())) continue if glyphName in instanceDescriptor.glyphs.keys(): # XXX this should be able to go now that we have full rule support. # reminder: this is what the glyphData can look like # {'instanceLocation': {'custom': 0.0, 'weight': 824.0}, # 'masters': [{'font': 'master.Adobe VF Prototype.Master_0.0', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 0.0, 'weight': 0.0}}, # {'font': 'master.Adobe VF Prototype.Master_1.1', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 0.0, 'weight': 368.0}}, # {'font': 'master.Adobe VF Prototype.Master_2.2', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 0.0, 'weight': 1000.0}}, # {'font': 'master.Adobe VF Prototype.Master_3.3', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 100.0, 'weight': 1000.0}}, # {'font': 'master.Adobe VF Prototype.Master_0.4', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 100.0, 'weight': 0.0}}, # {'font': 'master.Adobe VF Prototype.Master_4.5', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 100.0, 'weight': 368.0}}], # 'unicodes': [36]} glyphData = instanceDescriptor.glyphs[glyphName] else: glyphData = {} font.newGlyph(glyphName) font[glyphName].clear() if glyphData.get('mute', False): # mute this glyph, skip continue glyphInstanceLocation = glyphData.get("instanceLocation", instanceDescriptor.location) uniValues = [] neutral = glyphMutator.get(()) if neutral is not None: uniValues = neutral[0].unicodes glyphInstanceUnicodes = glyphData.get("unicodes", uniValues) note = glyphData.get("note") if note: font[glyphName] = note masters = glyphData.get("masters", None) if masters: items = [] for glyphMaster in masters: sourceGlyphFont = glyphMaster.get("font") sourceGlyphName = glyphMaster.get("glyphName", glyphName) m = self.fonts.get(sourceGlyphFont) if not sourceGlyphName in m: continue if hasattr(m[sourceGlyphName], "toMathGlyph"): sourceGlyph = m[sourceGlyphName].toMathGlyph() else: sourceGlyph = MathGlyph(m[sourceGlyphName]) sourceGlyphLocation = glyphMaster.get("location") items.append((sourceGlyphLocation, sourceGlyph)) bias, glyphMutator = self.getVariationModel( items, axes=self.serializedAxes, bias=self.defaultLoc) try: if not self.isAnisotropic(glyphInstanceLocation): glyphInstanceObject = glyphMutator.makeInstance( glyphInstanceLocation) else: # split anisotropic location into horizontal and vertical components horizontal, vertical = self.splitAnisotropic( glyphInstanceLocation) horizontalGlyphInstanceObject = glyphMutator.makeInstance( horizontal) verticalGlyphInstanceObject = glyphMutator.makeInstance( vertical) # merge them again glyphInstanceObject = ( 0, 1) * horizontalGlyphInstanceObject + ( 1, 0) * verticalGlyphInstanceObject except IndexError: # alignment problem with the data? print("Error making instance %s" % glyphName) continue font.newGlyph(glyphName) font[glyphName].clear() if self.roundGeometry: try: glyphInstanceObject = glyphInstanceObject.round() except AttributeError: pass try: glyphInstanceObject.extractGlyph(font[glyphName], onlyGeometry=True) except TypeError: # this causes ruled glyphs to end up in the wrong glyphname # but defcon2 objects don't support it pPen = font[glyphName].getPointPen() font[glyphName].clear() glyphInstanceObject.drawPoints(pPen) font[glyphName].width = glyphInstanceObject.width font[glyphName].unicodes = glyphInstanceUnicodes if doRules: resultNames = processRules(self.rules, loc, self.glyphNames) for oldName, newName in zip(self.glyphNames, resultNames): if oldName != newName: swapGlyphNames(font, oldName, newName) # copy the glyph lib? #for sourceDescriptor in self.sources: # if sourceDescriptor.copyLib: # pass # pass # store designspace location in the font.lib font.lib['designspace'] = list(instanceDescriptor.location.items()) return font
def makeInstance(self, instanceDescriptor, doRules=False, glyphNames=None, pairs=None, bend=False): """ Generate a font object for this instance """ font = self._instantiateFont(None) # make fonty things here loc = Location(instanceDescriptor.location) anisotropic = False locHorizontal = locVertical = loc if self.isAnisotropic(loc): anisotropic = True locHorizontal, locVertical = self.splitAnisotropic(loc) # groups renameMap = getattr(self.fonts[self.default.name], "kerningGroupConversionRenameMaps", None) font.kerningGroupConversionRenameMaps = renameMap if renameMap is not None else {'side1': {}, 'side2': {}} # make the kerning # this kerning is always horizontal. We can take the horizontal location # filter the available pairs? if instanceDescriptor.kerning: if pairs: try: kerningMutator = self.getKerningMutator(pairs=pairs) kerningObject = kerningMutator.makeInstance(locHorizontal, bend=bend) kerningObject.extractKerning(font) except: self.problems.append("Could not make kerning for %s. %s" % (loc, traceback.format_exc())) else: kerningMutator = self.getKerningMutator() if kerningMutator is not None: kerningObject = kerningMutator.makeInstance(locHorizontal, bend=bend) kerningObject.extractKerning(font) # make the info try: infoMutator = self.getInfoMutator() if infoMutator is not None: if not anisotropic: infoInstanceObject = infoMutator.makeInstance(loc, bend=bend) else: horizontalInfoInstanceObject = infoMutator.makeInstance(locHorizontal, bend=bend) verticalInfoInstanceObject = infoMutator.makeInstance(locVertical, bend=bend) # merge them again infoInstanceObject = (1,0)*horizontalInfoInstanceObject + (0,1)*verticalInfoInstanceObject if self.roundGeometry: try: infoInstanceObject = infoInstanceObject.round() except AttributeError: pass infoInstanceObject.extractInfo(font.info) font.info.familyName = instanceDescriptor.familyName font.info.styleName = instanceDescriptor.styleName font.info.postscriptFontName = instanceDescriptor.postScriptFontName # yikes, note the differences in capitalisation.. font.info.styleMapFamilyName = instanceDescriptor.styleMapFamilyName font.info.styleMapStyleName = instanceDescriptor.styleMapStyleName # NEED SOME HELP WITH THIS # localised names need to go to the right openTypeNameRecords # records = [] # nameID = 1 # platformID = # for languageCode, name in instanceDescriptor.localisedStyleMapFamilyName.items(): # # Name ID 1 (font family name) is found at the generic styleMapFamily attribute. # records.append((nameID, )) except: self.problems.append("Could not make fontinfo for %s. %s" % (loc, traceback.format_exc())) for sourceDescriptor in self.sources: if sourceDescriptor.copyInfo: # this is the source if self.fonts[sourceDescriptor.name] is not None: self._copyFontInfo(self.fonts[sourceDescriptor.name].info, font.info) if sourceDescriptor.copyLib: # excplicitly copy the font.lib items if self.fonts[sourceDescriptor.name] is not None: for key, value in self.fonts[sourceDescriptor.name].lib.items(): font.lib[key] = value if sourceDescriptor.copyGroups: if self.fonts[sourceDescriptor.name] is not None: sides = font.kerningGroupConversionRenameMaps.get('side1', {}) sides.update(font.kerningGroupConversionRenameMaps.get('side2', {})) for key, value in self.fonts[sourceDescriptor.name].groups.items(): if key not in sides: font.groups[key] = value if sourceDescriptor.copyFeatures: if self.fonts[sourceDescriptor.name] is not None: featuresText = self.fonts[sourceDescriptor.name].features.text font.features.text = featuresText # glyphs if glyphNames: selectedGlyphNames = glyphNames else: selectedGlyphNames = self.glyphNames # add the glyphnames to the font.lib['public.glyphOrder'] if not 'public.glyphOrder' in font.lib.keys(): font.lib['public.glyphOrder'] = selectedGlyphNames for glyphName in selectedGlyphNames: try: glyphMutator = self.getGlyphMutator(glyphName) if glyphMutator is None: self.problems.append("Could not make mutator for glyph %s" % (glyphName)) continue except: self.problems.append("Could not make mutator for glyph %s %s" % (glyphName, traceback.format_exc())) continue if glyphName in instanceDescriptor.glyphs.keys(): # XXX this should be able to go now that we have full rule support. # reminder: this is what the glyphData can look like # {'instanceLocation': {'custom': 0.0, 'weight': 824.0}, # 'masters': [{'font': 'master.Adobe VF Prototype.Master_0.0', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 0.0, 'weight': 0.0}}, # {'font': 'master.Adobe VF Prototype.Master_1.1', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 0.0, 'weight': 368.0}}, # {'font': 'master.Adobe VF Prototype.Master_2.2', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 0.0, 'weight': 1000.0}}, # {'font': 'master.Adobe VF Prototype.Master_3.3', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 100.0, 'weight': 1000.0}}, # {'font': 'master.Adobe VF Prototype.Master_0.4', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 100.0, 'weight': 0.0}}, # {'font': 'master.Adobe VF Prototype.Master_4.5', # 'glyphName': 'dollar.nostroke', # 'location': {'custom': 100.0, 'weight': 368.0}}], # 'unicodes': [36]} glyphData = instanceDescriptor.glyphs[glyphName] else: glyphData = {} font.newGlyph(glyphName) font[glyphName].clear() if glyphData.get('mute', False): # mute this glyph, skip continue glyphInstanceLocation = glyphData.get("instanceLocation", instanceDescriptor.location) glyphInstanceLocation = Location(glyphInstanceLocation) uniValues = [] neutral = glyphMutator.get(()) if neutral is not None: uniValues = neutral[0].unicodes else: neutralFont = self.getNeutralFont() if glyphName in neutralFont: uniValues = neutralFont[glyphName].unicodes glyphInstanceUnicodes = glyphData.get("unicodes", uniValues) note = glyphData.get("note") if note: font[glyphName] = note # XXXX phase out support for instance-specific masters # this should be handled by the rules system. masters = glyphData.get("masters", None) if masters is not None: items = [] for glyphMaster in masters: sourceGlyphFont = glyphMaster.get("font") sourceGlyphName = glyphMaster.get("glyphName", glyphName) m = self.fonts.get(sourceGlyphFont) if not sourceGlyphName in m: continue if hasattr(m[sourceGlyphName], "toMathGlyph"): sourceGlyph = m[sourceGlyphName].toMathGlyph() else: sourceGlyph = MathGlyph(m[sourceGlyphName]) sourceGlyphLocation = glyphMaster.get("location") items.append((Location(sourceGlyphLocation), sourceGlyph)) bias, glyphMutator = self.getVariationModel(items, axes=self.serializedAxes, bias=self.newDefaultLocation(bend=True)) try: if not self.isAnisotropic(glyphInstanceLocation): glyphInstanceObject = glyphMutator.makeInstance(glyphInstanceLocation, bend=bend) else: # split anisotropic location into horizontal and vertical components horizontal, vertical = self.splitAnisotropic(glyphInstanceLocation) horizontalGlyphInstanceObject = glyphMutator.makeInstance(horizontal, bend=bend) verticalGlyphInstanceObject = glyphMutator.makeInstance(vertical, bend=bend) # merge them again glyphInstanceObject = (1,0)*horizontalGlyphInstanceObject + (0,1)*verticalGlyphInstanceObject except IndexError: # alignment problem with the data? self.problems.append("Quite possibly some sort of data alignment error in %s" % glyphName) continue font.newGlyph(glyphName) font[glyphName].clear() if self.roundGeometry: try: glyphInstanceObject = glyphInstanceObject.round() except AttributeError: pass try: # File "/Users/erik/code/ufoProcessor/Lib/ufoProcessor/__init__.py", line 649, in makeInstance # glyphInstanceObject.extractGlyph(font[glyphName], onlyGeometry=True) # File "/Applications/RoboFont.app/Contents/Resources/lib/python3.6/fontMath/mathGlyph.py", line 315, in extractGlyph # glyph.anchors = [dict(anchor) for anchor in self.anchors] # File "/Applications/RoboFont.app/Contents/Resources/lib/python3.6/fontParts/base/base.py", line 103, in __set__ # raise FontPartsError("no setter for %r" % self.name) # fontParts.base.errors.FontPartsError: no setter for 'anchors' if hasattr(font[glyphName], "fromMathGlyph"): font[glyphName].fromMathGlyph(glyphInstanceObject) else: glyphInstanceObject.extractGlyph(font[glyphName], onlyGeometry=True) except TypeError: # this causes ruled glyphs to end up in the wrong glyphname # but defcon2 objects don't support it pPen = font[glyphName].getPointPen() font[glyphName].clear() glyphInstanceObject.drawPoints(pPen) font[glyphName].width = glyphInstanceObject.width font[glyphName].unicodes = glyphInstanceUnicodes if doRules: resultNames = processRules(self.rules, loc, self.glyphNames) for oldName, newName in zip(self.glyphNames, resultNames): if oldName != newName: swapGlyphNames(font, oldName, newName) # copy the glyph lib? #for sourceDescriptor in self.sources: # if sourceDescriptor.copyLib: # pass # pass # store designspace location in the font.lib font.lib['designspace.location'] = list(instanceDescriptor.location.items()) return font
def generateInstanceFont(self, spot, generationInfos): # self.w.spotSheet.close() # delattr(self.w, 'spotSheet') if generationInfos['sourceFont']: baseFont = generationInfos['sourceFont'][0] doKerning = generationInfos['interpolateKerning'] doFontInfos = generationInfos['interpolateFontInfos'] doReport = generationInfos['printReport'] progress = ProgressWindow('Generating instance', parentWindow=self.w) fonts = [font for _, font in self.masters] i, j = spot ch = getKeyForValue(i) instanceLocation = Location(horizontal=i, vertical=j) masterLocations = [(Location(horizontal=getValueForKey(_ch), vertical=_j), masterFont) for (_ch, _j), masterFont in self.masters] # Build font newFont = RFont(showUI=False) newFont.info.familyName = baseFont.info.familyName newFont.info.styleName = '%s%s'%(ch.upper(), j+1) interpolatedGlyphs = [] interpolatedInfo = None interpolatedKerning = None interpolationReports = [] # interpolate font infos if doFontInfos: infoMasters = [(location, MathInfo(font.info)) for location, font in masterLocations] try: bias, iM = buildMutator(infoMasters) instanceInfo = iM.makeInstance(instanceLocation) instanceInfo.extractInfo(newFont.info) except: pass # interpolate kerning if doKerning: kerningMasters = [(location, MathKerning(font.kerning)) for location, font in masterLocations] try: bias, kM = buildMutator(kerningMasters) instanceKerning = kM.makeInstance(instanceLocation) instanceKerning.extractKerning(newFont) for key, value in baseFont.groups.items(): newFont.groups[key] = value except: pass # filter compatible glyphs fontKeys = [set(font.keys()) for font in fonts] glyphList = set() for i, item in enumerate(fontKeys): if i == 0: glyphList = item elif i > 0: glyphList = glyphList & item compatibleBaseGlyphList = [] compatibleCompositeGlyphList = [] for glyphName in glyphList: glyphs = [font[glyphName] for font in fonts] compatible = True for glyph in glyphs[1:]: comp, report = glyphs[0].isCompatible(glyph) if comp == False: name = '%s <X> %s'%(fontName(glyphs[0].getParent()), fontName(glyph.getParent())) reportLine = (name, report) if reportLine not in interpolationReports: interpolationReports.append(reportLine) compatible = False if compatible: compatibleBaseGlyphList.append(glyphName) # initiate glyph interpolation for glyphName in compatibleBaseGlyphList: glyphMasters = [(location, MathGlyph(font[glyphName])) for location, font in masterLocations] try: bias, gM = buildMutator(glyphMasters) newGlyph = RGlyph() instanceGlyph = gM.makeInstance(instanceLocation) interpolatedGlyphs.append((glyphName, instanceGlyph.extractGlyph(newGlyph))) except: continue for name, iGlyph in interpolatedGlyphs: newFont.insertGlyph(iGlyph, name) progress.close() digest = [] if doReport: for fontNames, report in interpolationReports: digest.append(fontNames) digest += [u'– %s'%(reportLine) for reportLine in report] digest.append('\n') print '\n'.join(digest) newFont.showUI()