added rl_accel py33
authorrobin
Fri, 22 Feb 2013 17:55:24 +0000
branchpy33
changeset 3725 ca840494f9dd
parent 3724 8c3d733474a0
child 3726 d431ed4575a3
added rl_accel
src/reportlab/lib/_rl_accel.pyx
src/reportlab/lib/rl_accel.py
src/reportlab/lib/utils.py
src/reportlab/pdfbase/pdfmetrics.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/reportlab/lib/_rl_accel.pyx	Fri Feb 22 17:55:24 2013 +0000
@@ -0,0 +1,70 @@
+cdef extern from "math.h" nogil:
+	double log10(double)
+from cpython.unicode cimport PyUnicode_Check
+_fp_fmts = "%.0f", "%.1f", "%.2f", "%.3f", "%.4f", "%.5f", "%.6f"
+def fp_str(*a):
+	'''convert separate arguments (or single sequence arg) into space separated numeric strings'''
+	cdef int l, j
+	cdef double i, sa
+	s = []
+	if len(a)==1 and isinstance(a[0],(tuple,list)):
+		a = a[0]
+	A = s.append
+	for i in a:
+		sa =abs(i)
+		if sa<=1e-7: A('0')
+		else:
+			l = sa<=1 and 6 or min(max(0,(6-int(log10(sa)))),6)
+			n = _fp_fmts[l]%i
+			if l:
+				j = len(n)
+				while j:
+					j -= 1
+					if n[j]!='0':
+						if n[j]!='.': j += 1
+						break
+				n = n[:j]
+			A((n[0]!='0' or len(n)==1) and n or n[1:])
+	return ' '.join(s)
+
+def unicode2T1(utext,fonts,font0=None):
+	'''return a list of (font,string) pairs representing the unicode text'''
+	R = []
+	font, fonts = fonts[0], fonts[1:]
+	if font0 is None: font0 = font
+	enc = font.encName
+	if 'UCS-2' in enc:
+		enc = 'UTF16'
+	while utext:
+		try:
+			if PyUnicode_Check(utext):
+				s = utext.encode(enc)
+			else:
+				s = utext
+			R.append((font,s))
+			break
+		except UnicodeEncodeError as e:
+			i0, il = e.args[2:4]
+			if i0:
+				R.append((font,utext[:i0].encode(enc)))
+			if fonts:
+				R.extend(unicode2T1(utext[i0:il],fonts,font0))
+			else:
+				R.append((font0._notdefFont,font0._notdefChar*(il-i0)))
+			utext = utext[il:]
+	return R
+
+def _instanceStringWidthU(self, text, size, encoding='utf8'):
+	"""This is the "purist" approach to width"""
+	if not PyUnicode_Check(text): text = text.decode(encoding)
+	#return sum([sum(f.widths.__getitem__(ord(c)) for c in t) for f, t in unicode2T1(text,[self]+self.substitutionFonts)])*0.001*size
+	#return sum([sum(map(f.widths.__getitem__,list(map(ord,t)))) for f, t in unicode2T1(text,[self]+self.substitutionFonts)])*0.001*size
+	#cdef int i, n
+	cdef bytes t, c
+	cdef double s=0
+	cdef int i
+	for f, t in unicode2T1(text,[self]+self.substitutionFonts):
+		fwgi = f.widths.__getitem__
+		for c in t:
+			s += fwgi(ord(c))
+	return s*0.001*size
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/reportlab/lib/rl_accel.py	Fri Feb 22 17:55:24 2013 +0000
@@ -0,0 +1,81 @@
+from reportlab.lib.utils import isUnicodeType, isSeqType
+from math import log
+_log_10 = lambda x,log=log,_log_e_10=log(10.0): log(x)/_log_e_10
+_fp_fmts = "%.0f", "%.1f", "%.2f", "%.3f", "%.4f", "%.5f", "%.6f"
+def fp_str(*a):
+    '''convert separate arguments (or single sequence arg) into space separated numeric strings'''
+    if len(a)==1 and isSeqType(a[0]): a = a[0]
+    s = []
+    A = s.append
+    for i in a:
+        sa =abs(i)
+        if sa<=1e-7: A('0')
+        else:
+            l = sa<=1 and 6 or min(max(0,(6-int(_log_10(sa)))),6)
+            n = _fp_fmts[l]%i
+            if l:
+                j = len(n)
+                while j:
+                    j -= 1
+                    if n[j]!='0':
+                        if n[j]!='.': j += 1
+                        break
+                n = n[:j]
+            A((n[0]!='0' or len(n)==1) and n or n[1:])
+    return ' '.join(s)
+
+#hack test for comma users
+if ',' in fp_str(0.25):
+    _FP_STR = fp_str
+    def fp_str(*a):
+        return _FP_STR(*a).replace(',','.')
+
+def unicode2T1(utext,fonts,font0=None):
+    '''return a list of (font,string) pairs representing the unicode text'''
+    R = []
+    font, fonts = fonts[0], fonts[1:]
+    if font0 is None: font0 = font
+    enc = font.encName
+    if 'UCS-2' in enc:
+        enc = 'UTF16'
+    while utext:
+        try:
+            if isUnicodeType(utext):
+                s = utext.encode(enc)
+            else:
+                s = utext
+            R.append((font,s))
+            break
+        except UnicodeEncodeError as e:
+            i0, il = e.args[2:4]
+            if i0:
+                R.append((font,utext[:i0].encode(enc)))
+            if fonts:
+                R.extend(unicode2T1(utext[i0:il],fonts,font0))
+            else:
+                R.append((font0._notdefFont,font0._notdefChar*(il-i0)))
+            utext = utext[il:]
+    return R
+
+def _instanceStringWidthU(self, text, size, encoding='utf8'):
+    """This is the "purist" approach to width"""
+    if not isUnicodeType(text): text = text.decode(encoding)
+    return sum([sum(map(f.widths.__getitem__,list(map(ord,t)))) for f, t in unicode2T1(text,[self]+self.substitutionFonts)])*0.001*size
+
+if __name__=='__main__':
+    import sys, os
+    for modname in 'reportlab.lib.rl_accel','reportlab.lib._rl_accel':
+        for cmd  in (
+            #"unicode2T1('abcde fghi . jkl ; mno',fonts)",
+            #"unicode2T1(u'abcde fghi . jkl ; mno',fonts)",
+            "_instanceStringWidthU(font,'abcde fghi . jkl ; mno',10)",
+            "_instanceStringWidthU(font,u'abcde fghi . jkl ; mno',10)",
+            ):
+            print '%s %s' % (modname,cmd)
+            s=';'.join((
+                "from reportlab.pdfbase.pdfmetrics import getFont",
+                "from %s import unicode2T1,_instanceStringWidthU" % modname,
+                "fonts=[getFont('Helvetica')]+getFont('Helvetica').substitutionFonts""",
+                "font=fonts[0]",
+                ))
+            os.system('%s -m timeit -s"%s" "%s"' % (sys.executable,s,cmd))
--- a/src/reportlab/lib/utils.py	Fri Feb 22 15:16:19 2013 +0000
+++ b/src/reportlab/lib/utils.py	Fri Feb 22 17:55:24 2013 +0000
@@ -255,43 +255,9 @@
     #raise ImportError
     ### NOTE!  FP_STR SHOULD PROBABLY ALWAYS DO A PYTHON STR() CONVERSION ON ARGS
     ### IN CASE THEY ARE "LAZY OBJECTS".  ACCELLERATOR DOESN'T DO THIS (YET)
