1import unittest 2import tempfile 3import os 4from fontParts.world import RFont, FontList, OpenFont 5 6class TestFontList(unittest.TestCase): 7 8 def getFont(self): 9 font, _ = self.objectGenerator("font") 10 return font 11 12 # ---- 13 # Sort 14 # ---- 15 16 def getFonts_sortBy(self, attr, values): 17 fonts = FontList() 18 for value in values: 19 font = self.getFont() 20 setattr(font.info, attr, value) 21 if attr != "familyName": 22 font.info.familyName = "%s %s" % (attr, repr(value)) 23 fonts.append(font) 24 return fonts 25 26 # Sort Description Strings 27 # ------------------------ 28 29 def getFont_sortBy_monospaceGlyphs(self): 30 font = self.getFont() 31 font.info.familyName = "monospace %s" % str(id(font)) 32 glyph1 = font.newGlyph("a") 33 glyph1.width = 100 34 glyph2 = font.newGlyph("b") 35 glyph2.width = 100 36 return font 37 38 def getFont_sortBy_proportionalGlyphs(self): 39 font = self.getFont() 40 font.info.familyName = "proportional %s" % str(id(font)) 41 glyph1 = font.newGlyph("a") 42 glyph1.width = 100 43 glyph2 = font.newGlyph("b") 44 glyph2.width = 200 45 return font 46 47 # familyName 48 49 def test_sortBy_familyName(self): 50 fonts = self.getFonts_sortBy( 51 "familyName", 52 ["aaa", "bbb", "ccc", None] 53 ) 54 font1, font2, font3, font4 = fonts 55 fonts.sortBy("familyName") 56 expected = [font4, font1, font2, font3] 57 self.assertEqual(fonts, expected) 58 59 # styleName 60 61 def test_sortBy_styleName(self): 62 fonts = self.getFonts_sortBy( 63 "styleName", 64 ["aaa", "bbb", "ccc", None] 65 ) 66 font1, font2, font3, font4 = fonts 67 fonts.sortBy("styleName") 68 expected = [font4, font1, font2, font3] 69 self.assertEqual(fonts, expected) 70 71 # isRoman 72 73 def test_sortBy_isRoman_styleMapStyleName(self): 74 fonts = self.getFonts_sortBy( 75 "styleMapStyleName", 76 ["regular", "italic", "bold", "bold italic"] 77 ) 78 font1, font2, font3, font4 = fonts 79 fonts.reverse() 80 fonts.sortBy("isRoman") 81 expected = [font3, font1, font4, font2] 82 self.assertEqual(fonts, expected) 83 84 def test_sortBy_isRoman_italicAngle(self): 85 fonts = self.getFonts_sortBy( 86 "italicAngle", 87 [1, 2, 3, 0] 88 ) 89 font1, font2, font3, font4 = fonts 90 fonts.sortBy("isRoman") 91 expected = [font4, font1, font2, font3] 92 self.assertEqual(fonts, expected) 93 94 # isItalic 95 96 def test_sortBy_isItalic_styleMapStyleName(self): 97 fonts = self.getFonts_sortBy( 98 "styleMapStyleName", 99 ["regular", "italic", "bold", "bold italic"] 100 ) 101 font1, font2, font3, font4 = fonts 102 fonts.sortBy("isItalic") 103 expected = [font2, font4, font1, font3] 104 self.assertEqual(fonts, expected) 105 106 def test_sortBy_isItalic_italicAngle(self): 107 fonts = self.getFonts_sortBy( 108 "italicAngle", 109 [0, 1, 2, 3] 110 ) 111 font1, font2, font3, font4 = fonts 112 fonts.sortBy("isItalic") 113 expected = [font2, font3, font4, font1] 114 self.assertEqual(fonts, expected) 115 116 # widthValue 117 118 def test_sortBy_widthValue(self): 119 fonts = self.getFonts_sortBy( 120 "openTypeOS2WidthClass", 121 [1, 2, 3, None] 122 ) 123 font1, font2, font3, font4 = fonts 124 fonts.sortBy("widthValue") 125 expected = [font4, font1, font2, font3] 126 self.assertEqual(fonts, expected) 127 128 # weightValue 129 130 def test_sortBy_weightValue(self): 131 fonts = self.getFonts_sortBy( 132 "openTypeOS2WeightClass", 133 [100, 200, 300, None] 134 ) 135 font1, font2, font3, font4 = fonts 136 fonts.sortBy("weightValue") 137 expected = [font4, font1, font2, font3] 138 self.assertEqual(fonts, expected) 139 140 # isMonospace 141 142 def test_sortBy_isMonospace_postscriptIsFixedPitch(self): 143 fonts = self.getFonts_sortBy( 144 "postscriptIsFixedPitch", 145 [True, True, False, False] 146 ) 147 font1, font2, font3, font4 = fonts 148 fonts.reverse() 149 fonts.sortBy("isMonospace") 150 expected = [font2, font1, font4, font3] 151 self.assertEqual(fonts, expected) 152 153 def test_sortBy_isMonospace_glyphs(self): 154 font1 = self.getFont_sortBy_monospaceGlyphs() 155 font2 = self.getFont_sortBy_monospaceGlyphs() 156 font3 = self.getFont_sortBy_proportionalGlyphs() 157 font4 = self.getFont_sortBy_proportionalGlyphs() 158 fonts = FontList() 159 fonts.extend([font1, font2, font3, font4]) 160 fonts.reverse() 161 fonts.sortBy("isMonospace") 162 expected = [font2, font1, font4, font3] 163 self.assertEqual(fonts, expected) 164 165 # isProportional 166 167 def test_sortBy_isProportional_postscriptIsFixedPitch(self): 168 fonts = self.getFonts_sortBy( 169 "postscriptIsFixedPitch", 170 [False, False, True, True] 171 ) 172 font1, font2, font3, font4 = fonts 173 fonts.reverse() 174 fonts.sortBy("isProportional") 175 expected = [font2, font1, font4, font3] 176 self.assertEqual(fonts, expected) 177 178 def test_sortBy_isProportional_glyphs(self): 179 font1 = self.getFont_sortBy_monospaceGlyphs() 180 font2 = self.getFont_sortBy_monospaceGlyphs() 181 font3 = self.getFont_sortBy_proportionalGlyphs() 182 font4 = self.getFont_sortBy_proportionalGlyphs() 183 fonts = FontList() 184 fonts.extend([font1, font2, font3, font4]) 185 fonts.sortBy("isProportional") 186 expected = [font3, font4, font1, font2] 187 self.assertEqual(fonts, expected) 188 189 # font.info Attributes 190 191 def test_sortBy_fontInfoAttribute_xHeight(self): 192 fonts = self.getFonts_sortBy( 193 "xHeight", 194 [10, 20, 30, 40] 195 ) 196 font1, font2, font3, font4 = fonts 197 fonts.reverse() 198 fonts.sortBy("xHeight") 199 expected = [font1, font2, font3, font4] 200 self.assertEqual(fonts, expected) 201 202 # Sort Value Function 203 # ------------------- 204 205 def getFont_withGlyphCount(self, count): 206 font = self.getFont() 207 for i in range(count): 208 font.newGlyph("glyph%d" % i) 209 font.info.familyName = str(count) 210 return font 211 212 def test_sortBy_sortValueFunction(self): 213 font1 = self.getFont_withGlyphCount(10) 214 font2 = self.getFont_withGlyphCount(20) 215 font3 = self.getFont_withGlyphCount(30) 216 font4 = self.getFont_withGlyphCount(40) 217 fonts = FontList() 218 fonts.extend([font1, font2, font3, font4]) 219 fonts.reverse() 220 def glyphCountSortValue(font): 221 return len(font) 222 fonts.sortBy(glyphCountSortValue) 223 expected = [font1, font2, font3, font4] 224 self.assertEqual(fonts, expected) 225 226 227 # ------ 228 # Search 229 # ------ 230 231 # family name 232 233 def test_getFontsByFamilyName(self): 234 font1 = self.getFont() 235 font1.info.familyName = "A" 236 font2 = self.getFont() 237 font2.info.familyName = "B" 238 font3 = self.getFont() 239 font3.info.familyName = "C" 240 font4 = self.getFont() 241 font4.info.familyName = "A" 242 fonts = FontList() 243 fonts.extend([font1, font2, font3, font4]) 244 found = fonts.getFontsByFamilyName("A") 245 self.assertEqual(found, [font1, font4]) 246 247 # style name 248 249 def test_getFontsByStyleName(self): 250 font1 = self.getFont() 251 font1.info.styleName = "A" 252 font2 = self.getFont() 253 font2.info.styleName = "B" 254 font3 = self.getFont() 255 font3.info.styleName = "C" 256 font4 = self.getFont() 257 font4.info.styleName = "A" 258 fonts = FontList() 259 fonts.extend([font1, font2, font3, font4]) 260 found = fonts.getFontsByStyleName("A") 261 self.assertEqual(found, [font1, font4]) 262 263 # family name, style name 264 265 def test_getFontsByFamilyNameStyleName(self): 266 font1 = self.getFont() 267 font1.info.familyName = "A" 268 font1.info.styleName = "1" 269 font2 = self.getFont() 270 font2.info.familyName = "A" 271 font2.info.styleName = "2" 272 font3 = self.getFont() 273 font3.info.familyName = "B" 274 font3.info.styleName = "1" 275 font4 = self.getFont() 276 font4.info.familyName = "A" 277 font4.info.styleName = "1" 278 fonts = FontList() 279 fonts.extend([font1, font2, font3, font4]) 280 found = fonts.getFontsByFamilyNameStyleName("A", "1") 281 self.assertEqual(found, [font1, font4]) 282 283class TestFontOpen(unittest.TestCase): 284 285 def setUp(self): 286 font, _ = self.objectGenerator("font") 287 self.font_dir = tempfile.mkdtemp() 288 self.font_path = os.path.join(self.font_dir, "test.ufo") 289 font.save(self.font_path) 290 291 def tearDown(self): 292 import shutil 293 shutil.rmtree(self.font_dir) 294 295 def test_font_open(self): 296 OpenFont(self.font_path) 297 298 299class TestFontShell_RFont(unittest.TestCase): 300 301 def test_fontshell_RFont_empty(self): 302 RFont() 303