--- /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:')