"""fontTools.misc.fixedTools.py -- tools for working with fixed numbers. """ from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * __all__ = [ "fixedToFloat", "floatToFixed", ] def fixedToFloat(value, precisionBits): """Converts a fixed-point number to a float, choosing the float that has the shortest decimal reprentation. Eg. to convert a fixed number in a 2.14 format, use precisionBits=14. This is pretty slow compared to a simple division. Use sporadically. >>> fixedToFloat(13107, 14) 0.8 >>> fixedToFloat(0, 14) 0.0 >>> fixedToFloat(0x4000, 14) 1.0 """ if not value: return 0.0 scale = 1 << precisionBits value /= scale eps = .5 / scale digits = (precisionBits + 2) // 3 fmt = "%%.%df" % digits lo = fmt % (value - eps) hi = fmt % (value + eps) out = [] length = min(len(lo), len(hi)) for i in range(length): if lo[i] != hi[i]: break; out.append(lo[i]) outlen = len(out) if outlen < length: out.append(max(lo[outlen], hi[outlen])) return float(strjoin(out)) def floatToFixed(value, precisionBits): """Converts a float to a fixed-point number given the number of precisionBits. Ie. int(round(value * (1<<precisionBits))). >>> floatToFixed(0.8, 14) 13107 >>> floatToFixed(1.0, 14) 16384 >>> floatToFixed(1, 14) 16384 >>> floatToFixed(0, 14) 0 """ return int(round(value * (1<<precisionBits))) if __name__ == "__main__": import doctest doctest.testmod()