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