189 lines
6.8 KiB
Python
189 lines
6.8 KiB
Python
import io
|
|
import os
|
|
import re
|
|
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())
|