-    try:
-        from _rl_accel import fp_str                # in case of builtin version
-    except ImportError:
-        from reportlab.lib._rl_accel import fp_str  # specific
+    from reportlab.lib._rl_accel import fp_str  # specific
 except ImportError:
-    from math import log
-    _log_10 = lambda x,log=log,_log_e_10=log(10.0): log(x)/_log_e_10
-    _fp_fmts = "%.0f", "%.1f", "%.2f", "%.3f", "%.4f", "%.5f", "%.6f"
-    import re
-    _tz_re = re.compile('0+$')
-    del re
-    def fp_str(*a):
-        '''convert separate arguments (or single sequence arg) into space separated numeric strings'''
-        if len(a)==1 and isSeqType(a[0]): a = a[0]
-        s = []
-        A = s.append
-        for i in a:
-            sa =abs(i)
-            if sa<=1e-7: A('0')
-            else:
-                l = sa<=1 and 6 or min(max(0,(6-int(_log_10(sa)))),6)
-                n = _fp_fmts[l]%i
-                if l:
-                    n = _tz_re.sub('',n)
-                    try:
-                        if n[-1]=='.': n = n[:-1]
-                    except:
-                        print(i, n)
-                        raise
-                A((n[0]!='0' or len(n)==1) and n or n[1:])
-        return ' '.join(s)
-
-#hack test for comma users
-if ',' in fp_str(0.25):
-    _FP_STR = fp_str
-    def fp_str(*a):
-        return _FP_STR(*a).replace(',','.')
+    from reportlab.lib.rl_accel import fp_str   # specific
 
 def recursiveGetAttr(obj, name):
     "Can call down into e.g. object1.object2[4].attr"
