def test_round(self): m = _TestInfoObject() m.ascender = 699.99 m.descender = -199.99 m.xHeight = 399.66 m.postscriptSlantAngle = None m.postscriptStemSnapH = [80.1, 90.2] m.guidelines = [{'y': 100.99, 'x': None, 'angle': None, 'name': 'bar'}] m.italicAngle = -9.4 m.postscriptBlueScale = 0.137 info = MathInfo(m) info = info.round() self.assertEqual(info.ascender, 700) self.assertEqual(info.descender, -200) self.assertEqual(info.xHeight, 400) self.assertEqual(m.italicAngle, -9.4) self.assertEqual(m.postscriptBlueScale, 0.137) self.assertIsNone(info.postscriptSlantAngle) self.assertEqual(info.postscriptStemSnapH, [80, 90]) self.assertEqual( [sorted(gl.items()) for gl in info.guidelines], [[('angle', 0), ('name', 'bar'), ('x', 0), ('y', 101)]] ) written = {} expected = {} for attr, value in _testData.items(): if value is None: continue written[attr] = getattr(info, attr) if isinstance(value, list): expectedValue = [_roundNumber(v) for v in value] else: expectedValue = _roundNumber(value) expected[attr] = expectedValue self.assertEqual(sorted(expected), sorted(written))
def test_round(self): m = _TestInfoObject() m.ascender = 699.99 m.descender = -199.99 m.xHeight = 399.66 m.postscriptSlantAngle = None m.postscriptStemSnapH = [80.1, 90.2] m.guidelines = [{'y': 100.99, 'x': None, 'angle': None, 'name': 'bar'}] m.italicAngle = -9.4 m.postscriptBlueScale = 0.137 info = MathInfo(m) info = info.round() self.assertEqual(info.ascender, 700) self.assertEqual(info.descender, -200) self.assertEqual(info.xHeight, 400) self.assertEqual(m.italicAngle, -9.4) self.assertEqual(m.postscriptBlueScale, 0.137) self.assertIsNone(info.postscriptSlantAngle) self.assertEqual(info.postscriptStemSnapH, [80, 90]) self.assertEqual([sorted(gl.items()) for gl in info.guidelines], [[('angle', 0), ('name', 'bar'), ('x', 0), ('y', 101)]]) written = {} expected = {} for attr, value in _testData.items(): if value is None: continue written[attr] = getattr(info, attr) if isinstance(value, list): expectedValue = [_roundNumber(v) for v in value] else: expectedValue = _roundNumber(value) expected[attr] = expectedValue self.assertEqual(sorted(expected), sorted(written))
def test_compare_different(self): info1 = MathInfo(_TestInfoObject()) info2 = MathInfo(_TestInfoObject()) info2.ascender = info2.ascender - 1 self.assertFalse(info1 < info2) self.assertTrue(info1 > info2) self.assertNotEqual(info1, info2)
def test_weight_name(self): info1 = MathInfo(_TestInfoObject()) info2 = MathInfo(_TestInfoObject()) info2.openTypeOS2WeightClass = 0 info3 = info1 + info2 self.assertEqual(info3.openTypeOS2WeightClass, 500) self.assertEqual(info3.postscriptWeightName, "Medium") info2.openTypeOS2WeightClass = 49 info3 = info1 + info2 self.assertEqual(info3.openTypeOS2WeightClass, 549) self.assertEqual(info3.postscriptWeightName, "Medium") info2.openTypeOS2WeightClass = 50 info3 = info1 + info2 self.assertEqual(info3.openTypeOS2WeightClass, 550) self.assertEqual(info3.postscriptWeightName, "Semi-bold") info2.openTypeOS2WeightClass = 50 info3 = info1 - info2 self.assertEqual(info3.openTypeOS2WeightClass, 450) self.assertEqual(info3.postscriptWeightName, "Medium") info2.openTypeOS2WeightClass = 51 info3 = info1 - info2 self.assertEqual(info3.openTypeOS2WeightClass, 449) self.assertEqual(info3.postscriptWeightName, "Normal") info2.openTypeOS2WeightClass = 500 info3 = info1 - info2 self.assertEqual(info3.openTypeOS2WeightClass, 0) self.assertEqual(info3.postscriptWeightName, "Thin") info2.openTypeOS2WeightClass = 1500 info3 = info1 - info2 self.assertEqual(info3.openTypeOS2WeightClass, -1000) self.assertEqual(info3.postscriptWeightName, "Thin") info2.openTypeOS2WeightClass = 500 info3 = info1 + info2 self.assertEqual(info3.openTypeOS2WeightClass, 1000) self.assertEqual(info3.postscriptWeightName, "Black")
def test_sub(self): info1 = MathInfo(_TestInfoObject()) info2 = MathInfo(_TestInfoObject()) info3 = info1 - info2 written = {} expected = {} for attr, value in _testData.items(): if value is None: continue written[attr] = getattr(info3, attr) if isinstance(value, list): expectedValue = [v - v for v in value] else: expectedValue = value - value expected[attr] = expectedValue self.assertEqual(sorted(expected.items()), sorted(written.items()))
def test_add_data_subset_2nd_operand(self): info1 = MathInfo(_TestInfoObject()) info2 = MathInfo(_TestInfoObject(_testDataSubset)) info3 = info1 + info2 written = {} expected = {} for attr, value in _testData.items(): if value is None: continue written[attr] = getattr(info3, attr) if isinstance(value, list): expectedValue = [v + v for v in value] else: expectedValue = value + value expected[attr] = expectedValue self.assertEqual(sorted(expected), sorted(written))
def addInfo(self, instanceLocation=None, sources=None, copySourceName=None): """ Add font info data. """ if instanceLocation is None: instanceLocation = self.locationObject infoObject = self.font.info infoMasters = [] if sources is None: sources = self.sources items = [] for sourceName, (source, sourceLocation) in sources.items(): if sourceName in self.muted['info']: # info in this master was muted, so do not add. continue items.append((sourceLocation, MathInfo(source.info))) bias, m = buildMutator(items) instanceObject = m.makeInstance(instanceLocation) if self.roundGeometry: instanceObject = instanceObject.round() instanceObject.extractInfo(self.font.info) # handle the copyable info fields if copySourceName is not None: if not copySourceName in sources: if self.verbose and self.logger: self.logger.info( "Copy info source %s not found, skipping.", copySourceName) return copySourceObject, loc = sources[copySourceName] self._copyFontInfo(self.font.info, copySourceObject.info)
def test_sub_undefined_number_list_sets_None(self): self.assertIn("postscriptBlueValues", _numberListAttrs) info1 = _TestInfoObject() info1.postscriptBlueValues = None m1 = MathInfo(info1) info2 = _TestInfoObject() info2.postscriptBlueValues = [1, 2, 3] m2 = MathInfo(info2) m3 = m2 - m1 self.assertIsNone(m3.postscriptBlueValues) m4 = m1 - m2 self.assertIsNone(m4.postscriptBlueValues)
def test_number_lists_with_different_lengths(self): self.assertIn("postscriptBlueValues", _numberListAttrs) info1 = _TestInfoObject() info1.postscriptBlueValues = [1, 2] m1 = MathInfo(info1) info2 = _TestInfoObject() info2.postscriptBlueValues = [1, 2, 3] m2 = MathInfo(info2) m3 = m2 - m1 self.assertIsNone(m3.postscriptBlueValues) m4 = m1 - m2 self.assertIsNone(m4.postscriptBlueValues) m5 = m1 + m2 self.assertIsNone(m5.postscriptBlueValues)
def test_div(self): info1 = MathInfo(_TestInfoObject()) info2 = info1 / 2 written = {} expected = {} for attr, value in _testData.items(): if value is None: continue written[attr] = getattr(info2, attr) if isinstance(value, list): expectedValue = [v / 2 for v in value] else: expectedValue = value / 2 expected[attr] = expectedValue self.assertEqual(sorted(expected), sorted(written))
def addInfo(self, instanceLocation=None, sources=None, copySourceName=None): """ Add font info data. """ if instanceLocation is None: instanceLocation = self.locationObject infoObject = self.font.info infoMasters = [] if sources is None: sources = self.sources items = [] for sourceName, (source, sourceLocation) in sources.items(): if sourceName in self.muted['info']: # info in this master was muted, so do not add. continue items.append((sourceLocation, MathInfo(source.info))) try: bias, m = buildMutator(items, axes=self.axes) except: if self.logger: self.logger.exception("Error processing font info. %s", items) return instanceObject = m.makeInstance(instanceLocation, bend=self.bendLocations) if self.roundGeometry: try: instanceObject = instanceObject.round() except AttributeError: warnings.warn("MathInfo object missing round() method.") instanceObject.extractInfo(self.font.info) # handle the copyable info fields if copySourceName is not None: if not copySourceName in sources: if self.verbose and self.logger: self.logger.info( "Copy info source %s not found, skipping.", copySourceName) return copySourceObject, loc = sources[copySourceName] self._copyFontInfo(self.font.info, copySourceObject.info)
def test_mul_data_subset(self): info1 = MathInfo(_TestInfoObject(_testDataSubset)) info2 = info1 * 2.5 written = {} expected = {} for attr, value in _testDataSubset.items(): if value is None: continue written[attr] = getattr(info2, attr) expected = { "descender": -500.0, "guidelines": [{ "y": 250.0, "x": 0.0, "identifier": "2", "angle": 0.0, "name": "bar" }], "postscriptBlueValues": [-25.0, 0.0, 1000.0, 1025.0, 1625.0], "unitsPerEm": 2500.0 } self.assertEqual(sorted(expected.items()), sorted(written.items()))
def test_compare_same(self): info1 = MathInfo(_TestInfoObject()) info2 = MathInfo(_TestInfoObject()) self.assertFalse(info1 < info2) self.assertFalse(info1 > info2) self.assertEqual(info1, info2)
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()