def testRoundTrip(self): import difflib srcDir = GLYPHSETDIR dstDir = self.dstDir src = GlyphSet(srcDir, ufoFormatVersion=2, validateRead=True, validateWrite=True) dst = GlyphSet(dstDir, ufoFormatVersion=2, validateRead=True, validateWrite=True) for glyphName in src.keys(): g = src[glyphName] g.drawPoints(None) # load attrs dst.writeGlyph(glyphName, g, g.drawPoints) # compare raw file data: for glyphName in sorted(src.keys()): fileName = src.contents[glyphName] with open(os.path.join(srcDir, fileName), "r") as f: org = f.read() with open(os.path.join(dstDir, fileName), "r") as f: new = f.read() added = [] removed = [] for line in difflib.unified_diff(org.split("\n"), new.split("\n")): if line.startswith("+ "): added.append(line[1:]) elif line.startswith("- "): removed.append(line[1:]) self.assertEqual( added, removed, "%s.glif file differs after round tripping" % glyphName)
def write(self, glyphSet: GlyphSet, saveAs: bool = True) -> None: """Write Layer to a :class:`fontTools.ufoLib.glifLib.GlyphSet`. Args: glyphSet: The GlyphSet object to write to. saveAs: If True, tells the writer to save out-of-place. If False, tells the writer to save in-place. This affects how resources are cleaned before writing. """ glyphs = self._glyphs if not saveAs: for name in set(glyphSet.contents).difference(glyphs): glyphSet.deleteGlyph(name) for name, glyph in glyphs.items(): if glyph is _GLYPH_NOT_LOADED: if saveAs: glyph = self.loadGlyph(name) else: continue _prune_object_libs(glyph.lib, _fetch_glyph_identifiers(glyph)) glyphSet.writeGlyph(name, glyphObject=glyph, drawPointsFunc=glyph.drawPoints) glyphSet.writeContents() glyphSet.writeLayerInfo(self) if saveAs: # all glyphs are loaded by now, no need to keep ref to glyphSet self._glyphSet = None
def testCustomFileNamingScheme(self): def myGlyphNameToFileName(glyphName, glyphSet): return "prefix" + glyphNameToFileName(glyphName, glyphSet) src = GlyphSet(GLYPHSETDIR, validateRead=True, validateWrite=True) dst = GlyphSet(self.dstDir, myGlyphNameToFileName, validateRead=True, validateWrite=True) for glyphName in src.keys(): g = src[glyphName] g.drawPoints(None) # load attrs dst.writeGlyph(glyphName, g, g.drawPoints) d = {} for k, v in src.contents.items(): d[k] = "prefix" + v self.assertEqual(d, dst.contents)
def testReverseContents2(self): src = GlyphSet(GLYPHSETDIR, validateRead=True, validateWrite=True) dst = GlyphSet(self.dstDir, validateRead=True, validateWrite=True) dstMap = dst.getReverseContents() self.assertEqual(dstMap, {}) for glyphName in src.keys(): g = src[glyphName] g.drawPoints(None) # load attrs dst.writeGlyph(glyphName, g, g.drawPoints) self.assertNotEqual(dstMap, {}) srcMap = dict(src.getReverseContents()) # copy self.assertEqual(dstMap, srcMap) del srcMap["a.glif"] dst.deleteGlyph("a") self.assertEqual(dstMap, srcMap)
def test_conflicting_case_insensitive_file_names(self, tmp_path): src = GlyphSet(GLYPHSETDIR) dst = GlyphSet(tmp_path) glyph = src["a"] dst.writeGlyph("a", glyph) dst.writeGlyph("A", glyph) dst.writeGlyph("a_", glyph) dst.deleteGlyph("a_") dst.writeGlyph("a_", glyph) dst.writeGlyph("A_", glyph) dst.writeGlyph("i_j", glyph) assert dst.contents == { 'a': 'a.glif', 'A': 'A_.glif', 'a_': 'a_000000000000001.glif', 'A_': 'A__.glif', 'i_j': 'i_j.glif', } # make sure filenames are unique even on case-insensitive filesystems assert len({fileName.lower() for fileName in dst.contents.values()}) == 5
def test_GlyphSet_writeGlyph_formatVersion(tmp_path): src = GlyphSet(GLYPHSETDIR) dst = GlyphSet(tmp_path, ufoFormatVersion=(2, 0)) glyph = src["A"] # no explicit formatVersion passed: use the more recent GLIF formatVersion # that is supported by given ufoFormatVersion (GLIF 1 for UFO 2) dst.writeGlyph("A", glyph) glif = dst.getGLIF("A") assert b'format="1"' in glif assert b'formatMinor' not in glif # omitted when 0 # explicit, unknown formatVersion with pytest.raises(UnsupportedGLIFFormat): dst.writeGlyph("A", glyph, formatVersion=(0, 0)) # explicit, known formatVersion but unsupported by given ufoFormatVersion with pytest.raises( UnsupportedGLIFFormat, match="Unsupported GLIF format version .*for UFO format version", ): dst.writeGlyph("A", glyph, formatVersion=(2, 0))
def exportButtonCallback(self, sender): f = CurrentFont() if f is None: return if self.verbose: print('exporting selected glyphs back to their sources...\n') for glyphName in f.selectedGlyphNames: if self.importMode == 1: glyph = f[glyphName].getLayer('foreground') if self.glyphSetPathKey not in glyph.lib: continue glyphsFolder = glyph.lib[self.glyphSetPathKey] ufoName = splitall(glyphsFolder)[-2] glyphNameExtension = os.path.splitext(ufoName)[0] glyphNameParts = glyphName.split('.') if not (len(glyphNameParts) > 1 and glyphNameParts[-1] == os.path.splitext(ufoName)[0]): print(f'{glyphName} does not have the expected glyph name extension, skipping...') continue if self.verbose: print(f'\twriting {glyphName} to {ufoName}...') outputGlyphName = '.'.join(glyphNameParts[:-1]) glyphSet = GlyphSet(glyphsFolder, validateWrite=True) glyphSet.writeGlyph(outputGlyphName, glyph.naked(), glyph.drawPoints) glyphSet.writeContents() else: for layerName in f.layerOrder: glyph = f[glyphName].getLayer(layerName) if self.glyphSetPathKey not in glyph.lib: continue glyphsFolder = glyph.lib[self.glyphSetPathKey] # mode 0 if not '.ufoz' in glyphsFolder: glyphSet = GlyphSet(glyphsFolder, validateWrite=True) ufoName = splitall(glyphsFolder)[-2] if self.verbose: print(f'\twriting {glyphName} to {ufoName}...') glyphSet.writeGlyph(glyphName, glyph.naked(), glyph.drawPoints) glyphSet.writeContents() # mode 2 else: ufoPath = os.path.dirname(glyphsFolder) ufoName = splitall(ufoPath)[-1] dstFont = OpenFont(ufoPath, showInterface=False) if self.verbose: print(f'\twriting {glyphName} to {ufoName}...') dstFont.insertGlyph(glyph, name=glyph.name) dstFont.save() dstFont.close() if self.verbose: print() print('...done.\n')