diff --git a/Lib/fontTools/cffLib/__init__.py b/Lib/fontTools/cffLib/__init__.py index 3c5f36df2..e9065407e 100644 --- a/Lib/fontTools/cffLib/__init__.py +++ b/Lib/fontTools/cffLib/__init__.py @@ -831,6 +831,23 @@ class FDSelect(object): for glyphID in range(prev, first): gidArray[glyphID] = fd self.gidArray = gidArray + elif self.format == 4: + gidArray = [None] * numGlyphs + nRanges = readCard32(file) + fd = None + prev = None + for i in range(nRanges): + first = readCard32(file) + if prev is not None: + for glyphID in range(prev, first): + gidArray[glyphID] = fd + prev = first + fd = readCard16(file) + if prev is not None: + first = readCard32(file) + for glyphID in range(prev, first): + gidArray[glyphID] = fd + self.gidArray = gidArray else: assert False, "unsupported FDSelect format: %s" % format else: @@ -1001,6 +1018,10 @@ def packCard16(value): return struct.pack(">H", value) +def packCard32(value): + return struct.pack(">L", value) + + def buildOperatorDict(table): d = {} for op, name, arg, default, conv in table: @@ -1732,6 +1753,27 @@ def packFDSelect3(fdSelectArray): return bytesjoin(data) +def packFDSelect4(fdSelectArray): + fmt = 4 + fdRanges = [] + lenArray = len(fdSelectArray) + lastFDIndex = -1 + for i in range(lenArray): + fdIndex = fdSelectArray[i] + if lastFDIndex != fdIndex: + fdRanges.append([i, fdIndex]) + lastFDIndex = fdIndex + sentinelGID = i + 1 + + data = [packCard8(fmt)] + data.append(packCard32(len(fdRanges))) + for fdRange in fdRanges: + data.append(packCard32(fdRange[0])) + data.append(packCard16(fdRange[1])) + data.append(packCard32(sentinelGID)) + return bytesjoin(data) + + class FDSelectCompiler(object): def __init__(self, fdSelect, parent): @@ -1741,6 +1783,8 @@ class FDSelectCompiler(object): self.data = packFDSelect0(fdSelectArray) elif fmt == 3: self.data = packFDSelect3(fdSelectArray) + elif fmt == 4: + self.data = packFDSelect4(fdSelectArray) else: # choose smaller of the two formats data0 = packFDSelect0(fdSelectArray) diff --git a/Tests/cffLib/cffLib_test.py b/Tests/cffLib/cffLib_test.py index cc28e4e9b..cc9d33654 100644 --- a/Tests/cffLib/cffLib_test.py +++ b/Tests/cffLib/cffLib_test.py @@ -79,6 +79,20 @@ class CffLibTest(DataFilesHandler): font.importXML(ttx_path) copy.deepcopy(font) + def test_FDSelect_format_4(self): + ttx_path = self.getpath('TestFDSelect4.ttx') + font = TTFont(recalcBBoxes=False, recalcTimestamp=False) + font.importXML(ttx_path) + + self.temp_dir() + save_path = os.path.join(self.tempdir, 'TestOTF.otf') + font.save(save_path) + + font2 = TTFont(save_path) + topDict2 = font2["CFF2"].cff.topDictIndex[0] + self.assertEqual(topDict2.FDSelect.format, 4) + self.assertEqual(topDict2.FDSelect.gidArray, [0, 0, 1]) + if __name__ == "__main__": sys.exit(unittest.main()) diff --git a/Tests/cffLib/data/TestFDSelect4.ttx b/Tests/cffLib/data/TestFDSelect4.ttx new file mode 100644 index 000000000..f80c8a129 --- /dev/null +++ b/Tests/cffLib/data/TestFDSelect4.ttx @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copyright © 2015-2019 The Mada Project Authors, with Reserved Font Name “Source”. + + + Mada Medium + + + Mada-Medium + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 hmoveto + 103 hlineto + 107 357 22 71 20 73 19 74 rlinecurve + 4 hlineto + 20 -74 20 -73 22 -71 rrcurveto + 106 -357 108 0 -217 655 rlineto + -117 hlineto + -96 -467 rmoveto + 306 hlineto + 0 80 rlineto + -306 hlineto + + + 193 -12 rmoveto + 60 52 30 38 45 hvcurveto + 3 hlineto + 8 -56 82 0 0 294 rlineto + 130 0 -56 77 -121 hhcurveto + -78 -69 -32 -32 -50 hvcurveto + 38 -68 rlineto + 26 41 48 24 52 hhcurveto + 73 20 -51 -57 1 hvcurveto + -204 -22 -89 -54 0 -106 rrcurveto + -86 0 60 -55 84 hhcurveto + 31 79 rmoveto + -44 -34 21 49 0 hvcurveto + 0 55 50 37 146 18 0 -122 rcurveline + -38 -41 -34 -21 -43 hhcurveto + + + + + + + + + +