1"""fontTools.misc.fixedTools.py -- tools for working with fixed numbers. 2""" 3 4from __future__ import print_function, division, absolute_import 5from fontTools.misc.py23 import * 6 7__all__ = [ 8 "fixedToFloat", 9 "floatToFixed", 10] 11 12def fixedToFloat(value, precisionBits): 13 """Converts a fixed-point number to a float, choosing the float 14 that has the shortest decimal reprentation. Eg. to convert a 15 fixed number in a 2.14 format, use precisionBits=14. This is 16 pretty slow compared to a simple division. Use sporadically. 17 18 >>> fixedToFloat(13107, 14) 19 0.8 20 >>> fixedToFloat(0, 14) 21 0.0 22 >>> fixedToFloat(0x4000, 14) 23 1.0 24 """ 25 26 if not value: return 0.0 27 28 scale = 1 << precisionBits 29 value /= scale 30 eps = .5 / scale 31 digits = (precisionBits + 2) // 3 32 fmt = "%%.%df" % digits 33 lo = fmt % (value - eps) 34 hi = fmt % (value + eps) 35 out = [] 36 length = min(len(lo), len(hi)) 37 for i in range(length): 38 if lo[i] != hi[i]: 39 break; 40 out.append(lo[i]) 41 outlen = len(out) 42 if outlen < length: 43 out.append(max(lo[outlen], hi[outlen])) 44 return float(strjoin(out)) 45 46def floatToFixed(value, precisionBits): 47 """Converts a float to a fixed-point number given the number of 48 precisionBits. Ie. int(round(value * (1<<precisionBits))). 49 50 >>> floatToFixed(0.8, 14) 51 13107 52 >>> floatToFixed(1.0, 14) 53 16384 54 >>> floatToFixed(1, 14) 55 16384 56 >>> floatToFixed(0, 14) 57 0 58 """ 59 60 return int(round(value * (1<<precisionBits))) 61 62 63if __name__ == "__main__": 64 import doctest 65 doctest.testmod() 66