12d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod"""fontTools.misc.fixedTools.py -- tools for working with fixed numbers. 22d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod""" 32d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 41ae29591efbb29492ce05378909ccf4028d7c1eeBehdad Esfahbodfrom __future__ import print_function, division, absolute_import 52d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbodfrom fontTools.misc.py23 import * 62d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 72d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod__all__ = [ 82d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod "fixedToFloat", 92d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod "floatToFixed", 102d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod] 112d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 122d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahboddef fixedToFloat(value, precisionBits): 132d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod """Converts a fixed-point number to a float, choosing the float 142d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod that has the shortest decimal reprentation. Eg. to convert a 152d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod fixed number in a 2.14 format, use precisionBits=14. This is 162d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod pretty slow compared to a simple division. Use sporadically. 172d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 182d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod >>> fixedToFloat(13107, 14) 192d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 0.8 202d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod >>> fixedToFloat(0, 14) 212d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 0.0 222d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod >>> fixedToFloat(0x4000, 14) 232d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 1.0 242d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod """ 252d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 262d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod if not value: return 0.0 272d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 282d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod scale = 1 << precisionBits 292d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod value /= scale 302d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod eps = .5 / scale 312d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod digits = (precisionBits + 2) // 3 322d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod fmt = "%%.%df" % digits 332d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod lo = fmt % (value - eps) 342d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod hi = fmt % (value + eps) 352d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod out = [] 362d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod length = min(len(lo), len(hi)) 372d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod for i in range(length): 382d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod if lo[i] != hi[i]: 392d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod break; 402d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod out.append(lo[i]) 412d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod outlen = len(out) 422d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod if outlen < length: 432d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod out.append(max(lo[outlen], hi[outlen])) 442d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod return float(strjoin(out)) 452d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 462d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahboddef floatToFixed(value, precisionBits): 472d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod """Converts a float to a fixed-point number given the number of 482d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod precisionBits. Ie. int(round(value * (1<<precisionBits))). 492d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 502d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod >>> floatToFixed(0.8, 14) 512d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 13107 522d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod >>> floatToFixed(1.0, 14) 532d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 16384 542d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod >>> floatToFixed(1, 14) 552d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 16384 562d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod >>> floatToFixed(0, 14) 572d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 0 582d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod """ 592d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 602d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod return int(round(value * (1<<precisionBits))) 612d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 622d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod 632d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbodif __name__ == "__main__": 642d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod import doctest 652d67a188b1bef1b70b50b0862a19210d0d4c02f2Behdad Esfahbod doctest.testmod() 66