From 9fed95216a963b6ef4733d68a691f0ac965b120d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 May 2014 15:54:04 -0400 Subject: Fix rangeShift calculations for count=0 in sfnt, cmap, and kern --- Lib/fontTools/ttLib/sfnt.py | 2 +- Lib/fontTools/ttLib/tables/_c_m_a_p.py | 2 +- Lib/fontTools/ttLib/tables/_k_e_r_n.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/fontTools/ttLib/sfnt.py b/Lib/fontTools/ttLib/sfnt.py index c6bc93a9..95679e99 100644 --- a/Lib/fontTools/ttLib/sfnt.py +++ b/Lib/fontTools/ttLib/sfnt.py @@ -483,7 +483,7 @@ def getSearchRange(n): exponent = maxPowerOfTwo(n) searchRange = (2 ** exponent) * 16 entrySelector = exponent - rangeShift = n * 16 - searchRange + rangeShift = max(0, n * 16 - searchRange) return searchRange, entrySelector, rangeShift diff --git a/Lib/fontTools/ttLib/tables/_c_m_a_p.py b/Lib/fontTools/ttLib/tables/_c_m_a_p.py index d0c6c41f..a3fb6ccc 100644 --- a/Lib/fontTools/ttLib/tables/_c_m_a_p.py +++ b/Lib/fontTools/ttLib/tables/_c_m_a_p.py @@ -781,7 +781,7 @@ class cmap_format_4(CmapSubtable): maxExponent = maxPowerOfTwo(segCount) searchRange = 2 * (2 ** maxExponent) entrySelector = maxExponent - rangeShift = 2 * segCount - searchRange + rangeShift = max(0, 2 * segCount - searchRange) charCodeArray = array.array("H", endCode + [0] + startCode) idDeltaArray = array.array("H", idDelta) diff --git a/Lib/fontTools/ttLib/tables/_k_e_r_n.py b/Lib/fontTools/ttLib/tables/_k_e_r_n.py index 9fa9dd85..b8e60d39 100644 --- a/Lib/fontTools/ttLib/tables/_k_e_r_n.py +++ b/Lib/fontTools/ttLib/tables/_k_e_r_n.py @@ -118,7 +118,7 @@ class KernTable_format_0(object): nPairs = len(self.kernTable) entrySelector = sfnt.maxPowerOfTwo(nPairs) searchRange = (2 ** entrySelector) * 6 - rangeShift = (nPairs - (2 ** entrySelector)) * 6 + rangeShift = max(0, (nPairs - (2 ** entrySelector)) * 6) data = struct.pack(">HHHH", nPairs, searchRange, entrySelector, rangeShift) # yeehee! (I mean, turn names into indices) -- cgit v1.2.3 From 62dd7b2a0e0ab1109b56572c568ef5f582d8a0fd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 May 2014 16:01:47 -0400 Subject: Refactor getSearchRange() --- Lib/fontTools/ttLib/__init__.py | 22 ++++++++++++++++++++++ Lib/fontTools/ttLib/sfnt.py | 28 +++------------------------- Lib/fontTools/ttLib/tables/_c_m_a_p.py | 10 +++------- Lib/fontTools/ttLib/tables/_k_e_r_n.py | 6 ++---- 4 files changed, 30 insertions(+), 36 deletions(-) diff --git a/Lib/fontTools/ttLib/__init__.py b/Lib/fontTools/ttLib/__init__.py index 1286765a..546b3271 100644 --- a/Lib/fontTools/ttLib/__init__.py +++ b/Lib/fontTools/ttLib/__init__.py @@ -966,3 +966,25 @@ def reorderFontTables(inFile, outFile, tableOrder=None, checkChecksums=False): for tag in sortedTagList(tables, tableOrder): writer[tag] = reader[tag] writer.close() + + +def maxPowerOfTwo(x): + """Return the highest exponent of two, so that + (2 ** exponent) <= x. Return 0 if x is 0. + """ + exponent = 0 + while x: + x = x >> 1 + exponent = exponent + 1 + return max(exponent - 1, 0) + + +def getSearchRange(n, itemSize): + """Calculate searchRange, entrySelector, rangeShift. + """ + # This stuff needs to be stored in the file, because? + exponent = maxPowerOfTwo(n) + searchRange = (2 ** exponent) * itemSize + entrySelector = exponent + rangeShift = max(0, n * itemSize - searchRange) + return searchRange, entrySelector, rangeShift diff --git a/Lib/fontTools/ttLib/sfnt.py b/Lib/fontTools/ttLib/sfnt.py index 95679e99..c65fd28d 100644 --- a/Lib/fontTools/ttLib/sfnt.py +++ b/Lib/fontTools/ttLib/sfnt.py @@ -15,6 +15,7 @@ a table's length chages you need to rewrite the whole file anyway. from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * from fontTools.misc import sstruct +from fontTools.ttLib import getSearchRange import struct @@ -116,7 +117,7 @@ class SFNTWriter(object): self.directorySize = sfntDirectorySize self.DirectoryEntry = SFNTDirectoryEntry - self.searchRange, self.entrySelector, self.rangeShift = getSearchRange(numTables) + self.searchRange, self.entrySelector, self.rangeShift = getSearchRange(numTables, 16) self.nextTableOffset = self.directorySize + numTables * self.DirectoryEntry.formatSize # clear out directory area @@ -242,7 +243,7 @@ class SFNTWriter(object): # Haven't debugged. if self.DirectoryEntry != SFNTDirectoryEntry: # Create a SFNT directory for checksum calculation purposes - self.searchRange, self.entrySelector, self.rangeShift = getSearchRange(self.numTables) + self.searchRange, self.entrySelector, self.rangeShift = getSearchRange(self.numTables, 16) directory = sstruct.pack(sfntDirectoryFormat, self) tables = sorted(self.tables.items()) for tag, entry in tables: @@ -464,29 +465,6 @@ def calcChecksum(data): return value -def maxPowerOfTwo(x): - """Return the highest exponent of two, so that - (2 ** exponent) <= x - """ - exponent = 0 - while x: - x = x >> 1 - exponent = exponent + 1 - return max(exponent - 1, 0) - - -def getSearchRange(n): - """Calculate searchRange, entrySelector, rangeShift for the - sfnt directory. 'n' is the number of tables. - """ - # This stuff needs to be stored in the file, because? - exponent = maxPowerOfTwo(n) - searchRange = (2 ** exponent) * 16 - entrySelector = exponent - rangeShift = max(0, n * 16 - searchRange) - return searchRange, entrySelector, rangeShift - - if __name__ == "__main__": import doctest doctest.testmod() diff --git a/Lib/fontTools/ttLib/tables/_c_m_a_p.py b/Lib/fontTools/ttLib/tables/_c_m_a_p.py index a3fb6ccc..0519e78b 100644 --- a/Lib/fontTools/ttLib/tables/_c_m_a_p.py +++ b/Lib/fontTools/ttLib/tables/_c_m_a_p.py @@ -1,6 +1,7 @@ from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * from fontTools.misc.textTools import safeEval, readHex +from fontTools.ttLib import getSearchRange from fontTools.unicode import Unicode from . import DefaultTable import sys @@ -699,8 +700,6 @@ class cmap_format_4(CmapSubtable): def compile(self, ttFont): if self.data: return struct.pack(">HHH", self.format, self.length, self.language) + self.data - - from fontTools.ttLib.sfnt import maxPowerOfTwo charCodes = list(self.cmap.keys()) lenCharCodes = len(charCodes) @@ -775,13 +774,10 @@ class cmap_format_4(CmapSubtable): idDelta.append(1) # 0xffff + 1 == (tadaa!) 0. So this end code maps to .notdef idRangeOffset.append(0) - # Insane. + # Insane. segCount = len(endCode) segCountX2 = segCount * 2 - maxExponent = maxPowerOfTwo(segCount) - searchRange = 2 * (2 ** maxExponent) - entrySelector = maxExponent - rangeShift = max(0, 2 * segCount - searchRange) + searchRange, entrySelector, rangeShift = getSearchRange(segCount, 2) charCodeArray = array.array("H", endCode + [0] + startCode) idDeltaArray = array.array("H", idDelta) diff --git a/Lib/fontTools/ttLib/tables/_k_e_r_n.py b/Lib/fontTools/ttLib/tables/_k_e_r_n.py index b8e60d39..928298bc 100644 --- a/Lib/fontTools/ttLib/tables/_k_e_r_n.py +++ b/Lib/fontTools/ttLib/tables/_k_e_r_n.py @@ -1,6 +1,6 @@ from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * -from fontTools.ttLib import sfnt +from fontTools.ttLib import getSearchRange from fontTools.misc.textTools import safeEval, readHex from fontTools.misc.fixedTools import fixedToFloat as fi2fl, floatToFixed as fl2fi from . import DefaultTable @@ -116,9 +116,7 @@ class KernTable_format_0(object): def compile(self, ttFont): nPairs = len(self.kernTable) - entrySelector = sfnt.maxPowerOfTwo(nPairs) - searchRange = (2 ** entrySelector) * 6 - rangeShift = max(0, (nPairs - (2 ** entrySelector)) * 6) + searchRange, entrySelector, rangeShift = getSearchRange(nPairs, 6) data = struct.pack(">HHHH", nPairs, searchRange, entrySelector, rangeShift) # yeehee! (I mean, turn names into indices) -- cgit v1.2.3