aboutsummaryrefslogtreecommitdiff
path: root/Tests/ttLib/tables/O_S_2f_2_test.py
blob: 71388560b568f882d3b8985a7cab99135783ea2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
from fontTools.ttLib import TTFont, newTable, getTableModule
from fontTools.ttLib.tables.O_S_2f_2 import *
import unittest


class OS2TableTest(unittest.TestCase):
    @staticmethod
    def makeOS2_cmap(mapping):
        font = TTFont()
        font["OS/2"] = os2 = newTable("OS/2")
        os2.version = 4
        font["cmap"] = cmap = newTable("cmap")
        st = getTableModule("cmap").CmapSubtable.newSubtable(4)
        st.platformID, st.platEncID, st.language = 3, 1, 0
        st.cmap = mapping
        cmap.tables = []
        cmap.tables.append(st)
        return font, os2, cmap

    def test_getUnicodeRanges(self):
        table = table_O_S_2f_2()
        table.ulUnicodeRange1 = 0xFFFFFFFF
        table.ulUnicodeRange2 = 0xFFFFFFFF
        table.ulUnicodeRange3 = 0xFFFFFFFF
        table.ulUnicodeRange4 = 0xFFFFFFFF
        bits = table.getUnicodeRanges()
        for i in range(127):
            self.assertIn(i, bits)

    def test_setUnicodeRanges(self):
        table = table_O_S_2f_2()
        table.ulUnicodeRange1 = 0
        table.ulUnicodeRange2 = 0
        table.ulUnicodeRange3 = 0
        table.ulUnicodeRange4 = 0
        bits = set(range(123))
        table.setUnicodeRanges(bits)
        self.assertEqual(table.getUnicodeRanges(), bits)
        with self.assertRaises(ValueError):
            table.setUnicodeRanges([-1, 127, 255])

    def test_recalcUnicodeRanges(self):
        font, os2, cmap = self.makeOS2_cmap(
            {0x0041: "A", 0x03B1: "alpha", 0x0410: "Acyr"}
        )
        os2.setUnicodeRanges({0, 1, 9})
        # 'pruneOnly' will clear any bits for which there's no intersection:
        # bit 1 ('Latin 1 Supplement'), in this case. However, it won't set
        # bit 7 ('Greek and Coptic') despite the "alpha" character is present.
        self.assertEqual(os2.recalcUnicodeRanges(font, pruneOnly=True), {0, 9})
        # try again with pruneOnly=False: bit 7 is now set.
        self.assertEqual(os2.recalcUnicodeRanges(font), {0, 7, 9})
        # add a non-BMP char from 'Mahjong Tiles' block (bit 122)
        cmap.tables[0].cmap[0x1F000] = "eastwindtile"
        # the bit 122 and the special bit 57 ('Non Plane 0') are also enabled
        self.assertEqual(os2.recalcUnicodeRanges(font), {0, 7, 9, 57, 122})

    def test_intersectUnicodeRanges(self):
        self.assertEqual(intersectUnicodeRanges([0x0410]), {9})
        self.assertEqual(intersectUnicodeRanges([0x0410, 0x1F000]), {9, 57, 122})
        self.assertEqual(
            intersectUnicodeRanges([0x0410, 0x1F000], inverse=True),
            (set(range(123)) - {9, 57, 122}),
        )

    def test_getCodePageRanges(self):
        table = table_O_S_2f_2()
        # version 0 doesn't define these fields so by definition defines no cp ranges
        table.version = 0
        self.assertEqual(table.getCodePageRanges(), set())
        # version 1 and above do contain ulCodePageRange1 and 2 fields
        table.version = 1
        table.ulCodePageRange1 = 0xFFFFFFFF
        table.ulCodePageRange2 = 0xFFFFFFFF
        bits = table.getCodePageRanges()
        for i in range(63):
            self.assertIn(i, bits)

    def test_setCodePageRanges(self):
        table = table_O_S_2f_2()
        table.version = 4
        table.ulCodePageRange1 = 0
        table.ulCodePageRange2 = 0
        bits = set(range(64))
        table.setCodePageRanges(bits)
        self.assertEqual(table.getCodePageRanges(), bits)
        with self.assertRaises(ValueError):
            table.setCodePageRanges([-1])
        with self.assertRaises(ValueError):
            table.setCodePageRanges([64])
        with self.assertRaises(ValueError):
            table.setCodePageRanges([255])

    def test_setCodePageRanges_bump_version(self):
        # Setting codepage ranges on a OS/2 table version 0 automatically makes it
        # a version 1 table
        table = table_O_S_2f_2()
        table.version = 0
        self.assertEqual(table.getCodePageRanges(), set())
        table.setCodePageRanges({0, 1, 2})
        self.assertEqual(table.getCodePageRanges(), {0, 1, 2})
        self.assertEqual(table.version, 1)

    def test_recalcCodePageRanges(self):
        font, os2, cmap = self.makeOS2_cmap(
            {ord("A"): "A", ord("Ά"): "Alphatonos", ord("Б"): "Be"}
        )
        os2.setCodePageRanges({0, 2, 9})

        # With pruneOnly=True, should clear any CodePage for which there are no
        # characters in the cmap.
        self.assertEqual(os2.recalcCodePageRanges(font, pruneOnly=True), {2})

        # With pruneOnly=False, should also set CodePages not initially set.
        self.assertEqual(os2.recalcCodePageRanges(font), {2, 3})

        # Add a Korean character, should set CodePage 21 (Korean Johab)
        cmap.tables[0].cmap[ord("곴")] = "goss"
        self.assertEqual(os2.recalcCodePageRanges(font), {2, 3, 21})

        # Remove all characters from cmap, should still set CodePage 0 (Latin 1)
        cmap.tables[0].cmap = {}
        self.assertEqual(os2.recalcCodePageRanges(font), {0})


if __name__ == "__main__":
    import sys

    sys.exit(unittest.main())