1from __future__ import print_function, division, absolute_import
2from fontTools.misc.py23 import *
3from fontTools.misc.testTools import getXML, parseXML
4from fontTools.misc.textTools import deHexStr
5from fontTools.ttLib import getTableModule, newTable
6import unittest
7
8
9CPAL_DATA_V0 = deHexStr(
10    '0000 0002 '          # version=0, numPaletteEntries=2
11    '0002 0004 '          # numPalettes=2, numColorRecords=4
12    '00000010 '           # offsetToFirstColorRecord=16
13    '0000 0002 '          # colorRecordIndex=[0, 2]
14    '000000FF FFCC66FF '  # colorRecord #0, #1 (blue/green/red/alpha)
15    '000000FF 000080FF')  # colorRecord #2, #3
16
17
18CPAL_DATA_V0_SHARING_COLORS = deHexStr(
19    '0000 0003 '                   # version=0, numPaletteEntries=3
20    '0004 0006 '                   # numPalettes=4, numColorRecords=6
21    '00000014 '                    # offsetToFirstColorRecord=20
22    '0000 0000 0003 0000 '         # colorRecordIndex=[0, 0, 3, 0]
23    '443322FF 77889911 55555555 '  # colorRecord #0, #1, #2 (BGRA)
24    '443322FF 77889911 FFFFFFFF')  # colorRecord #3, #4, #5
25
26
27CPAL_DATA_V1_NOLABELS_NOTYPES = deHexStr(
28    '0001 0003 '                   # version=1, numPaletteEntries=3
29    '0002 0006 '                   # numPalettes=2, numColorRecords=6
30    '0000001C  '                   # offsetToFirstColorRecord=28
31    '0000 0003 '                   # colorRecordIndex=[0, 3]
32    '00000000  '                   # offsetToPaletteTypeArray=0
33    '00000000  '                   # offsetToPaletteLabelArray=0
34    '00000000  '                   # offsetToPaletteEntryLabelArray=0
35    'CAFECAFE 00112233 44556677 '  # colorRecord #0, #1, #2 (BGRA)
36    '31415927 42424242 00331337')  # colorRecord #3, #4, #5
37
38
39CPAL_DATA_V1 = deHexStr(
40    '0001 0003 '                   # version=1, numPaletteEntries=3
41    '0002 0006 '                   # numPalettes=2, numColorRecords=6
42    '0000001C  '                   # offsetToFirstColorRecord=28
43    '0000 0003 '                   # colorRecordIndex=[0, 3]
44    '00000034  '                   # offsetToPaletteTypeArray=52
45    '0000003C  '                   # offsetToPaletteLabelArray=60
46    '00000040  '                   # offsetToPaletteEntryLabelArray=64
47    'CAFECAFE 00112233 44556677 '  # colorRecord #0, #1, #2 (BGRA)
48    '31415927 42424242 00331337 '  # colorRecord #3, #4, #5
49    '00000001 00000002 '           # paletteType=[1, 2]
50    '0102 0103 '                   # paletteLabel=[258, 259]
51    '0201 0202 0203')              # paletteEntryLabel=[513, 514, 515]
52
53
54class FakeNameTable(object):
55    def __init__(self, names):
56        self.names = names
57
58    def getDebugName(self, nameID):
59        return self.names.get(nameID)
60
61
62class CPALTest(unittest.TestCase):
63    def test_decompile_v0(self):
64        cpal = newTable('CPAL')
65        cpal.decompile(CPAL_DATA_V0, ttFont=None)
66        self.assertEqual(cpal.version, 0)
67        self.assertEqual(cpal.numPaletteEntries, 2)
68        self.assertEqual(repr(cpal.palettes),
69                         '[[#000000FF, #66CCFFFF], [#000000FF, #800000FF]]')
70        self.assertEqual(cpal.paletteLabels, [0, 0])
71        self.assertEqual(cpal.paletteTypes, [0, 0])
72        self.assertEqual(cpal.paletteEntryLabels, [0, 0])
73
74    def test_decompile_v0_sharingColors(self):
75        cpal = newTable('CPAL')
76        cpal.decompile(CPAL_DATA_V0_SHARING_COLORS, ttFont=None)
77        self.assertEqual(cpal.version, 0)
78        self.assertEqual(cpal.numPaletteEntries, 3)
79        self.assertEqual([repr(p) for p in cpal.palettes], [
80            '[#223344FF, #99887711, #55555555]',
81            '[#223344FF, #99887711, #55555555]',
82            '[#223344FF, #99887711, #FFFFFFFF]',
83            '[#223344FF, #99887711, #55555555]'])
84        self.assertEqual(cpal.paletteLabels, [0, 0, 0, 0])
85        self.assertEqual(cpal.paletteTypes, [0, 0, 0, 0])
86        self.assertEqual(cpal.paletteEntryLabels, [0, 0, 0])
87
88    def test_decompile_v1_noLabelsNoTypes(self):
89        cpal = newTable('CPAL')
90        cpal.decompile(CPAL_DATA_V1_NOLABELS_NOTYPES, ttFont=None)
91        self.assertEqual(cpal.version, 1)
92        self.assertEqual(cpal.numPaletteEntries, 3)
93        self.assertEqual([repr(p) for p in cpal.palettes], [
94            '[#CAFECAFE, #22110033, #66554477]',  # RGBA
95            '[#59413127, #42424242, #13330037]'])
96        self.assertEqual(cpal.paletteLabels, [0, 0])
97        self.assertEqual(cpal.paletteTypes, [0, 0])
98        self.assertEqual(cpal.paletteEntryLabels, [0, 0, 0])
99
100    def test_decompile_v1(self):
101        cpal = newTable('CPAL')
102        cpal.decompile(CPAL_DATA_V1, ttFont=None)
103        self.assertEqual(cpal.version, 1)
104        self.assertEqual(cpal.numPaletteEntries, 3)
105        self.assertEqual([repr(p) for p in cpal.palettes], [
106            '[#CAFECAFE, #22110033, #66554477]',  # RGBA
107            '[#59413127, #42424242, #13330037]'])
108        self.assertEqual(cpal.paletteTypes, [1, 2])
109        self.assertEqual(cpal.paletteLabels, [258, 259])
110        self.assertEqual(cpal.paletteEntryLabels, [513, 514, 515])
111
112    def test_compile_v0(self):
113        cpal = newTable('CPAL')
114        cpal.decompile(CPAL_DATA_V0, ttFont=None)
115        self.assertEqual(cpal.compile(ttFont=None), CPAL_DATA_V0)
116
117    def test_compile_v0_sharingColors(self):
118        cpal = newTable('CPAL')
119        cpal.version = 0
120        Color = getTableModule('CPAL').Color
121        palette1 = [Color(red=0x22, green=0x33, blue=0x44, alpha=0xff),
122                    Color(red=0x99, green=0x88, blue=0x77, alpha=0x11),
123                    Color(red=0x55, green=0x55, blue=0x55, alpha=0x55)]
124        palette2 = [Color(red=0x22, green=0x33, blue=0x44, alpha=0xff),
125                    Color(red=0x99, green=0x88, blue=0x77, alpha=0x11),
126                    Color(red=0xFF, green=0xFF, blue=0xFF, alpha=0xFF)]
127        cpal.numPaletteEntries = len(palette1)
128        cpal.palettes = [palette1, palette1, palette2, palette1]
129        self.assertEqual(cpal.compile(ttFont=None),
130                         CPAL_DATA_V0_SHARING_COLORS)
131
132    def test_compile_v1(self):
133        cpal = newTable('CPAL')
134        cpal.decompile(CPAL_DATA_V1, ttFont=None)
135        self.assertEqual(cpal.compile(ttFont=None), CPAL_DATA_V1)
136
137    def test_compile_v1_noLabelsNoTypes(self):
138        cpal = newTable('CPAL')
139        cpal.decompile(CPAL_DATA_V1_NOLABELS_NOTYPES, ttFont=None)
140        self.assertEqual(cpal.compile(ttFont=None),
141                         CPAL_DATA_V1_NOLABELS_NOTYPES)
142
143    def test_toXML_v0(self):
144        cpal = newTable('CPAL')
145        cpal.decompile(CPAL_DATA_V0, ttFont=None)
146        self.assertEqual(getXML(cpal.toXML),
147                         ['<version value="0"/>',
148                          '<numPaletteEntries value="2"/>',
149                          '<palette index="0">',
150                          '  <color index="0" value="#000000FF"/>',
151                          '  <color index="1" value="#66CCFFFF"/>',
152                          '</palette>',
153                          '<palette index="1">',
154                          '  <color index="0" value="#000000FF"/>',
155                          '  <color index="1" value="#800000FF"/>',
156                          '</palette>'])
157
158    def test_toXML_v1(self):
159        name = FakeNameTable({258: "Spring theme", 259: "Winter theme",
160                              513: "darks", 515: "lights"})
161        cpal = newTable('CPAL')
162        ttFont = {"name": name, "CPAL": cpal}
163        cpal.decompile(CPAL_DATA_V1, ttFont)
164        self.assertEqual(getXML(cpal.toXML, ttFont),
165                         ['<version value="1"/>',
166                          '<numPaletteEntries value="3"/>',
167                          '<palette index="0" label="258" type="1">',
168                          '  <!-- Spring theme -->',
169                          '  <color index="0" value="#CAFECAFE"/>',
170                          '  <color index="1" value="#22110033"/>',
171                          '  <color index="2" value="#66554477"/>',
172                          '</palette>',
173                          '<palette index="1" label="259" type="2">',
174                          '  <!-- Winter theme -->',
175                          '  <color index="0" value="#59413127"/>',
176                          '  <color index="1" value="#42424242"/>',
177                          '  <color index="2" value="#13330037"/>',
178                          '</palette>',
179                          '<paletteEntryLabels>',
180                          '  <label index="0" value="513"/><!-- darks -->',
181                          '  <label index="1" value="514"/>',
182                          '  <label index="2" value="515"/><!-- lights -->',
183                          '</paletteEntryLabels>'])
184
185    def test_fromXML_v0(self):
186        cpal = newTable('CPAL')
187        for name, attrs, content in parseXML(
188                '<version value="0"/>'
189                '<numPaletteEntries value="2"/>'
190                '<palette index="0">'
191                '  <color index="0" value="#12345678"/>'
192                '  <color index="1" value="#FEDCBA98"/>'
193                '</palette>'):
194            cpal.fromXML(name, attrs, content, ttFont=None)
195        self.assertEqual(cpal.version, 0)
196        self.assertEqual(cpal.numPaletteEntries, 2)
197        self.assertEqual(repr(cpal.palettes), '[[#12345678, #FEDCBA98]]')
198        self.assertEqual(cpal.paletteLabels, [0])
199        self.assertEqual(cpal.paletteTypes, [0])
200        self.assertEqual(cpal.paletteEntryLabels, [0, 0])
201
202    def test_fromXML_v1(self):
203        cpal = newTable('CPAL')
204        for name, attrs, content in parseXML(
205                '<version value="1"/>'
206                '<numPaletteEntries value="3"/>'
207                '<palette index="0" label="259" type="2">'
208                '  <color index="0" value="#12345678"/>'
209                '  <color index="1" value="#FEDCBA98"/>'
210                '  <color index="2" value="#CAFECAFE"/>'
211                '</palette>'
212                '<paletteEntryLabels>'
213                '  <label index="1" value="262"/>'
214                '</paletteEntryLabels>'):
215            cpal.fromXML(name, attrs, content, ttFont=None)
216        self.assertEqual(cpal.version, 1)
217        self.assertEqual(cpal.numPaletteEntries, 3)
218        self.assertEqual(repr(cpal.palettes),
219                         '[[#12345678, #FEDCBA98, #CAFECAFE]]')
220        self.assertEqual(cpal.paletteLabels, [259])
221        self.assertEqual(cpal.paletteTypes, [2])
222        self.assertEqual(cpal.paletteEntryLabels, [0, 262, 0])
223
224
225if __name__ == "__main__":
226    import sys
227    sys.exit(unittest.main())
228