from __future__ import print_function, division, absolute_import, unicode_literals
import io
import os
import re
from fontTools.misc.py23 import *
from fontTools import ttLib
from fontTools.fontBuilder import FontBuilder
import unittest
from fontTools.ttLib.tables._c_m_a_p import CmapSubtable, table__c_m_a_p

CURR_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
DATA_DIR = os.path.join(CURR_DIR, 'data')
CMAP_FORMAT_14_TTX = os.path.join(DATA_DIR, "_c_m_a_p_format_14.ttx")
CMAP_FORMAT_14_BW_COMPAT_TTX = os.path.join(DATA_DIR, "_c_m_a_p_format_14_bw_compat.ttx")

def strip_VariableItems(string):
    # ttlib changes with the fontTools version
    string = re.sub(' ttLibVersion=".*"', '', string)
    return string

class CmapSubtableTest(unittest.TestCase):

	def makeSubtable(self, cmapFormat, platformID, platEncID, langID):
		subtable = CmapSubtable.newSubtable(cmapFormat)
		subtable.platformID, subtable.platEncID, subtable.language = (platformID, platEncID, langID)
		return subtable

	def test_toUnicode_utf16be(self):
		subtable = self.makeSubtable(4, 0, 2, 7)
		self.assertEqual("utf_16_be", subtable.getEncoding())
		self.assertEqual(True, subtable.isUnicode())

	def test_toUnicode_macroman(self):
		subtable = self.makeSubtable(4, 1, 0, 7)  # MacRoman
		self.assertEqual("mac_roman", subtable.getEncoding())
		self.assertEqual(False, subtable.isUnicode())

	def test_toUnicode_macromanian(self):
		subtable = self.makeSubtable(4, 1, 0, 37)  # Mac Romanian
		self.assertNotEqual(None, subtable.getEncoding())
		self.assertEqual(False, subtable.isUnicode())

	def test_extended_mac_encodings(self):
		subtable = self.makeSubtable(4, 1, 1, 0) # Mac Japanese
		self.assertNotEqual(None, subtable.getEncoding())
		self.assertEqual(False, subtable.isUnicode())

	def test_extended_unknown(self):
		subtable = self.makeSubtable(4, 10, 11, 12)
		self.assertEqual(subtable.getEncoding(), None)
		self.assertEqual(subtable.getEncoding("ascii"), "ascii")
		self.assertEqual(subtable.getEncoding(default="xyz"), "xyz")

	def test_compile_2(self):
		subtable = self.makeSubtable(2, 1, 2, 0)
		subtable.cmap = {c: "cid%05d" % c for c in range(32, 8192)}
		font = ttLib.TTFont()
		font.setGlyphOrder([".notdef"] + list(subtable.cmap.values()))
		data = subtable.compile(font)

		subtable2 = CmapSubtable.newSubtable(2)
		subtable2.decompile(data, font)
		self.assertEqual(subtable2.cmap, subtable.cmap)

	def test_compile_2_rebuild_rev_glyph_order(self):
		for fmt in [2, 4, 12]:
			subtable = self.makeSubtable(fmt, 1, 2, 0)
			subtable.cmap = {c: "cid%05d" % c for c in range(32, 8192)}
			font = ttLib.TTFont()
			font.setGlyphOrder([".notdef"] + list(subtable.cmap.values()))
			font._reverseGlyphOrderDict = {}  # force first KeyError branch in subtable.compile()
			data = subtable.compile(font)
			subtable2 = CmapSubtable.newSubtable(fmt)
			subtable2.decompile(data, font)
			self.assertEqual(subtable2.cmap, subtable.cmap, str(fmt))

	def test_compile_2_gids(self):
		for fmt in [2, 4, 12]:
			subtable = self.makeSubtable(fmt, 1, 3, 0)
			subtable.cmap = {0x0041:'gid001', 0x0042:'gid002'}
			font = ttLib.TTFont()
			font.setGlyphOrder([".notdef"])
			data = subtable.compile(font)

	def test_compile_decompile_4_empty(self):
		subtable = self.makeSubtable(4, 3, 1, 0)
		subtable.cmap = {}
		font = ttLib.TTFont()
		font.setGlyphOrder([])
		data = subtable.compile(font)
		subtable2 = CmapSubtable.newSubtable(4)
		subtable2.decompile(data, font)
		self.assertEqual(subtable2.cmap, {})

	def test_decompile_4(self):
		subtable = CmapSubtable.newSubtable(4)
		font = ttLib.TTFont()
		font.setGlyphOrder([])
		subtable.decompile(b'\0' * 3 + b'\x10' + b'\0' * 12, font)

	def test_decompile_12(self):
		subtable = CmapSubtable.newSubtable(12)
		font = ttLib.TTFont()
		font.setGlyphOrder([])
		subtable.decompile(b'\0' * 7 + b'\x10' + b'\0' * 8, font)

	def test_buildReversed(self):
		c4 = self.makeSubtable(4, 3, 1, 0)
		c4.cmap = {0x0041:'A', 0x0391:'A'}
		c12 = self.makeSubtable(12, 3, 10, 0)
		c12.cmap = {0x10314: 'u10314'}
		cmap = table__c_m_a_p()
		cmap.tables = [c4, c12]
		self.assertEqual(cmap.buildReversed(), {'A':{0x0041, 0x0391}, 'u10314':{0x10314}})

	def test_getBestCmap(self):
		c4 = self.makeSubtable(4, 3, 1, 0)
		c4.cmap = {0x0041:'A', 0x0391:'A'}
		c12 = self.makeSubtable(12, 3, 10, 0)
		c12.cmap = {0x10314: 'u10314'}
		cmap = table__c_m_a_p()
		cmap.tables = [c4, c12]
		self.assertEqual(cmap.getBestCmap(), {0x10314: 'u10314'})
		self.assertEqual(cmap.getBestCmap(cmapPreferences=[(3, 1)]), {0x0041:'A', 0x0391:'A'})
		self.assertEqual(cmap.getBestCmap(cmapPreferences=[(0, 4)]), None)

	def test_font_getBestCmap(self):
		c4 = self.makeSubtable(4, 3, 1, 0)
		c4.cmap = {0x0041:'A', 0x0391:'A'}
		c12 = self.makeSubtable(12, 3, 10, 0)
		c12.cmap = {0x10314: 'u10314'}
		cmap = table__c_m_a_p()
		cmap.tables = [c4, c12]
		font = ttLib.TTFont()
		font["cmap"] = cmap
		self.assertEqual(font.getBestCmap(), {0x10314: 'u10314'})
		self.assertEqual(font.getBestCmap(cmapPreferences=[(3, 1)]), {0x0041:'A', 0x0391:'A'})
		self.assertEqual(font.getBestCmap(cmapPreferences=[(0, 4)]), None)

	def test_format_14(self):
		subtable = self.makeSubtable(14, 0, 5, 0)
		subtable.cmap = {}  # dummy
		subtable.uvsDict = {
			0xFE00: [(0x0030, "zero.slash")],
			0xFE01: [(0x0030, None)],
		}
		fb = FontBuilder(1024, isTTF=True)
		font = fb.font
		fb.setupGlyphOrder([".notdef", "zero.slash"])
		fb.setupMaxp()
		fb.setupPost()
		cmap = table__c_m_a_p()
		cmap.tableVersion = 0
		cmap.tables = [subtable]
		font["cmap"] = cmap
		f = io.BytesIO()
		font.save(f)
		f.seek(0)
		font = ttLib.TTFont(f)
		self.assertEqual(font["cmap"].getcmap(0, 5).uvsDict, subtable.uvsDict)
		f = io.StringIO(newline=None)
		font.saveXML(f, tables=["cmap"])
		ttx = strip_VariableItems(f.getvalue())
		with open(CMAP_FORMAT_14_TTX) as f:
			expected = strip_VariableItems(f.read())
		self.assertEqual(ttx, expected)
		with open(CMAP_FORMAT_14_BW_COMPAT_TTX) as f:
			font.importXML(f)
		self.assertEqual(font["cmap"].getcmap(0, 5).uvsDict, subtable.uvsDict)


if __name__ == "__main__":
	import sys
	sys.exit(unittest.main())
