1from __future__ import absolute_import, unicode_literals 2import os 3import tempfile 4import shutil 5import unittest 6from io import open 7from .testSupport import getDemoFontGlyphSetPath 8from fontTools.ufoLib.glifLib import ( 9 GlyphSet, glyphNameToFileName, readGlyphFromString, writeGlyphToString, 10) 11from fontTools.misc.etree import XML_DECLARATION 12 13GLYPHSETDIR = getDemoFontGlyphSetPath() 14 15 16class GlyphSetTests(unittest.TestCase): 17 18 def setUp(self): 19 self.dstDir = tempfile.mktemp() 20 os.mkdir(self.dstDir) 21 22 def tearDown(self): 23 shutil.rmtree(self.dstDir) 24 25 def testRoundTrip(self): 26 import difflib 27 srcDir = GLYPHSETDIR 28 dstDir = self.dstDir 29 src = GlyphSet(srcDir, ufoFormatVersion=2, validateRead=True, validateWrite=True) 30 dst = GlyphSet(dstDir, ufoFormatVersion=2, validateRead=True, validateWrite=True) 31 for glyphName in src.keys(): 32 g = src[glyphName] 33 g.drawPoints(None) # load attrs 34 dst.writeGlyph(glyphName, g, g.drawPoints) 35 # compare raw file data: 36 for glyphName in sorted(src.keys()): 37 fileName = src.contents[glyphName] 38 with open(os.path.join(srcDir, fileName), "r") as f: 39 org = f.read() 40 with open(os.path.join(dstDir, fileName), "r") as f: 41 new = f.read() 42 added = [] 43 removed = [] 44 for line in difflib.unified_diff( 45 org.split("\n"), new.split("\n")): 46 if line.startswith("+ "): 47 added.append(line[1:]) 48 elif line.startswith("- "): 49 removed.append(line[1:]) 50 self.assertEqual( 51 added, removed, 52 "%s.glif file differs after round tripping" % glyphName) 53 54 def testRebuildContents(self): 55 gset = GlyphSet(GLYPHSETDIR, validateRead=True, validateWrite=True) 56 contents = gset.contents 57 gset.rebuildContents() 58 self.assertEqual(contents, gset.contents) 59 60 def testReverseContents(self): 61 gset = GlyphSet(GLYPHSETDIR, validateRead=True, validateWrite=True) 62 d = {} 63 for k, v in gset.getReverseContents().items(): 64 d[v] = k 65 org = {} 66 for k, v in gset.contents.items(): 67 org[k] = v.lower() 68 self.assertEqual(d, org) 69 70 def testReverseContents2(self): 71 src = GlyphSet(GLYPHSETDIR, validateRead=True, validateWrite=True) 72 dst = GlyphSet(self.dstDir, validateRead=True, validateWrite=True) 73 dstMap = dst.getReverseContents() 74 self.assertEqual(dstMap, {}) 75 for glyphName in src.keys(): 76 g = src[glyphName] 77 g.drawPoints(None) # load attrs 78 dst.writeGlyph(glyphName, g, g.drawPoints) 79 self.assertNotEqual(dstMap, {}) 80 srcMap = dict(src.getReverseContents()) # copy 81 self.assertEqual(dstMap, srcMap) 82 del srcMap["a.glif"] 83 dst.deleteGlyph("a") 84 self.assertEqual(dstMap, srcMap) 85 86 def testCustomFileNamingScheme(self): 87 def myGlyphNameToFileName(glyphName, glyphSet): 88 return "prefix" + glyphNameToFileName(glyphName, glyphSet) 89 src = GlyphSet(GLYPHSETDIR, validateRead=True, validateWrite=True) 90 dst = GlyphSet(self.dstDir, myGlyphNameToFileName, validateRead=True, validateWrite=True) 91 for glyphName in src.keys(): 92 g = src[glyphName] 93 g.drawPoints(None) # load attrs 94 dst.writeGlyph(glyphName, g, g.drawPoints) 95 d = {} 96 for k, v in src.contents.items(): 97 d[k] = "prefix" + v 98 self.assertEqual(d, dst.contents) 99 100 def testGetUnicodes(self): 101 src = GlyphSet(GLYPHSETDIR, validateRead=True, validateWrite=True) 102 unicodes = src.getUnicodes() 103 for glyphName in src.keys(): 104 g = src[glyphName] 105 g.drawPoints(None) # load attrs 106 if not hasattr(g, "unicodes"): 107 self.assertEqual(unicodes[glyphName], []) 108 else: 109 self.assertEqual(g.unicodes, unicodes[glyphName]) 110 111 112class FileNameTests(unittest.TestCase): 113 114 def testDefaultFileNameScheme(self): 115 self.assertEqual(glyphNameToFileName("a", None), "a.glif") 116 self.assertEqual(glyphNameToFileName("A", None), "A_.glif") 117 self.assertEqual(glyphNameToFileName("Aring", None), "A_ring.glif") 118 self.assertEqual(glyphNameToFileName("F_A_B", None), "F__A__B_.glif") 119 self.assertEqual(glyphNameToFileName("A.alt", None), "A_.alt.glif") 120 self.assertEqual(glyphNameToFileName("A.Alt", None), "A_.A_lt.glif") 121 self.assertEqual(glyphNameToFileName(".notdef", None), "_notdef.glif") 122 self.assertEqual(glyphNameToFileName("T_H", None), "T__H_.glif") 123 self.assertEqual(glyphNameToFileName("T_h", None), "T__h.glif") 124 self.assertEqual(glyphNameToFileName("t_h", None), "t_h.glif") 125 self.assertEqual(glyphNameToFileName("F_F_I", None), "F__F__I_.glif") 126 self.assertEqual(glyphNameToFileName("f_f_i", None), "f_f_i.glif") 127 self.assertEqual(glyphNameToFileName("AE", None), "A_E_.glif") 128 self.assertEqual(glyphNameToFileName("Ae", None), "A_e.glif") 129 self.assertEqual(glyphNameToFileName("ae", None), "ae.glif") 130 self.assertEqual(glyphNameToFileName("aE", None), "aE_.glif") 131 self.assertEqual(glyphNameToFileName("a.alt", None), "a.alt.glif") 132 self.assertEqual(glyphNameToFileName("A.aLt", None), "A_.aL_t.glif") 133 self.assertEqual(glyphNameToFileName("A.alT", None), "A_.alT_.glif") 134 self.assertEqual(glyphNameToFileName("Aacute_V.swash", None), "A_acute_V_.swash.glif") 135 self.assertEqual(glyphNameToFileName(".notdef", None), "_notdef.glif") 136 self.assertEqual(glyphNameToFileName("con", None), "_con.glif") 137 self.assertEqual(glyphNameToFileName("CON", None), "C_O_N_.glif") 138 self.assertEqual(glyphNameToFileName("con.alt", None), "_con.alt.glif") 139 self.assertEqual(glyphNameToFileName("alt.con", None), "alt._con.glif") 140 141 142class _Glyph(object): 143 pass 144 145 146class ReadWriteFuncTest(unittest.TestCase): 147 148 def testRoundTrip(self): 149 glyph = _Glyph() 150 glyph.name = "a" 151 glyph.unicodes = [0x0061] 152 153 s1 = writeGlyphToString(glyph.name, glyph) 154 155 glyph2 = _Glyph() 156 readGlyphFromString(s1, glyph2) 157 self.assertEqual(glyph.__dict__, glyph2.__dict__) 158 159 s2 = writeGlyphToString(glyph2.name, glyph2) 160 self.assertEqual(s1, s2) 161 162 def testXmlDeclaration(self): 163 s = writeGlyphToString("a", _Glyph()) 164 self.assertTrue(s.startswith(XML_DECLARATION % "UTF-8")) 165