Home | History | Annotate | Download | only in misc
      1 """fontTools.misc.fixedTools.py -- tools for working with fixed numbers.
      2 """
      3 
      4 from __future__ import print_function, division, absolute_import
      5 from fontTools.misc.py23 import *
      6 
      7 __all__ = [
      8     "fixedToFloat",
      9     "floatToFixed",
     10 ]
     11 
     12 def 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 
     46 def 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 
     63 if __name__ == "__main__":
     64     import doctest
     65     doctest.testmod()
     66