added rl_settings.decimalSymbol & support for simple bullet anchoring, version-->3.1.35
authorrobin
Mon, 22 Sep 2014 14:33:32 +0100
changeset 4136 16f067cf3dae
parent 4135 226667ad6b1f
child 4137 7e1936f8193c
added rl_settings.decimalSymbol & support for simple bullet anchoring, version-->3.1.35
src/reportlab/__init__.py
src/reportlab/graphics/shapes.py
src/reportlab/lib/styles.py
src/reportlab/pdfgen/canvas.py
src/reportlab/platypus/paragraph.py
src/reportlab/platypus/paraparser.py
src/reportlab/rl_settings.py
tests/test_paragraphs.py
--- a/src/reportlab/__init__.py	Thu Sep 18 16:04:11 2014 +0100
+++ b/src/reportlab/__init__.py	Mon Sep 22 14:33:32 2014 +0100
@@ -3,7 +3,7 @@
 #history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/__init__.py
 __version__=''' $Id$ '''
 __doc__="""The Reportlab PDF generation library."""
-Version = "3.1.34"
+Version = "3.1.35"
 
 import sys, os, imp
 
--- a/src/reportlab/graphics/shapes.py	Thu Sep 18 16:04:11 2014 +0100
+++ b/src/reportlab/graphics/shapes.py	Mon Sep 22 14:33:32 2014 +0100
@@ -10,7 +10,7 @@
 from pprint import pprint
 
 from reportlab.platypus import Flowable
-from reportlab.rl_config import shapeChecking, verbose, defaultGraphicsFontName as _baseGFontName, _unset_
+from reportlab.rl_config import shapeChecking, verbose, defaultGraphicsFontName as _baseGFontName, _unset_, decimalSymbol
 from reportlab.lib import logger
 from reportlab.lib import colors
 from reportlab.lib.validators import *
@@ -1371,7 +1371,7 @@
     def getBounds(self):
         return getPointsBounds(self.points)
 
-def numericXShift(tA,text,w,fontName,fontSize,encoding=None,pivotCharacter='.'):
+def numericXShift(tA,text,w,fontName,fontSize,encoding=None,pivotCharacter=decimalSymbol):
     dp = getattr(tA,'_dp',pivotCharacter)
     i = text.rfind(dp)
     if i>=0:
--- a/src/reportlab/lib/styles.py	Thu Sep 18 16:04:11 2014 +0100
+++ b/src/reportlab/lib/styles.py	Mon Sep 22 14:33:32 2014 +0100
@@ -128,6 +128,7 @@
                                 #dy
         'splitLongWords':1,     #make best efforts to split long words
         'underlineProportion': _baseUnderlineProportion,    #set to non-zero to get proportional
+        'bulletAnchor': 'start',    #where the bullet is anchored ie start, middle, end or numeric
         }
 
 class LineStyle(PropertySet):
--- a/src/reportlab/pdfgen/canvas.py	Thu Sep 18 16:04:11 2014 +0100
+++ b/src/reportlab/pdfgen/canvas.py	Mon Sep 22 14:33:32 2014 +0100
@@ -1529,7 +1529,7 @@
         t.textLine(text)
         self.drawText(t)
 
