19d7dc222990efdab0681ce7c519ef3a73d3fd718Behdad Esfahbod# Copyright 2013 Google, Inc. All Rights Reserved.
29d7dc222990efdab0681ce7c519ef3a73d3fd718Behdad Esfahbod#
39d7dc222990efdab0681ce7c519ef3a73d3fd718Behdad Esfahbod# Google Author(s): Behdad Esfahbod
49d7dc222990efdab0681ce7c519ef3a73d3fd718Behdad Esfahbod
51ae29591efbb29492ce05378909ccf4028d7c1eeBehdad Esfahbodfrom __future__ import print_function, division, absolute_import
630e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom fontTools.misc.py23 import *
730e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom fontTools.misc.textTools import safeEval
82b06aaa2a6bcd363c25fb0c43f6bb906906594bdBehdad Esfahbodfrom . import DefaultTable
950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbodimport struct
1050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
1150d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
1250d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbodclass table_C_P_A_L_(DefaultTable.DefaultTable):
1350d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
1450d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod	def decompile(self, data, ttFont):
1550d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.version, self.numPaletteEntries, numPalettes, numColorRecords, goffsetFirstColorRecord = struct.unpack(">HHHHL", data[:12])
1650d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		assert (self.version == 0), "Version of COLR table is higher than I know how to handle"
1750d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.palettes = []
1850d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		pos = 12
1950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		for i in range(numPalettes):
2050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			startIndex = struct.unpack(">H", data[pos:pos+2])[0]
2150d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			assert (startIndex + self.numPaletteEntries <= numColorRecords)
2250d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			pos += 2
2350d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			palette = []
2450d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			ppos = goffsetFirstColorRecord + startIndex * 4
2550d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			for j in range(self.numPaletteEntries):
2650d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod				palette.append( Color(*struct.unpack(">BBBB", data[ppos:ppos+4])) )
2750d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod				ppos += 4
2850d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			self.palettes.append(palette)
2950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
3050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod	def compile(self, ttFont):
3150d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		dataList = [struct.pack(">HHHHL", self.version, self.numPaletteEntries, len(self.palettes), self.numPaletteEntries * len(self.palettes), 12+2*len(self.palettes))]
3250d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		for i in range(len(self.palettes)):
3350d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			dataList.append(struct.pack(">H", i*self.numPaletteEntries))
3450d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		for palette in self.palettes:
3550d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			assert(len(palette) == self.numPaletteEntries)
3650d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			for color in palette:
3750d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod				dataList.append(struct.pack(">BBBB", color.blue,color.green,color.red,color.alpha))
3818316aa769566eeb6f3f4a6ed2685fa8f8e861c2Behdad Esfahbod		data = bytesjoin(dataList)
3950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		return data
4050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
4150d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod	def toXML(self, writer, ttFont):
4250d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		writer.simpletag("version", value=self.version)
4350d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		writer.newline()
4450d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		writer.simpletag("numPaletteEntries", value=self.numPaletteEntries)
4550d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		writer.newline()
4650d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		for index, palette in enumerate(self.palettes):
4750d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			writer.begintag("palette", index=index)
4850d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			writer.newline()
4950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			assert(len(palette) == self.numPaletteEntries)
5050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			for cindex, color in enumerate(palette):
5150d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod				color.toXML(writer, ttFont, cindex)
5250d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			writer.endtag("palette")
5350d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			writer.newline()
5450d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
553a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod	def fromXML(self, name, attrs, content, ttFont):
5650d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		if not hasattr(self, "palettes"):
5750d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			self.palettes = []
5850d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		if name == "palette":
5950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			palette = []
6050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			for element in content:
61faaca764a1cd62d376f783df20cd1edce21ca816Behdad Esfahbod				if isinstance(element, basestring):
6250d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod					continue
6350d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			palette = []
6450d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			for element in content:
65faaca764a1cd62d376f783df20cd1edce21ca816Behdad Esfahbod				if isinstance(element, basestring):
6650d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod					continue
6750d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod				color = Color()
683a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod				color.fromXML(element[0], element[1], element[2], ttFont)
6950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod				palette.append (color)
7050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			self.palettes.append(palette)
71bc5e1cb195c0bfa1c8e7507326d5a9ad05aecb4bBehdad Esfahbod		elif "value" in attrs:
7250d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			value =  safeEval(attrs["value"])
7350d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			setattr(self, name, value)
7450d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
75e388db566b9ba42669c7e353db4293cf27bc2a5bBehdad Esfahbodclass Color(object):
7650d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
7750d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod	def __init__(self, blue=None, green=None, red=None, alpha=None):
7850d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.blue  = blue
7950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.green = green
8050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.red   = red
8150d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.alpha = alpha
8250d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
8350d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod	def hex(self):
8450d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		return "#%02X%02X%02X%02X" % (self.red, self.green, self.blue, self.alpha)
8550d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
8650d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod	def __repr__(self):
8750d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		return self.hex()
8850d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
8950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod	def toXML(self, writer, ttFont, index=None):
9050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		writer.simpletag("color", value=self.hex(), index=index)
9150d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		writer.newline()
9250d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod
933a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod	def fromXML(self, eltname, attrs, content, ttFont):
9450d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		value = attrs["value"]
9550d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		if value[0] == '#':
9650d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod			value = value[1:]
9750d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.red   = int(value[0:2], 16)
9850d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.green = int(value[2:4], 16)
9950d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.blue  = int(value[4:6], 16)
10050d9a44e5887e303480af571cca8b69cd82c3173Behdad Esfahbod		self.alpha = int(value[6:8], 16) if len (value) >= 8 else 0xFF
101