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