From 832f2f766fc94ab3e1bd246c007ab926c7ce519b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 25 May 2023 08:19:15 -0600 Subject: [PATCH] [varStore.optimize] Use faster intTools.bit_count as popcount --- Lib/fontTools/misc/intTools.py | 4 ++-- Lib/fontTools/varLib/featureVars.py | 4 ++-- Lib/fontTools/varLib/varStore.py | 13 ++++--------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Lib/fontTools/misc/intTools.py b/Lib/fontTools/misc/intTools.py index 6ba03e163..0ca29854a 100644 --- a/Lib/fontTools/misc/intTools.py +++ b/Lib/fontTools/misc/intTools.py @@ -1,4 +1,4 @@ -__all__ = ["popCount"] +__all__ = ["popCount", "bit_count", "bit_indices"] try: @@ -13,7 +13,7 @@ except AttributeError: See https://docs.python.org/3.10/library/stdtypes.html#int.bit_count """ -popCount = bit_count +popCount = bit_count # alias def bit_indices(v): diff --git a/Lib/fontTools/varLib/featureVars.py b/Lib/fontTools/varLib/featureVars.py index 7829fdcb8..f0403d76e 100644 --- a/Lib/fontTools/varLib/featureVars.py +++ b/Lib/fontTools/varLib/featureVars.py @@ -4,7 +4,7 @@ https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariat NOTE: The API is experimental and subject to change. """ from fontTools.misc.dictTools import hashdict -from fontTools.misc.intTools import popCount +from fontTools.misc.intTools import bit_count from fontTools.ttLib import newTable from fontTools.ttLib.tables import otTables as ot from fontTools.ttLib.ttVisitor import TTVisitor @@ -190,7 +190,7 @@ def overlayFeatureVariations(conditionalSubstitutions): # Generate output items = [] for box, rank in sorted( - boxMap.items(), key=(lambda BoxAndRank: -popCount(BoxAndRank[1])) + boxMap.items(), key=(lambda BoxAndRank: -bit_count(BoxAndRank[1])) ): # Skip any box that doesn't have any substitution. if rank == 0: diff --git a/Lib/fontTools/varLib/varStore.py b/Lib/fontTools/varLib/varStore.py index 73d92ece4..ffb7cf938 100644 --- a/Lib/fontTools/varLib/varStore.py +++ b/Lib/fontTools/varLib/varStore.py @@ -1,4 +1,5 @@ from fontTools.misc.roundTools import noRound, otRound +from fontTools.misc.intTools import bit_count from fontTools.ttLib.tables import otTables as ot from fontTools.varLib.models import supportScalar from fontTools.varLib.builder import ( @@ -360,7 +361,7 @@ ot.GPOS.remap_device_varidxes = Object_remap_device_varidxes class _Encoding(object): def __init__(self, chars): self.chars = chars - self.width = self._popcount(chars) + self.width = bit_count(chars) self.columns = self._columns(chars) self.overhead = self._characteristic_overhead(self.columns) self.items = set() @@ -400,13 +401,7 @@ class _Encoding(object): return not (chars & ~self.chars) def __sub__(self, other): - return self._popcount(self.chars & ~other.chars) - - @staticmethod - def _popcount(n): - # Apparently this is the fastest native way to do it... - # https://stackoverflow.com/a/9831671 - return bin(n).count("1") + return bit_count(self.chars & ~other.chars) @staticmethod def _characteristic_overhead(columns): @@ -429,7 +424,7 @@ class _Encoding(object): def gain_from_merging(self, other_encoding): combined_chars = other_encoding.chars | self.chars - combined_width = _Encoding._popcount(combined_chars) + combined_width = bit_count(combined_chars) combined_columns = self.columns | other_encoding.columns combined_overhead = _Encoding._characteristic_overhead(combined_columns) combined_gain = (