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