--- a/src/reportlab/pdfbase/pdfmetrics.py	Fri Feb 22 15:16:19 2013 +0000
+++ b/src/reportlab/pdfbase/pdfmetrics.py	Fri Feb 22 17:55:24 2013 +0000
@@ -34,36 +34,10 @@
 _encodings = {}
 _fonts = {}
 
-def _py_unicode2T1(utext,fonts):
-    '''return a list of (font,string) pairs representing the unicode text'''
-    R = []
-    font, fonts = fonts[0], fonts[1:]
-    enc = font.encName
-    if 'UCS-2' in enc:
-        enc = 'UTF16'
-    while utext:
-        try:
-            if isUnicodeType(utext):
-                s = utext.encode(enc)
-            else:
-                s = utext
-            R.append((font,s))
-            break
-        except UnicodeEncodeError as e:
-            i0, il = e.args[2:4]
-            if i0:
-                R.append((font,utext[:i0].encode(enc)))
-            if fonts:
-                R.extend(_py_unicode2T1(utext[i0:il],fonts))
-            else:
-                R.append((_notdefFont,_notdefChar*(il-i0)))
-            utext = utext[il:]
-    return R
-
 try:
-    from _rl_accel import unicode2T1
+    from reportlab.lib._rl_accel import unicode2T1
 except ImportError:
-    unicode2T1 = _py_unicode2T1
+    from reportlab.lib.rl_accel import unicode2T1
 
 class FontError(Exception):
     pass
@@ -405,14 +379,6 @@
                         pass
         self.widths = w
 
-    def _py_stringWidth(self, text, size, encoding='utf8'):
-        """This is the "purist" approach to width.  The practical approach
-        is to use the stringWidth function, which may be swapped in for one
-        written in C."""
-        if not isUnicodeType(text): text = text.decode(encoding)
-        return sum([sum(map(f.widths.__getitem__,list(map(ord,t)))) for f, t in unicode2T1(text,[self]+self.substitutionFonts)])*0.001*size
-    stringWidth = _py_stringWidth
-
     def _formatWidths(self):
         "returns a pretty block in PDF Array format to aid inspection"
         text = b'['
@@ -739,11 +705,11 @@
     return getFont(fontName).stringWidth(text, fontSize, encoding=encoding)
 
 try:
-    from _rl_accel import _instanceStringWidthU
-    import new
-    Font.stringWidth = new.instancemethod(_instanceStringWidthU,None,Font)
+    from reportlab.lib._rl_accel import _instanceStringWidthU
 except ImportError:
-    pass
+    from reportlab.lib.rl_accel import _instanceStringWidthU
+import new
+Font.stringWidth = new.instancemethod(_instanceStringWidthU,None,Font)
 
 def dumpFontData():
     print('Registered Encodings:')