fonttools/Lib/fontTools/misc/intTools.py
Jany Belluz bba5e8b213 Add optional compaction of GPOS PairPos subtables in otlLib.optimize.gpos
See pull request: https://github.com/fonttools/fonttools/pull/2326

The new module `otlLib.optimize.gpos` provides `compact` functions that
can reduce the file size of GPOS PairPos lookups by splitting subtables
in a smart way to avoid storing zero-valued pairs.

The compaction methods are called from `otlLib.builder` and
`varLib.merger` so that static and variable fonts can benefit from the
optimization at compile time.

The new module `otlLib.optimize` is also executable, to allow running
the optimization on existing fonts.

The optimization is a trade-off because on the one hand it can reduce
significantly the byte size of the GPOS table (up to 50% in random
Google Fonts) but on the other hand it adds to the compilation time and
may make fonts very slightly bigger once compressed to WOFF2 (because
WOFF2 doesn't mind about zero values and compresses them very well).

As such, the optimization is off by default, and you can activate it by
providing the environment variable `FONTTOOLS_GPOS_COMPACT_MODE=5` for
example (values from 0 = off to 9 = max file size savings, but many more
subtables).
2021-07-05 17:28:43 +01:00

26 lines
549 B
Python

__all__ = ["popCount"]
try:
bit_count = int.bit_count
except AttributeError:
def bit_count(v):
return bin(v).count("1")
"""Return number of 1 bits (population count) of the absolute value of an integer.
See https://docs.python.org/3.10/library/stdtypes.html#int.bit_count
"""
popCount = bit_count
def bit_indices(v):
"""Return list of indices where bits are set, 0 being the index of the least significant bit.
>>> bit_indices(0b101)
[0, 2]
"""
return [i for i, b in enumerate(bin(v)[::-1]) if b == "1"]