-    def drawAlignedString(self, x, y, text, pivotChar="."):
+    def drawAlignedString(self, x, y, text, pivotChar=rl_config.decimalSymbol):
         """Draws a string aligned on the first '.' (or other pivot character).
 
         The centre position of the pivot character will be used as x.
--- a/src/reportlab/platypus/paragraph.py	Thu Sep 18 16:04:11 2014 +0100
+++ b/src/reportlab/platypus/paragraph.py	Mon Sep 22 14:33:32 2014 +0100
@@ -15,8 +15,7 @@
 from reportlab.lib.textsplit import wordSplit, ALL_CANNOT_START
 from copy import deepcopy
 from reportlab.lib.abag import ABag
-from reportlab.rl_config import platypus_link_underline
-from reportlab import rl_config
+from reportlab.rl_config import platypus_link_underline, decimalSymbol, _FUZZ, paraFontSizeHeightOffset
 from reportlab.lib.utils import _className, isBytes, unicodeT, bytesT, strTypes
 from reportlab.lib.rl_accel import sameFrag
 import re
@@ -596,16 +595,39 @@
 
 def _drawBullet(canvas, offset, cur_y, bulletText, style, rtl):
     '''draw a bullet text could be a simple string or a frag list'''
-    if not rtl:
-        tx2 = canvas.beginText(style.bulletIndent, cur_y+getattr(style,"bulletOffsetY",0))
+    bulletAnchor = style.bulletAnchor
+    if rtl or style.bulletAnchor!='start':
+        numeric = bulletAnchor=='numeric'
+        if isinstance(bulletText,strTypes):
+            t =  bulletText
+            q = numeric and decimalSymbol in t
+            if q: t = t[:t.index(decimalSymbol)]
+            bulletWidth = stringWidth(t, style.bulletFontName, style.bulletFontSize)
+            if q: bulletWidth += 0.5 * stringWidth(decimalSymbol, style.bulletFontName, style.bulletFontSize)
+        else:
+            #it's a list of fragments
+            bulletWidth = 0
+            for f in bulletText:
+                t = f.text
+                q = numeric and decimalSymbol in t
+                if q:
+                    t = t[:t.index(decimalSymbol)]
+                    bulletWidth += 0.5 * stringWidth(decimalSymbol, f.fontName, f.fontSize)
+                bulletWidth += stringWidth(t, f.fontName, f.fontSize)
+                if q:
+                    break
     else:
-        bt = bulletText[0].text
-        bulletWidth = stringWidth(bt, style.bulletFontName, style.bulletFontSize)
+        bulletWidth = 0
+    if bulletAnchor=='middle': bulletWidth *= 0.5
+    cur_y += getattr(style,"bulletOffsetY",0)
+    if not rtl:
+        tx2 = canvas.beginText(style.bulletIndent-bulletWidth,cur_y)
+    else:
         width = rtl[0]
         bulletStart = width+style.rightIndent-(style.bulletIndent+bulletWidth)
-        tx2 = canvas.beginText(bulletStart, cur_y+getattr(style,"bulletOffsetY",0))
+        tx2 = canvas.beginText(bulletStart, cur_y)
     tx2.setFont(style.bulletFontName, style.bulletFontSize)
-    tx2.setFillColor(hasattr(style,'bulletColor') and style.bulletColor or style.textColor)
+    tx2.setFillColor(getattr(style,'bulletColor',style.textColor))
     if isinstance(bulletText,strTypes):
         tx2.textOut(bulletText)
     else:
@@ -632,7 +654,7 @@
             #it's a list of fragments
             bulletWidth = 0
             for f in bulletText:
-                bulletWidth = bulletWidth + stringWidth(f.text, f.fontName, f.fontSize)
+                bulletWidth += stringWidth(f.text, f.fontName, f.fontSize)
         bulletLen = style.bulletIndent + bulletWidth + 0.6 * style.bulletFontSize
         if style.wordWrap=='RTL':
             indent = style.rightIndent+style.firstLineIndent
@@ -877,7 +899,6 @@
 
 def cjkFragSplit(frags, maxWidths, calcBounds, encoding='utf8'):
     '''This attempts to be wordSplit for frags using the dumb algorithm'''
-    from reportlab.rl_config import _FUZZ
     U = []  #get a list of single glyphs with their widths etc etc
     for f in frags:
         text = f.text
@@ -1584,7 +1605,7 @@
                 elif self.style.alignment == TA_JUSTIFY:
                     dpl = _justifyDrawParaLine
                 f = blPara
-                if rl_config.paraFontSizeHeightOffset:
+                if paraFontSizeHeightOffset:
                     cur_y = self.height - f.fontSize
                 else:
                     cur_y = self.height - getattr(f,'ascent',f.fontSize)
@@ -1656,7 +1677,7 @@
                     for line in lines:
                         line.words = line.words[::-1]
                 f = lines[0]
-                if rl_config.paraFontSizeHeightOffset:
+                if paraFontSizeHeightOffset:
                     cur_y = self.height - f.fontSize
                 else:
                     cur_y = self.height - getattr(f,'ascent',f.fontSize)
--- a/src/reportlab/platypus/paraparser.py	Thu Sep 18 16:04:11 2014 +0100
+++ b/src/reportlab/platypus/paraparser.py	Mon Sep 22 14:33:32 2014 +0100
@@ -116,7 +116,13 @@
     elif s=='right': return TA_RIGHT
     elif s=='justify': return TA_JUSTIFY
     elif s in ('centre','center'): return TA_CENTER
-    else: raise ValueError
+    else: raise ValueError('illegal alignment %r' % s)
+
+def _bAnchor(s):
+    s = s.lower()
+    if not s in ('start','middle','end','numeric'):
+        raise ValueError('illegal bullet anchor %r' % s)
+    return s
 
 _paraAttrMap = {'font': ('fontName', None),
                 'face': ('fontName', None),
@@ -135,6 +141,7 @@
                 'boffsety': ('bulletOffsetY',_num),
                 'bindent': ('bulletIndent',_num),
                 'bcolor': ('bulletColor',toColor),
+                'banchor': ('bulletAnchor',_bAnchor),
                 'color':('textColor',toColor),
                 'backcolor':('backColor',toColor),
                 'bgcolor':('backColor',toColor),
@@ -151,6 +158,7 @@
                 'indent': ('bulletIndent',_num),
                 'color': ('bulletColor',toColor),
                 'fg': ('bulletColor',toColor),
+                'anchor': ('bulletAnchor',_bAnchor),
                 }
 
 #things which are valid font attributes
--- a/src/reportlab/rl_settings.py	Thu Sep 18 16:04:11 2014 +0100
+++ b/src/reportlab/rl_settings.py	Mon Sep 22 14:33:32 2014 +0100
@@ -48,7 +48,8 @@
 T1SearchPath
 TTFSearchPath
 CMapSearchPath
-baseUnderlineProportion'''.split())
+baseUnderlineProportion
+decimalSymbol'''.split())
 
 allowTableBoundsErrors =    1 # set to 0 to die on too large elements in tables in debug (recommend 1 for production use)
 shapeChecking =             1
@@ -100,6 +101,7 @@
                                                     #else it reports minimum(required,available) width
 baseUnderlineProportion=    0.0                     #non-zero for doing font size proportional lines in Paragraph.py
                                                     #by default typical value 0.05. may be overridden on a parastyle.
+decimalSymbol=              '.'                     #what we use to align floats numerically
 
 # places to look for T1Font information
 T1SearchPath =  (
--- a/tests/test_paragraphs.py	Thu Sep 18 16:04:11 2014 +0100
+++ b/tests/test_paragraphs.py	Mon Sep 22 14:33:32 2014 +0100
@@ -166,6 +166,18 @@
         SA(Paragraph('''This is just a very long silly text to see if the <FONT face="Courier">caseSensitive</FONT> flag also works if the paragraph is <EM>very</EM> long. '''*20, styNormal, caseSensitive=0))
 
         SA(Indenter("1cm"))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2'>1.1</bullet>sample bullet default anchor</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2'>1.22</bullet>sample bullet default anchor</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2' anchor='start'>1.1</bullet>sample bullet start align</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2' anchor='start'>1.22</bullet>sample bullet start align</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2' anchor='middle'>1.1</bullet>sample bullet middle align</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2' anchor='middle'>1.22</bullet>sample bullet middle align</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2' anchor='end'>1.1</bullet>sample bullet end align</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2' anchor='end'>1.22</bullet>sample bullet end align</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2' anchor='numeric'>1.1</bullet>sample bullet numeric align</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2' anchor='numeric'>1.22</bullet>sample bullet numeric align</para>", styNormal))
+        SA(Paragraph("<para><bullet bulletIndent='-0.7cm' bulletOffsetY='2' anchor='numeric'><span color='red'>1</span><span color='green'>.</span><span color='blue'>3</span></bullet>sample bullet numeric align</para>", styNormal))
+
         SA(Paragraph("<para><bullet bulletIndent='-1cm' bulletOffsetY='2'><seq id='s0'/>)</bullet>Indented list bulletOffsetY=2. %s</para>" % randomText(), styNormal))
         SA(Paragraph("<para><bullet bulletIndent='-1cm'><seq id='s0'/>)</bullet>Indented list. %s</para>" % randomText(), styNormal))
         SA(Paragraph("<para><bullet bulletIndent='-1cm'><seq id='s0'/>)</bullet>Indented list. %s</para>" % randomText(), styNormal))