src/reportlab/platypus/paragraph.py
author rgbecker
Tue, 22 Nov 2011 13:43:50 +0000
changeset 3552 20ecbcc53c15
parent 3547 6d9cf43ebf9d
child 3555 8a805f3ead47
permissions -rw-r--r--
paraparser.py add support for <span style=stylename>
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2921
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2008
494
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 488
diff changeset
     2
#see license.txt for license details
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 2321
diff changeset
     3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/platypus/paragraph.py
2321
3454f5b41760 Unicode and UTF8 support changes
andy
parents: 2211
diff changeset
     4
__version__=''' $Id$ '''
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 3031
diff changeset
     5
__doc__='''The standard paragraph implementation'''
2881
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
     6
from string import join, whitespace
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
     7
from operator import truth
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
     8
from types import StringType, ListType
3547
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
     9
from unicodedata import category
2883
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
    10
from reportlab.pdfbase.pdfmetrics import stringWidth, getFont, getAscentDescent
518
5be3fcb26c78 Semantic Name changes
rgbecker
parents: 516
diff changeset
    11
from reportlab.platypus.paraparser import ParaParser
279
e7d8b3631d5c Global sequencer put in the 'story builder'.
andy_robinson
parents: 268
diff changeset
    12
from reportlab.platypus.flowables import Flowable
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    13
from reportlab.lib.colors import Color
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    14
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
449
1ba0d6fb0f9e XPreformatted fixed empty lines and leading space
rgbecker
parents: 438
diff changeset
    15
from reportlab.lib.utils import _className
3042
2ae512e69843 Implemented variable padding for platypus paragraphs.
jonas
parents: 3032
diff changeset
    16
from reportlab.lib.geomutils import normalizeTRBL
2940
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
    17
from reportlab.lib.textsplit import wordSplit, ALL_CANNOT_START
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
    18
from copy import deepcopy
518
5be3fcb26c78 Semantic Name changes
rgbecker
parents: 516
diff changeset
    19
from reportlab.lib.abag import ABag
2887
9223e843c42a reprotlab: add platypus_link_underline and fix some paragraph issues
rgbecker
parents: 2886
diff changeset
    20
from reportlab.rl_config import platypus_link_underline 
3159
35758478fcff paragraph.py: use rl_config for control of para height offset
rgbecker
parents: 3156
diff changeset
    21
from reportlab import rl_config
2594
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
    22
import re
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
    23
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
    24
#on UTF8 branch, split and strip must be unicode-safe!
3022
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    25
#thanks to Dirk Holtwick for helpful discussions/insight
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    26
#on this one
3493
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
    27
_wsc = ''.join((
3022
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    28
    u'\u0009',  # HORIZONTAL TABULATION
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    29
    u'\u000A',  # LINE FEED
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    30
    u'\u000B',  # VERTICAL TABULATION
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    31
    u'\u000C',  # FORM FEED
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    32
    u'\u000D',  # CARRIAGE RETURN
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    33
    u'\u001C',  # FILE SEPARATOR
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    34
    u'\u001D',  # GROUP SEPARATOR
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    35
    u'\u001E',  # RECORD SEPARATOR
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    36
    u'\u001F',  # UNIT SEPARATOR
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    37
    u'\u0020',  # SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    38
    u'\u0085',  # NEXT LINE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    39
    #u'\u00A0', # NO-BREAK SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    40
    u'\u1680',  # OGHAM SPACE MARK
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    41
    u'\u2000',  # EN QUAD
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    42
    u'\u2001',  # EM QUAD
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    43
    u'\u2002',  # EN SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    44
    u'\u2003',  # EM SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    45
    u'\u2004',  # THREE-PER-EM SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    46
    u'\u2005',  # FOUR-PER-EM SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    47
    u'\u2006',  # SIX-PER-EM SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    48
    u'\u2007',  # FIGURE SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    49
    u'\u2008',  # PUNCTUATION SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    50
    u'\u2009',  # THIN SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    51
    u'\u200A',  # HAIR SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    52
    u'\u200B',  # ZERO WIDTH SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    53
    u'\u2028',  # LINE SEPARATOR
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    54
    u'\u2029',  # PARAGRAPH SEPARATOR
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    55
    u'\u202F',  # NARROW NO-BREAK SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    56
    u'\u205F',  # MEDIUM MATHEMATICAL SPACE
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    57
    u'\u3000',  # IDEOGRAPHIC SPACE
3493
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
    58
    ))
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
    59
_wsc_re_split=re.compile('[%s]+'% re.escape(_wsc)).split
3022
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    60
2898
71cc316046ff paragraph.py: fix longstanding split bug
rgbecker
parents: 2894
diff changeset
    61
def split(text, delim=None):
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
    62
    if type(text) is str: text = text.decode('utf8')
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
    63
    if type(delim) is str: delim = delim.decode('utf8')
3022
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    64
    if delim is None and u'\xa0' in text:
4bbfeb0709ea reportlab: add Dirk Holtwick inspired split to paragraph.py
rgbecker
parents: 3003
diff changeset
    65
        return [uword.encode('utf8') for uword in _wsc_re_split(text)]
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
    66
    return [uword.encode('utf8') for uword in text.split(delim)]
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
    67
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
    68
def strip(text):
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
    69
    if type(text) is str: text = text.decode('utf8')
3493
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
    70
    return text.strip(_wsc).encode('utf8')
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
    71
518
5be3fcb26c78 Semantic Name changes
rgbecker
parents: 516
diff changeset
    72
class ParaLines(ABag):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
    73
    """
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
    74
    class ParaLines contains the broken into lines representation of Paragraphs
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
    75
        kind=0  Simple
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
    76
        fontName, fontSize, textColor apply to whole Paragraph
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
    77
        lines   [(extraSpace1,words1),....,(extraspaceN,wordsN)]
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    78
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
    79
        kind==1 Complex
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
    80
        lines   [FragLine1,...,FragLineN]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
    81
    """
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    82
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    83
class FragLine(ABag):
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
    84
    """
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
    85
    class FragLine contains a styled line (ie a line with more than one style)::
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    86
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
    87
        extraSpace  unused space for justification only
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
    88
        wordCount   1+spaces in line for justification purposes
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
    89
        words       [ParaFrags] style text lumps to be concatenated together
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
    90
        fontSize    maximum fontSize seen on the line; not used at present,
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
    91
                    but could be used for line spacing.
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
    92
                
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
    93
    """
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    94
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    95
#our one and only parser
268
8414113fa500 more documentation changes
aaron_watters
parents: 253
diff changeset
    96
# XXXXX if the parser has any internal state using only one is probably a BAD idea!
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    97
_parser=ParaParser()
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    98
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    99
def _lineClean(L):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   100
    return join(filter(truth,split(strip(L))))
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   101
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   102
def cleanBlockQuotedText(text,joiner=' '):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   103
    """This is an internal utility which takes triple-
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   104
    quoted text form within the document and returns
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   105
    (hopefully) the paragraph the user intended originally."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   106
    L=filter(truth,map(_lineClean, split(text, '\n')))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   107
    return join(L, joiner)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   108
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   109
def setXPos(tx,dx):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   110
    if dx>1e-6 or dx<-1e-6:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   111
        tx.setXPos(dx)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   112
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   113
def _leftDrawParaLine( tx, offset, extraspace, words, last=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   114
    setXPos(tx,offset)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   115
    tx._textOut(join(words),1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   116
    setXPos(tx,-offset)
1915
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   117
    return offset
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   118
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   119
def _centerDrawParaLine( tx, offset, extraspace, words, last=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   120
    m = offset + 0.5 * extraspace
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   121
    setXPos(tx,m)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   122
    tx._textOut(join(words),1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   123
    setXPos(tx,-m)
1915
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   124
    return m
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   125
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   126
def _rightDrawParaLine( tx, offset, extraspace, words, last=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   127
    m = offset + extraspace
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   128
    setXPos(tx,m)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   129
    tx._textOut(join(words),1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   130
    setXPos(tx,-m)
1915
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   131
    return m
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   132
3373
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   133
def _nbspCount(w):
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   134
    if isinstance(w,str):
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   135
        return w.count('\xc2\xa0')
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   136
    else:
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   137
        return w.count(u'\xa0')
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   138
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   139
def _justifyDrawParaLine( tx, offset, extraspace, words, last=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   140
    setXPos(tx,offset)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   141
    text  = join(words)
3373
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   142
    if last or extraspace<=1e-8:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   143
        #last one, left align
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   144
        tx._textOut(text,1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   145
    else:
3373
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   146
        nSpaces = len(words)+sum([_nbspCount(w) for w in words])-1
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   147
        if nSpaces:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   148
            tx.setWordSpace(extraspace / float(nSpaces))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   149
            tx._textOut(text,1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   150
            tx.setWordSpace(0)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   151
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   152
            tx._textOut(text,1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   153
    setXPos(tx,-offset)
1915
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   154
    return offset
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   155
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
   156
def imgVRange(h,va,fontSize):
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   157
    '''return bottom,top offsets relative to baseline(0)'''
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   158
    if va=='baseline':
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   159
        iyo = 0
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   160
    elif va in ('text-top','top'):
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   161
        iyo = fontSize-h
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   162
    elif va=='middle':
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
   163
        iyo = fontSize - (1.2*fontSize+h)*0.5
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   164
    elif va in ('text-bottom','bottom'):
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
   165
        iyo = fontSize - 1.2*fontSize
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   166
    elif va=='super':
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   167
        iyo = 0.5*fontSize
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   168
    elif va=='sub':
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   169
        iyo = -0.5*fontSize
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   170
    elif hasattr(va,'normalizedValue'):
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   171
        iyo = va.normalizedValue(fontSize)
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   172
    else:
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   173
        iyo = va
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   174
    return iyo,iyo+h
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   175
3434
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   176
def imgNormV(v,nv):
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   177
    if hasattr(v,'normalizedValue'):
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   178
        return v.normalizedValue(nv)
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   179
    else:
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   180
        return v
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   181
2881
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   182
_56=5./6
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   183
_16=1./6
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   184
def _putFragLine(cur_x, tx, line):
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   185
    xs = tx.XtraState
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   186
    cur_y = xs.cur_y
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   187
    x0 = tx._x0
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   188
    autoLeading = xs.autoLeading
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   189
    leading = xs.leading
2910
5522f685b679 paragraph.py: fix leftIndent problem
rgbecker
parents: 2901
diff changeset
   190
    cur_x += xs.leftIndent
2881
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   191
    dal = autoLeading in ('min','max')
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   192
    if dal:
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   193
        if autoLeading=='max':
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   194
            ascent = max(_56*leading,line.ascent)
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   195
            descent = max(_16*leading,-line.descent)
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   196
        else:
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   197
            ascent = line.ascent
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   198
            descent = -line.descent
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   199
        leading = ascent+descent
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   200
    if tx._leading!=leading:
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   201
        tx.setLeading(leading)
2881
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   202
    if dal:
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   203
        olb = tx._olb
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   204
        if olb is not None:
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   205
            xcy = olb-ascent
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   206
            if tx._oleading!=leading:
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   207
                cur_y += leading - tx._oleading
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   208
            if abs(xcy-cur_y)>1e-8:
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   209
                cur_y = xcy
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   210
                tx.setTextOrigin(x0,cur_y)
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   211
                xs.cur_y = cur_y
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   212
        tx._olb = cur_y - descent
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   213
        tx._oleading = leading
2708
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   214
    ws = getattr(tx,'_wordSpace',0)
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   215
    nSpaces = 0
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   216
    words = line.words
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   217
    for f in words:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   218
        if hasattr(f,'cbDefn'):
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   219
            cbDefn = f.cbDefn
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   220
            kind = cbDefn.kind
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   221
            if kind=='img':
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   222
                #draw image cbDefn,cur_y,cur_x
2871
afd057e790cb paragraph.py: attempt to fix problem when inline img is first in line
rgbecker
parents: 2865
diff changeset
   223
                txfs = tx._fontsize
afd057e790cb paragraph.py: attempt to fix problem when inline img is first in line
rgbecker
parents: 2865
diff changeset
   224
                if txfs is None:
afd057e790cb paragraph.py: attempt to fix problem when inline img is first in line
rgbecker
parents: 2865
diff changeset
   225
                    txfs = xs.style.fontSize
3434
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   226
                w = imgNormV(cbDefn.width,None)
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   227
                h = imgNormV(cbDefn.height,txfs)
2871
afd057e790cb paragraph.py: attempt to fix problem when inline img is first in line
rgbecker
parents: 2865
diff changeset
   228
                iy0,iy1 = imgVRange(h,cbDefn.valign,txfs)
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   229
                cur_x_s = cur_x + nSpaces*ws
2894
78cd38a39719 paragraph.py: add auto mask for inline images
rgbecker
parents: 2892
diff changeset
   230
                tx._canvas.drawImage(cbDefn.image,cur_x_s,cur_y+iy0,w,h,mask='auto')
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   231
                cur_x += w
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   232
                cur_x_s += w
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   233
                setXPos(tx,cur_x_s-tx._x0)
2744
9472eedb9702 reportlab/platypus: add two way <a> tag
rgbecker
parents: 2735
diff changeset
   234
            else:
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   235
                name = cbDefn.name
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   236
                if kind=='anchor':
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   237
                    tx._canvas.bookmarkHorizontal(name,cur_x,cur_y+leading)
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   238
                else:
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   239
                    func = getattr(tx._canvas,name,None)
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   240
                    if not func:
2892
131b417f9845 paragraph: improved <a> syntax checks and better test
rgbecker
parents: 2888
diff changeset
   241
                        raise AttributeError("Missing %s callback attribute '%s'" % (kind,name))
3048
3ff2383916b9 Renamed setencrypt to setEncrypt to follow naming convention.
jonas
parents: 3042
diff changeset
   242
                    tx._canvas._curr_tx_info=dict(tx=tx,cur_x=cur_x,cur_y=cur_y,leading=leading,xs=tx.XtraState)
3ff2383916b9 Renamed setencrypt to setEncrypt to follow naming convention.
jonas
parents: 3042
diff changeset
   243
                    try:
3ff2383916b9 Renamed setencrypt to setEncrypt to follow naming convention.
jonas
parents: 3042
diff changeset
   244
                        func(tx._canvas,kind,cbDefn.label)
3ff2383916b9 Renamed setencrypt to setEncrypt to follow naming convention.
jonas
parents: 3042
diff changeset
   245
                    finally:
3ff2383916b9 Renamed setencrypt to setEncrypt to follow naming convention.
jonas
parents: 3042
diff changeset
   246
                        del tx._canvas._curr_tx_info
2750
05229265aff3 reportlab: fix special case <a> tag problem, add AnchorFlowable class
rgbecker
parents: 2745
diff changeset
   247
            if f is words[-1]:
05229265aff3 reportlab: fix special case <a> tag problem, add AnchorFlowable class
rgbecker
parents: 2745
diff changeset
   248
                if not tx._fontname:
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   249
                    tx.setFont(xs.style.fontName,xs.style.fontSize)
3322
e27df3a204a1 pargraph.py: all eol cbDefns should do textOut('',1)
rgbecker
parents: 3192
diff changeset
   250
                tx._textOut('',1)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   251
        else:
2708
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   252
            cur_x_s = cur_x + nSpaces*ws
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   253
            if (tx._fontname,tx._fontsize)!=(f.fontName,f.fontSize):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   254
                tx._setFont(f.fontName, f.fontSize)
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   255
            if xs.textColor!=f.textColor:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   256
                xs.textColor = f.textColor
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   257
                tx.setFillColor(f.textColor)
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   258
            if xs.rise!=f.rise:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   259
                xs.rise=f.rise
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   260
                tx.setRise(f.rise)
2708
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   261
            text = f.text
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   262
            tx._textOut(text,f is words[-1])    # cheap textOut
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   263
            if not xs.underline and f.underline:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   264
                xs.underline = 1
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   265
                xs.underline_x = cur_x_s
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   266
                xs.underlineColor = f.textColor
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   267
            elif xs.underline:
2456
afa6ef178273 paragraph.py: added proper undeerline color
rgbecker
parents: 2445
diff changeset
   268
                if not f.underline:
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   269
                    xs.underline = 0
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   270
                    xs.underlines.append( (xs.underline_x, cur_x_s, xs.underlineColor) )
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   271
                    xs.underlineColor = None
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   272
                elif xs.textColor!=xs.underlineColor:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   273
                    xs.underlines.append( (xs.underline_x, cur_x_s, xs.underlineColor) )
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   274
                    xs.underlineColor = xs.textColor
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   275
                    xs.underline_x = cur_x_s
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   276
            if not xs.strike and f.strike:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   277
                xs.strike = 1
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   278
                xs.strike_x = cur_x_s
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   279
                xs.strikeColor = f.textColor
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   280
            elif xs.strike:
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   281
                if not f.strike:
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   282
                    xs.strike = 0
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   283
                    xs.strikes.append( (xs.strike_x, cur_x_s, xs.strikeColor) )
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   284
                    xs.strikeColor = None
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   285
                elif xs.textColor!=xs.strikeColor:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   286
                    xs.strikes.append( (xs.strike_x, cur_x_s, xs.strikeColor) )
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   287
                    xs.strikeColor = xs.textColor
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   288
                    xs.strike_x = cur_x_s
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   289
            if f.link and not xs.link:
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   290
                if not xs.link:
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   291
                    xs.link = f.link
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   292
                    xs.link_x = cur_x_s
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   293
                    xs.linkColor = xs.textColor
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   294
            elif xs.link:
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   295
                if not f.link:
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   296
                    xs.links.append( (xs.link_x, cur_x_s, xs.link, xs.linkColor) )
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   297
                    xs.link = None
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   298
                    xs.linkColor = None
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   299
                elif f.link!=xs.link or xs.textColor!=xs.linkColor:
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   300
                    xs.links.append( (xs.link_x, cur_x_s, xs.link, xs.linkColor) )
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   301
                    xs.link = f.link
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   302
                    xs.link_x = cur_x_s
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   303
                    xs.linkColor = xs.textColor
3476
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   304
            bg = getattr(f,'backColor',None)
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   305
            if bg and not xs.backColor:
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   306
                xs.backColor = bg
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   307
                xs.backColor_x = cur_x_s
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   308
            elif xs.backColor:
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   309
                if not bg:
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   310
                    xs.backColors.append( (xs.backColor_x, cur_x_s, xs.backColor) )
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   311
                    xs.backColor = None
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   312
                elif f.backColor!=xs.backColor or xs.textColor!=xs.backColor:
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   313
                    xs.backColors.append( (xs.backColor_x, cur_x_s, xs.backColor) )
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   314
                    xs.backColor = bg
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   315
                    xs.backColor_x = cur_x_s
2708
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   316
            txtlen = tx._canvas.stringWidth(text, tx._fontname, tx._fontsize)
2593
3adaab508968 reportlab: minor fixes to platypus, tests and fix jap splitting bug
rgbecker
parents: 2584
diff changeset
   317
            cur_x += txtlen
3373
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   318
            nSpaces += text.count(' ')+_nbspCount(text)
2708
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   319
    cur_x_s = cur_x+(nSpaces-1)*ws
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   320
    if xs.underline:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   321
        xs.underlines.append( (xs.underline_x, cur_x_s, xs.underlineColor) )
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   322
    if xs.strike:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   323
        xs.strikes.append( (xs.strike_x, cur_x_s, xs.strikeColor) )
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   324
    if xs.link:
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   325
        xs.links.append( (xs.link_x, cur_x_s, xs.link,xs.linkColor) )
3476
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   326
    if xs.backColor:
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   327
        xs.backColors.append( (xs.backColor_x, cur_x_s, xs.backColor) )
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   328
    if tx._x0!=x0:
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   329
        setXPos(tx,x0-tx._x0)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   330
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   331
def _leftDrawParaLineX( tx, offset, line, last=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   332
    setXPos(tx,offset)
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   333
    _putFragLine(offset, tx, line)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   334
    setXPos(tx,-offset)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   335
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   336
def _centerDrawParaLineX( tx, offset, line, last=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   337
    m = offset+0.5*line.extraSpace
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   338
    setXPos(tx,m)
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   339
    _putFragLine(m,tx, line)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   340
    setXPos(tx,-m)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   341
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   342
def _rightDrawParaLineX( tx, offset, line, last=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   343
    m = offset+line.extraSpace
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   344
    setXPos(tx,m)
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   345
    _putFragLine(m,tx, line)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   346
    setXPos(tx,-m)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   347
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   348
def _justifyDrawParaLineX( tx, offset, line, last=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   349
    setXPos(tx,offset)
2840
69e2c8b05684 reportlab: fixes to paragraph <br/> tag
rgbecker
parents: 2836
diff changeset
   350
    extraSpace = line.extraSpace
3373
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   351
    simple = last or abs(extraSpace)<=1e-8 or line.lineBreak
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   352
    if not simple:
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   353
        nSpaces = line.wordCount+sum([_nbspCount(w.text) for w in line.words if not hasattr(w,'cbDefn')])-1
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   354
        simple = not nSpaces
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   355
    if not simple:
2840
69e2c8b05684 reportlab: fixes to paragraph <br/> tag
rgbecker
parents: 2836
diff changeset
   356
        tx.setWordSpace(extraSpace / float(nSpaces))
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   357
        _putFragLine(offset, tx, line)
2840
69e2c8b05684 reportlab: fixes to paragraph <br/> tag
rgbecker
parents: 2836
diff changeset
   358
        tx.setWordSpace(0)
3373
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   359
    else:
127aed2a021d paragraph.py: fixup for nbsp
rgbecker
parents: 3326
diff changeset
   360
        _putFragLine(offset, tx, line)  #no space modification
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   361
    setXPos(tx,-offset)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   362
1373
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   363
try:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   364
    from _rl_accel import _sameFrag
1915
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   365
except ImportError:
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   366
    try:
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   367
        from reportlab.lib._rl_accel import _sameFrag
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   368
    except ImportError:
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   369
        #if you modify this you need to modify _rl_accel RGB
1915
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   370
        def _sameFrag(f,g):
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   371
            'returns 1 if two ParaFrags map out the same'
2664
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
   372
            if (hasattr(f,'cbDefn') or hasattr(g,'cbDefn')
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
   373
                    or hasattr(f,'lineBreak') or hasattr(g,'lineBreak')): return 0
3476
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   374
            for a in ('fontName', 'fontSize', 'textColor', 'rise', 'underline', 'strike', 'link', "backColor"):
2958
12316671c2aa reportlab: minor changes to allow running without accelerators
rgbecker
parents: 2940
diff changeset
   375
                if getattr(f,a,None)!=getattr(g,a,None): return 0
1915
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   376
            return 1
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   377
3434
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   378
def _getFragWords(frags,maxWidth=None):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   379
    ''' given a Parafrag list return a list of fragwords
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   380
        [[size, (f00,w00), ..., (f0n,w0n)],....,[size, (fm0,wm0), ..., (f0n,wmn)]]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   381
        each pair f,w represents a style and some string
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   382
        each sublist represents a word
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   383
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   384
    R = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   385
    W = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   386
    n = 0
2840
69e2c8b05684 reportlab: fixes to paragraph <br/> tag
rgbecker
parents: 2836
diff changeset
   387
    hangingStrip = False
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   388
    for f in frags:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   389
        text = f.text
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   390
        #del f.text # we can't do this until we sort out splitting
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   391
                    # of paragraphs
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   392
        if text!='':
2840
69e2c8b05684 reportlab: fixes to paragraph <br/> tag
rgbecker
parents: 2836
diff changeset
   393
            if hangingStrip:
69e2c8b05684 reportlab: fixes to paragraph <br/> tag
rgbecker
parents: 2836
diff changeset
   394
                hangingStrip = False
69e2c8b05684 reportlab: fixes to paragraph <br/> tag
rgbecker
parents: 2836
diff changeset
   395
                text = text.lstrip()
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   396
            S = split(text)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   397
            if S==[]: S = ['']
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   398
            if W!=[] and text[0] in whitespace:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   399
                W.insert(0,n)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   400
                R.append(W)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   401
                W = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   402
                n = 0
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   403
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   404
            for w in S[:-1]:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   405
                W.append((f,w))
2593
3adaab508968 reportlab: minor fixes to platypus, tests and fix jap splitting bug
rgbecker
parents: 2584
diff changeset
   406
                n += stringWidth(w, f.fontName, f.fontSize)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   407
                W.insert(0,n)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   408
                R.append(W)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   409
                W = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   410
                n = 0
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   411
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   412
            w = S[-1]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   413
            W.append((f,w))
2593
3adaab508968 reportlab: minor fixes to platypus, tests and fix jap splitting bug
rgbecker
parents: 2584
diff changeset
   414
            n += stringWidth(w, f.fontName, f.fontSize)
2841
c18f03647e07 fixed _getFragWords
hassan
parents: 2840
diff changeset
   415
            if text and text[-1] in whitespace:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   416
                W.insert(0,n)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   417
                R.append(W)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   418
                W = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   419
                n = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   420
        elif hasattr(f,'cbDefn'):
3434
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   421
            cb = f.cbDefn
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   422
            w = getattr(cb,'width',0)
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   423
            if w:
3434
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   424
                if hasattr(w,'normalizedValue'):
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   425
                    w._normalizer = maxWidth
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   426
                    w = w.normalizedValue(maxWidth)
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   427
                if W!=[]:
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   428
                    W.insert(0,n)
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   429
                    R.append(W)
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   430
                    W = []
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   431
                    n = 0
2865
dcf03cc19361 paragraph.py: attempt to fix up inline images across paragraph split
rgbecker
parents: 2863
diff changeset
   432
                R.append([w,(f,'')])
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   433
            else:
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   434
                W.append((f,''))
2664
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
   435
        elif hasattr(f, 'lineBreak'):
2663
927cc273c5a5 <br/> work in progress
andy
parents: 2646
diff changeset
   436
            #pass the frag through.  The line breaker will scan for it.
2664
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
   437
            if W!=[]:
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
   438
                W.insert(0,n)
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
   439
                R.append(W)
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
   440
                W = []
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
   441
                n = 0
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
   442
            R.append([0,(f,'')])
2840
69e2c8b05684 reportlab: fixes to paragraph <br/> tag
rgbecker
parents: 2836
diff changeset
   443
            hangingStrip = True
508
37dc6fc3fa65 More <onDraw> hacks
rgbecker
parents: 506
diff changeset
   444
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   445
    if W!=[]:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   446
        W.insert(0,n)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   447
        R.append(W)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   448
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   449
    return R
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   450
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   451
def _split_blParaSimple(blPara,start,stop):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   452
    f = blPara.clone()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   453
    for a in ('lines', 'kind', 'text'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   454
        if hasattr(f,a): delattr(f,a)
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   455
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   456
    f.words = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   457
    for l in blPara.lines[start:stop]:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   458
        for w in l[1]:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   459
            f.words.append(w)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   460
    return [f]
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   461
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   462
def _split_blParaHard(blPara,start,stop):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   463
    f = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   464
    lines = blPara.lines[start:stop]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   465
    for l in lines:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   466
        for w in l.words:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   467
            f.append(w)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   468
        if l is not lines[-1]:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   469
            i = len(f)-1
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   470
            while i>=0 and hasattr(f[i],'cbDefn') and not getattr(f[i].cbDefn,'width',0): i -= 1
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   471
            if i>=0:
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   472
                g = f[i]
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   473
                if not g.text: g.text = ' '
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   474
                elif g.text[-1]!=' ': g.text += ' '
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   475
    return f
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   476
250
a1bcf9c6c21e <bullet> xml tag added
rgbecker
parents: 221
diff changeset
   477
def _drawBullet(canvas, offset, cur_y, bulletText, style):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   478
    '''draw a bullet text could be a simple string or a frag list'''
2860
3f14d66194c2 platypus: added bulletOffsetY inspired by haraldarminmassa@gmail.com
rgbecker
parents: 2857
diff changeset
   479
    tx2 = canvas.beginText(style.bulletIndent, cur_y+getattr(style,"bulletOffsetY",0))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   480
    tx2.setFont(style.bulletFontName, style.bulletFontSize)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   481
    tx2.setFillColor(hasattr(style,'bulletColor') and style.bulletColor or style.textColor)
2646
d177c247184a platypus: eliminate StringType usages and cp1252 usage
rgbecker
parents: 2644
diff changeset
   482
    if isinstance(bulletText,basestring):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   483
        tx2.textOut(bulletText)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   484
    else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   485
        for f in bulletText:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   486
            tx2.setFont(f.fontName, f.fontSize)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   487
            tx2.setFillColor(f.textColor)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   488
            tx2.textOut(f.text)
250
a1bcf9c6c21e <bullet> xml tag added
rgbecker
parents: 221
diff changeset
   489
2366
7dd247980b7d minor twitching on Indenter
rgbecker
parents: 2341
diff changeset
   490
    canvas.drawText(tx2)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   491
    #AR making definition lists a bit less ugly
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   492
    #bulletEnd = tx2.getX()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   493
    bulletEnd = tx2.getX() + style.bulletFontSize * 0.6
2366
7dd247980b7d minor twitching on Indenter
rgbecker
parents: 2341
diff changeset
   494
    offset = max(offset,bulletEnd - style.leftIndent)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   495
    return offset
250
a1bcf9c6c21e <bullet> xml tag added
rgbecker
parents: 221
diff changeset
   496
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   497
def _handleBulletWidth(bulletText,style,maxWidths):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   498
    '''work out bullet width and adjust maxWidths[0] if neccessary
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   499
    '''
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   500
    if bulletText:
2646
d177c247184a platypus: eliminate StringType usages and cp1252 usage
rgbecker
parents: 2644
diff changeset
   501
        if isinstance(bulletText,basestring):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   502
            bulletWidth = stringWidth( bulletText, style.bulletFontName, style.bulletFontSize)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   503
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   504
            #it's a list of fragments
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   505
            bulletWidth = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   506
            for f in bulletText:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   507
                bulletWidth = bulletWidth + stringWidth(f.text, f.fontName, f.fontSize)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   508
        bulletRight = style.bulletIndent + bulletWidth + 0.6 * style.bulletFontSize
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   509
        indent = style.leftIndent+style.firstLineIndent
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   510
        if bulletRight > indent:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   511
            #..then it overruns, and we have less space available on line 1
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   512
            maxWidths[0] -= (bulletRight - indent)
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   513
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   514
def splitLines0(frags,widths):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   515
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   516
    given a list of ParaFrags we return a list of ParaLines
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   517
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   518
    each ParaLine has
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   519
    1)  ExtraSpace
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   520
    2)  blankCount
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   521
    3)  [textDefns....]
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   522
    each text definition is a (ParaFrag, start, limit) triplet
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   523
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   524
    #initialise the algorithm
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   525
    lines   = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   526
    lineNum = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   527
    maxW    = widths[lineNum]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   528
    i       = -1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   529
    l       = len(frags)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   530
    lim     = start = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   531
    while 1:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   532
        #find a non whitespace character
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   533
        while i<l:
2593
3adaab508968 reportlab: minor fixes to platypus, tests and fix jap splitting bug
rgbecker
parents: 2584
diff changeset
   534
            while start<lim and text[start]==' ': start += 1
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   535
            if start==lim:
2593
3adaab508968 reportlab: minor fixes to platypus, tests and fix jap splitting bug
rgbecker
parents: 2584
diff changeset
   536
                i += 1
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   537
                if i==l: break
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   538
                start = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   539
                f = frags[i]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   540
                text = f.text
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   541
                lim = len(text)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   542
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   543
                break   # we found one
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   544
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   545
        if start==lim: break    #if we didn't find one we are done
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   546
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   547
        #start of a line
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   548
        g       = (None,None,None)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   549
        line    = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   550
        cLen    = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   551
        nSpaces = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   552
        while cLen<maxW:
2881
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   553
            j = text.find(' ',start)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   554
            if j<0: j==lim
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   555
            w = stringWidth(text[start:j],f.fontName,f.fontSize)
2593
3adaab508968 reportlab: minor fixes to platypus, tests and fix jap splitting bug
rgbecker
parents: 2584
diff changeset
   556
            cLen += w
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   557
            if cLen>maxW and line!=[]:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   558
                cLen = cLen-w
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   559
                #this is the end of the line
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   560
                while g.text[lim]==' ':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   561
                    lim = lim - 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   562
                    nSpaces = nSpaces-1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   563
                break
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   564
            if j<0: j = lim
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   565
            if g[0] is f: g[2] = j  #extend
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   566
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   567
                g = (f,start,j)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   568
                line.append(g)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   569
            if j==lim:
2593
3adaab508968 reportlab: minor fixes to platypus, tests and fix jap splitting bug
rgbecker
parents: 2584
diff changeset
   570
                i += 1
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   571
2708
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   572
def _do_under_line(i, t_off, ws, tx, lm=-0.125):
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   573
    y = tx.XtraState.cur_y - i*tx.XtraState.style.leading + lm*tx.XtraState.f.fontSize
2708
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   574
    textlen = tx._canvas.stringWidth(join(tx.XtraState.lines[i][1]), tx._fontname, tx._fontsize)
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   575
    tx._canvas.line(t_off, y, t_off+textlen+ws, y)
1915
5a94ea499657 Added in Ury Marshak's underlining stuff hacked for <2.2
rgbecker
parents: 1752
diff changeset
   576
2594
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   577
_scheme_re = re.compile('^[a-zA-Z][-+a-zA-Z0-9]+$')
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   578
def _doLink(tx,link,rect):
2938
5115bf2e8eeb paragraph.py: fix encoding bug
rgbecker
parents: 2936
diff changeset
   579
    if isinstance(link,unicode):
5115bf2e8eeb paragraph.py: fix encoding bug
rgbecker
parents: 2936
diff changeset
   580
        link = link.encode('utf8')
2594
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   581
    parts = link.split(':',1)
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   582
    scheme = len(parts)==2 and parts[0].lower() or ''
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   583
    if _scheme_re.match(scheme) and scheme!='document':
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   584
        kind=scheme.lower()=='pdf' and 'GoToR' or 'URI'
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   585
        if kind=='GoToR': link = parts[1]
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   586
        tx._canvas.linkURL(link, rect, relative=1, kind=kind)
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   587
    else:
2744
9472eedb9702 reportlab/platypus: add two way <a> tag
rgbecker
parents: 2735
diff changeset
   588
        if link[0]=='#':
9472eedb9702 reportlab/platypus: add two way <a> tag
rgbecker
parents: 2735
diff changeset
   589
            link = link[1:]
9472eedb9702 reportlab/platypus: add two way <a> tag
rgbecker
parents: 2735
diff changeset
   590
            scheme=''
2594
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   591
        tx._canvas.linkRect("", scheme!='document' and link or parts[1], rect, relative=1)
746800f5caf9 reportlab: fix up links in paragraphs
rgbecker
parents: 2593
diff changeset
   592
2708
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   593
def _do_link_line(i, t_off, ws, tx):
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   594
    xs = tx.XtraState
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   595
    leading = xs.style.leading
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   596
    y = xs.cur_y - i*leading - xs.f.fontSize/8.0 # 8.0 factor copied from para.py
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   597
    text = join(xs.lines[i][1])
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   598
    textlen = tx._canvas.stringWidth(text, tx._fontname, tx._fontsize)
2708
13619490e003 paragraph.py: fix underlining position errors
rgbecker
parents: 2681
diff changeset
   599
    _doLink(tx, xs.link, (t_off, y, t_off+textlen+ws, y+leading))
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   600
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   601
def _do_post_text(tx):
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   602
    xs = tx.XtraState
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   603
    leading = xs.style.leading
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   604
    autoLeading = xs.autoLeading
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   605
    f = xs.f
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   606
    if autoLeading=='max':
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   607
        leading = max(leading,1.2*f.fontSize)
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   608
    elif autoLeading=='min':
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   609
        leading = 1.2*f.fontSize
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   610
    ff = 0.125*f.fontSize
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   611
    y0 = xs.cur_y
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   612
    y = y0 - ff
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   613
    csc = None
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   614
    for x1,x2,c in xs.underlines:
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   615
        if c!=csc:
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   616
            tx._canvas.setStrokeColor(c)
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   617
            csc = c
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   618
        tx._canvas.line(x1, y, x2, y)
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   619
    xs.underlines = []
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   620
    xs.underline=0
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   621
    xs.underlineColor=None
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   622
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   623
    ys = y0 + 2*ff
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   624
    for x1,x2,c in xs.strikes:
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   625
        if c!=csc:
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   626
            tx._canvas.setStrokeColor(c)
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   627
            csc = c
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   628
        tx._canvas.line(x1, ys, x2, ys)
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   629
    xs.strikes = []
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   630
    xs.strike=0
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   631
    xs.strikeColor=None
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   632
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   633
    yl = y + leading
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   634
    for x1,x2,link,c in xs.links:
2887
9223e843c42a reprotlab: add platypus_link_underline and fix some paragraph issues
rgbecker
parents: 2886
diff changeset
   635
        if platypus_link_underline:
9223e843c42a reprotlab: add platypus_link_underline and fix some paragraph issues
rgbecker
parents: 2886
diff changeset
   636
            if c!=csc:
9223e843c42a reprotlab: add platypus_link_underline and fix some paragraph issues
rgbecker
parents: 2886
diff changeset
   637
                tx._canvas.setStrokeColor(c)
9223e843c42a reprotlab: add platypus_link_underline and fix some paragraph issues
rgbecker
parents: 2886
diff changeset
   638
                csc = c
2899
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   639
            tx._canvas.line(x1, y, x2, y)
bdcad3b5bf68 attempt to fix offset problems with images
rgbecker
parents: 2898
diff changeset
   640
        _doLink(tx, link, (x1, y, x2, yl))
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   641
    xs.links = []
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   642
    xs.link=None
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
   643
    xs.linkColor=None
3476
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   644
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   645
    for x1,x2,c in xs.backColors:
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   646
        tx._canvas.setFillColor(c)
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   647
        tx._canvas.rect(x1,y,x2-x1,yl-y,stroke=0,fill=1)
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   648
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   649
    xs.backColors=[]
0d4b3cfbbd04 paragraph.py: add in support for backColor in <font> tag
rgbecker
parents: 3440
diff changeset
   650
    xs.backColor=None
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   651
    xs.cur_y -= leading
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   652
2936
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   653
def textTransformFrags(frags,style):
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   654
    tt = style.textTransform
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   655
    if tt:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   656
        tt=tt.lower()
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   657
        if tt=='lowercase':
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   658
            tt = unicode.lower
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   659
        elif tt=='uppercase':
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   660
            tt = unicode.upper
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   661
        elif  tt=='capitalize':
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   662
            tt = unicode.title
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   663
        elif tt=='none':
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   664
            return
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   665
        else:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   666
            raise ValueError('ParaStyle.textTransform value %r is invalid' % style.textTransform) 
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   667
        n = len(frags)
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   668
        if n==1:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   669
            #single fragment the easy case
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   670
            frags[0].text = tt(frags[0].text.decode('utf8')).encode('utf8')
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   671
        elif tt is unicode.title:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   672
            pb = True
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   673
            for f in frags:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   674
                t = f.text
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   675
                if not t: continue
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   676
                u = t.decode('utf8')
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   677
                if u.startswith(u' ') or pb:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   678
                    u = tt(u)
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   679
                else:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   680
                    i = u.find(u' ')
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   681
                    if i>=0:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   682
                        u = u[:i]+tt(u[i:])
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   683
                pb = u.endswith(u' ')
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   684
                f.text = u.encode('utf8')
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   685
        else:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   686
            for f in frags:
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   687
                t = f.text
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   688
                if not t: continue
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   689
                f.text = tt(t.decode('utf8')).encode('utf8')
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   690
2940
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   691
class cjkU(unicode):
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   692
    '''simple class to hold the frag corresponding to a str'''
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   693
    def __new__(cls,value,frag,encoding):
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   694
        self = unicode.__new__(cls,value)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   695
        self._frag = frag
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   696
        if hasattr(frag,'cbDefn'):
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   697
            w = getattr(frag.cbDefn,'width',0)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   698
            self._width = w
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   699
        else:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   700
            self._width = stringWidth(value,frag.fontName,frag.fontSize)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   701
        return self
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   702
    frag = property(lambda self: self._frag)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   703
    width = property(lambda self: self._width)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   704
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   705
def makeCJKParaLine(U,extraSpace,calcBounds):
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   706
    words = []
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   707
    CW = []
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   708
    f0 = FragLine()
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   709
    maxSize = maxAscent = minDescent = 0
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   710
    for u in U:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   711
        f = u.frag
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   712
        fontSize = f.fontSize
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   713
        if calcBounds:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   714
            cbDefn = getattr(f,'cbDefn',None)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   715
            if getattr(cbDefn,'width',0):
3434
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   716
                descent, ascent = imgVRange(imgNormV(cbDefn.height,fontSize),cbDefn.valign,fontSize)
2940
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   717
            else:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   718
                ascent, descent = getAscentDescent(f.fontName,fontSize)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   719
        else:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   720
            ascent, descent = getAscentDescent(f.fontName,fontSize)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   721
        maxSize = max(maxSize,fontSize)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   722
        maxAscent = max(maxAscent,ascent)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   723
        minDescent = min(minDescent,descent)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   724
        if not _sameFrag(f0,f):
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   725
            f0=f0.clone()
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   726
            f0.text = u''.join(CW)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   727
            words.append(f0)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   728
            CW = []
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   729
            f0 = f
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   730
        CW.append(u)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   731
    if CW:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   732
        f0=f0.clone()
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   733
        f0.text = u''.join(CW)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   734
        words.append(f0)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   735
    return FragLine(kind=1,extraSpace=extraSpace,wordCount=1,words=words[1:],fontSize=maxSize,ascent=maxAscent,descent=minDescent)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   736
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   737
def cjkFragSplit(frags, maxWidths, calcBounds, encoding='utf8'):
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   738
    '''This attempts to be wordSplit for frags using the dumb algorithm'''
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   739
    from reportlab.rl_config import _FUZZ
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   740
    U = []  #get a list of single glyphs with their widths etc etc
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   741
    for f in frags:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   742
        text = f.text
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   743
        if not isinstance(text,unicode):
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   744
            text = text.decode(encoding)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   745
        if text:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   746
            U.extend([cjkU(t,f,encoding) for t in text])
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   747
        else:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   748
            U.append(cjkU(text,f,encoding))
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   749
    lines = []
3156
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   750
    i = widthUsed = lineStartPos = 0
2940
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   751
    maxWidth = maxWidths[0]
3156
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   752
    nU = len(U)
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   753
    while i<nU:
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   754
        u = U[i]
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   755
        i += 1
2940
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   756
        w = u.width
3438
3cac4523a459 paragraph.py: fix cjk breaking for <img width='x%'
rgbecker
parents: 3434
diff changeset
   757
        if hasattr(w,'normalizedValue'):
3434
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
   758
            w._normalizer = maxWidth
3438
3cac4523a459 paragraph.py: fix cjk breaking for <img width='x%'
rgbecker
parents: 3434
diff changeset
   759
            w = w.normalizedValue(None)
2940
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   760
        widthUsed += w
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   761
        lineBreak = hasattr(u.frag,'lineBreak')
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   762
        endLine = (widthUsed>maxWidth + _FUZZ and widthUsed>0) or lineBreak
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   763
        if endLine:
3156
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   764
            extraSpace = maxWidth - widthUsed
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   765
            if not lineBreak:
3547
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   766
                if ord(u)<0x3000:
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   767
                    # we appear to be inside a non-Asian script section.
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   768
                    # (this is a very crude test but quick to compute).
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   769
                    # This is likely to be quite rare so the speed of the
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   770
                    # code below is hopefully not a big issue.  The main
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   771
                    # situation requiring this is that a document title
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   772
                    # with an english product name in it got cut.
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   773
                    
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   774
                    
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   775
                    # we count back and look for 
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   776
                    #  - a space-like character
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   777
                    #  - reversion to Kanji (which would be a good split point)
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   778
                    #  - in the worst case, roughly half way back along the line
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   779
                    limitCheck = (lineStartPos+i)>>1        #(arbitrary taste issue)
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   780
                    for j in xrange(i-1,limitCheck,-1):
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   781
                        uj = U[j]
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   782
                        if uj and category(uj)=='Zs' or ord(uj)>=0x3000:
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   783
                            k = j+1
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   784
                            if k<i:
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   785
                                j = k+1
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   786
                                extraSpace += sum(U[ii].width for ii in xrange(j,i))
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   787
                                w = U[k].width
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   788
                                u = U[k]
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   789
                                i = j
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   790
                                break
6d9cf43ebf9d western character modificaton for CJK splitting
rgbecker
parents: 3540
diff changeset
   791
3492
9f7288085d44 reportlab: fix support for cjk splitting
rgbecker
parents: 3489
diff changeset
   792
                #we are pushing this character back, but
9f7288085d44 reportlab: fix support for cjk splitting
rgbecker
parents: 3489
diff changeset
   793
                #the most important of the Japanese typography rules
9f7288085d44 reportlab: fix support for cjk splitting
rgbecker
parents: 3489
diff changeset
   794
                #if this character cannot start a line, wrap it up to this line so it hangs
3156
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   795
                #in the right margin. We won't do two or more though - that's unlikely and
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   796
                #would result in growing ugliness.
3489
5a3b2a822a33 paragraph.py: improve cjk frag splitting
rgbecker
parents: 3476
diff changeset
   797
                #and increase the extra space
5a3b2a822a33 paragraph.py: improve cjk frag splitting
rgbecker
parents: 3476
diff changeset
   798
                #bug fix contributed by Alexander Vasilenko <alexs.vasilenko@gmail.com>
3492
9f7288085d44 reportlab: fix support for cjk splitting
rgbecker
parents: 3489
diff changeset
   799
                if u not in ALL_CANNOT_START and i>lineStartPos+1:
9f7288085d44 reportlab: fix support for cjk splitting
rgbecker
parents: 3489
diff changeset
   800
                    #otherwise we need to push the character back
9f7288085d44 reportlab: fix support for cjk splitting
rgbecker
parents: 3489
diff changeset
   801
                    #the i>lineStart+1 condition ensures progress
3489
5a3b2a822a33 paragraph.py: improve cjk frag splitting
rgbecker
parents: 3476
diff changeset
   802
                    i -= 1
5a3b2a822a33 paragraph.py: improve cjk frag splitting
rgbecker
parents: 3476
diff changeset
   803
                    extraSpace += w
2940
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   804
            lines.append(makeCJKParaLine(U[lineStartPos:i],extraSpace,calcBounds))
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   805
            try:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   806
                maxWidth = maxWidths[len(lines)]
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   807
            except IndexError:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   808
                maxWidth = maxWidths[-1]  # use the last one
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   809
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   810
            lineStartPos = i
3489
5a3b2a822a33 paragraph.py: improve cjk frag splitting
rgbecker
parents: 3476
diff changeset
   811
            widthUsed = 0
3156
b696c4ce59a8 paragraph.py: attempt to fix up the br tag for CJK
rgbecker
parents: 3154
diff changeset
   812
2940
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   813
    #any characters left?
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   814
    if widthUsed > 0:
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   815
        lines.append(makeCJKParaLine(U[lineStartPos:],maxWidth-widthUsed,calcBounds))
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   816
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   817
    return ParaLines(kind=1,lines=lines)
a0e54b5117ce reportlab: add multi-frag cjk
rgbecker
parents: 2938
diff changeset
   818
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   819
class Paragraph(Flowable):
1940
baa0abc136c4 Henning von Bargen's caseSensitive flag
rgbecker
parents: 1915
diff changeset
   820
    """ Paragraph(text, style, bulletText=None, caseSensitive=1)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   821
        text a string of stuff to go into the paragraph.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   822
        style is a style definition as in reportlab.lib.styles.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   823
        bulletText is an optional bullet defintion.
1940
baa0abc136c4 Henning von Bargen's caseSensitive flag
rgbecker
parents: 1915
diff changeset
   824
        caseSensitive set this to 0 if you want the markup tags and their attributes to be case-insensitive.
316
e15cf6a28eb8 Documentation fixes
rgbecker
parents: 302
diff changeset
   825
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   826
        This class is a flowable that can format a block of text
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   827
        into a paragraph with a given style.
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   828
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   829
        The paragraph Text can contain XML-like markup including the tags:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   830
        <b> ... </b> - bold
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   831
        <i> ... </i> - italics
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   832
        <u> ... </u> - underline
2644
e762ad1c8909 reportlab: add support for strike through
rgbecker
parents: 2598
diff changeset
   833
        <strike> ... </strike> - strike through
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   834
        <super> ... </super> - superscript
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   835
        <sub> ... </sub> - subscript
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   836
        <font name=fontfamily/fontname color=colorname size=float>
3552
20ecbcc53c15 paraparser.py add support for <span style=stylename>
rgbecker
parents: 3547
diff changeset
   837
        <span name=fontfamily/fontname color=colorname backcolor=colorname size=float style=stylename>
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3159
diff changeset
   838
        <onDraw name=callable label="a label"/>
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3159
diff changeset
   839
        <index [name="callablecanvasattribute"] label="a label"/>
2670
3fdd642a7b76 minor cosmetic changes
rgbecker
parents: 2664
diff changeset
   840
        <link>link text</link>
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   841
        attributes of links
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   842
        size/fontSize=num
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   843
        name/face/fontName=name
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   844
        fg/textColor/color=color
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   845
        backcolor/backColor/bgcolor=color
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   846
        dest/destination/target/href/link=target
2745
0b44535fa1a5 paraparser/paragraph.py: fix comments
rgbecker
parents: 2744
diff changeset
   847
        <a>anchor text</a>
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   848
        attributes of anchors
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   849
        fontSize=num
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   850
        fontName=name
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   851
        fg/textColor/color=color
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   852
        backcolor/backColor/bgcolor=color
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   853
        href=href
2745
0b44535fa1a5 paraparser/paragraph.py: fix comments
rgbecker
parents: 2744
diff changeset
   854
        <a name="anchorpoint"/>
2670
3fdd642a7b76 minor cosmetic changes
rgbecker
parents: 2664
diff changeset
   855
        <unichar name="unicode character name"/>
3fdd642a7b76 minor cosmetic changes
rgbecker
parents: 2664
diff changeset
   856
        <unichar value="unicode code point"/>
2857
487dc2450eec reprotlab: inline images horizontal positioning OK
rgbecker
parents: 2841
diff changeset
   857
        <img src="path" width="1in" height="1in" valign="bottom"/>
3440
739ddbe7feab paaraparser/paragraph.py: add info re percentage in <img> for idea contributed by Roberto Alsina <ralsina@netmanagers.com.ar>
rgbecker
parents: 3438
diff changeset
   858
                width="w%" --> fontSize*w/100   idea from Roberto Alsina
739ddbe7feab paaraparser/paragraph.py: add info re percentage in <img> for idea contributed by Roberto Alsina <ralsina@netmanagers.com.ar>
rgbecker
parents: 3438
diff changeset
   859
                height="h%" --> linewidth*h/100 <ralsina@netmanagers.com.ar>
268
8414113fa500 more documentation changes
aaron_watters
parents: 253
diff changeset
   860
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   861
        The whole may be surrounded by <para> </para> tags
268
8414113fa500 more documentation changes
aaron_watters
parents: 253
diff changeset
   862
2791
806b0a5177c1 added docs on mapping
andy
parents: 2758
diff changeset
   863
        The <b> and <i> tags will work for the built-in fonts (Helvetica
806b0a5177c1 added docs on mapping
andy
parents: 2758
diff changeset
   864
        /Times / Courier).  For other fonts you need to register a family
806b0a5177c1 added docs on mapping
andy
parents: 2758
diff changeset
   865
        of 4 fonts using reportlab.pdfbase.pdfmetrics.registerFont; then
806b0a5177c1 added docs on mapping
andy
parents: 2758
diff changeset
   866
        use the addMapping function to tell the library that these 4 fonts
806b0a5177c1 added docs on mapping
andy
parents: 2758
diff changeset
   867
        form a family e.g.
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   868
        from reportlab.lib.fonts import addMapping
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   869
        addMapping('Vera', 0, 0, 'Vera')    #normal
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   870
        addMapping('Vera', 0, 1, 'Vera-Italic')    #italic
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   871
        addMapping('Vera', 1, 0, 'Vera-Bold')    #bold
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
   872
        addMapping('Vera', 1, 1, 'Vera-BoldItalic')    #italic and bold
2791
806b0a5177c1 added docs on mapping
andy
parents: 2758
diff changeset
   873
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   874
        It will also be able to handle any MathML specified Greek characters.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   875
    """
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   876
    def __init__(self, text, style, bulletText = None, frags=None, caseSensitive=1, encoding='utf8'):
2200
be0cfccc662a Fixed up tabs and whitespace in all source files
andy_robinson
parents: 2183
diff changeset
   877
        self.caseSensitive = caseSensitive
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   878
        self.encoding = encoding
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   879
        self._setup(text, style, bulletText, frags, cleanBlockQuotedText)
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   880
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   881
    def __repr__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   882
        n = self.__class__.__name__
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   883
        L = [n+"("]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   884
        keys = self.__dict__.keys()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   885
        for k in keys:
3088
6beaabf3fd4e paragraph.py: improve repr
rgbecker
parents: 3048
diff changeset
   886
            L.append('%s: %s' % (repr(k).replace("\n", " ").replace("  "," "),repr(getattr(self, k)).replace("\n", " ").replace("  "," ")))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   887
        L.append(") #"+n)
2881
41b10eb435c1 paragraph.py: fix autoLeading
rgbecker
parents: 2877
diff changeset
   888
        return '\n'.join(L)
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   889
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   890
    def _setup(self, text, style, bulletText, frags, cleaner):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   891
        if frags is None:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   892
            text = cleaner(text)
1940
baa0abc136c4 Henning von Bargen's caseSensitive flag
rgbecker
parents: 1915
diff changeset
   893
            _parser.caseSensitive = self.caseSensitive
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   894
            style, frags, bulletTextFrags = _parser.parse(text,style)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   895
            if frags is None:
2892
131b417f9845 paragraph: improved <a> syntax checks and better test
rgbecker
parents: 2888
diff changeset
   896
                raise ValueError("xml parser error (%s) in paragraph beginning\n'%s'"\
131b417f9845 paragraph: improved <a> syntax checks and better test
rgbecker
parents: 2888
diff changeset
   897
                    % (_parser.errors[0],text[:min(30,len(text))]))
2936
97860052e0fc paragraph.py: make textTransformFrags externall callable
rgbecker
parents: 2935
diff changeset
   898
            textTransformFrags(frags,style)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   899
            if bulletTextFrags: bulletText = bulletTextFrags
3540
bdb6c7856c23 paragraph.py: allow bulletText in styles to work
rgbecker
parents: 3539
diff changeset
   900
            elif bulletText is None:
bdb6c7856c23 paragraph.py: allow bulletText in styles to work
rgbecker
parents: 3539
diff changeset
   901
                bulletText = getattr(style,'bulletText',None)
279
e7d8b3631d5c Global sequencer put in the 'story builder'.
andy_robinson
parents: 268
diff changeset
   902
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   903
        #AR hack
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   904
        self.text = text
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   905
        self.frags = frags
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   906
        self.style = style
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   907
        self.bulletText = bulletText
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   908
        self.debug = 0  #turn this on to see a pretty one with all the margins etc.
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   909
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   910
    def wrap(self, availWidth, availHeight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   911
        # work out widths array for breaking
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   912
        self.width = availWidth
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   913
        style = self.style
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   914
        leftIndent = style.leftIndent
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   915
        first_line_width = availWidth - (leftIndent+style.firstLineIndent) - style.rightIndent
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   916
        later_widths = availWidth - leftIndent - style.rightIndent
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   917
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   918
        if style.wordWrap == 'CJK':
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   919
            #use Asian text wrap algorithm to break characters
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   920
            blPara = self.breakLinesCJK([first_line_width, later_widths])
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
   921
        else:
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   922
            blPara = self.breakLines([first_line_width, later_widths])
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   923
        self.blPara = blPara
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   924
        autoLeading = getattr(self,'autoLeading',getattr(style,'autoLeading',''))
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   925
        leading = style.leading
3179
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   926
        if blPara.kind==1:
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   927
            if autoLeading not in ('','off'):
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   928
                height = 0
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   929
                if autoLeading=='max':
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   930
                    for l in blPara.lines:
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   931
                        height += max(l.ascent-l.descent,leading)
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   932
                elif autoLeading=='min':
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   933
                    for l in blPara.lines:
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   934
                        height += l.ascent - l.descent
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   935
                else:
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   936
                    raise ValueError('invalid autoLeading value %r' % autoLeading)
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   937
            else:
3179
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   938
                height = len(blPara.lines) * leading
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   939
        else:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   940
            if autoLeading=='max':
3179
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   941
                leading = max(leading,blPara.ascent-blPara.descent)
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   942
            elif autoLeading=='min':
3179
4c4576402c25 paragraph.py: attempt to fix bug reported by VolkerHaas
rgbecker
parents: 3165
diff changeset
   943
                leading = blPara.ascent-blPara.descent
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   944
            height = len(blPara.lines) * leading
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   945
        self.height = height
2900
bbad3077c8f1 paragraph.py: fix simple paragraph vertical position
rgbecker
parents: 2899
diff changeset
   946
        return self.width, height
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   947
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   948
    def minWidth(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   949
        'Attempt to determine a minimum sensible width'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   950
        frags = self.frags
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   951
        nFrags= len(frags)
2467
5630a2b21a90 tables.py, paragraph.py: Gary Poster's layout improvement patch
rgbecker
parents: 2456
diff changeset
   952
        if not nFrags: return 0
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   953
        if nFrags==1:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   954
            f = frags[0]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   955
            fS = f.fontSize
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   956
            fN = f.fontName
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   957
            words = hasattr(f,'text') and split(f.text, ' ') or f.words
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   958
            func = lambda w, fS=fS, fN=fN: stringWidth(w,fN,fS)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   959
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   960
            words = _getFragWords(frags)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   961
            func  = lambda x: x[0]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   962
        return max(map(func,words))
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   963
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   964
    def _get_split_blParaFunc(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   965
        return self.blPara.kind==0 and _split_blParaSimple or _split_blParaHard
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   966
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   967
    def split(self,availWidth, availHeight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   968
        if len(self.frags)<=0: return []
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   969
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   970
        #the split information is all inside self.blPara
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   971
        if not hasattr(self,'blPara'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   972
            self.wrap(availWidth,availHeight)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   973
        blPara = self.blPara
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   974
        style = self.style
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   975
        autoLeading = getattr(self,'autoLeading',getattr(style,'autoLeading',''))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   976
        leading = style.leading
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
   977
        lines = blPara.lines
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   978
        if blPara.kind==1 and autoLeading not in ('','off'):
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   979
            s = height = 0
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   980
            if autoLeading=='max':
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   981
                for i,l in enumerate(blPara.lines):
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
   982
                    h = max(l.ascent-l.descent,leading)
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   983
                    n = height+h
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   984
                    if n>availHeight+1e-8:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   985
                        break
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   986
                    height = n
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   987
                    s = i+1
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   988
            elif autoLeading=='min':
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   989
                for i,l in enumerate(blPara.lines):
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
   990
                    n = height+l.ascent-l.descent
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   991
                    if n>availHeight+1e-8:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   992
                        break
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   993
                    height = n
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   994
                    s = i+1
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   995
            else:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   996
                raise ValueError('invalid autoLeading value %r' % autoLeading)
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   997
        else:
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   998
            l = leading
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
   999
            if autoLeading=='max':
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
  1000
                l = max(leading,1.2*style.fontSize)
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
  1001
            elif autoLeading=='min':
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
  1002
                l = 1.2*style.fontSize
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3322
diff changeset
  1003
            s = int(availHeight/(l*1.0))
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
  1004
            height = s*l
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
  1005
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1006
        n = len(lines)
3539
906fc3087160 paragraph.py: try to pick up allowWidows/Orphans from style
rgbecker
parents: 3493
diff changeset
  1007
        allowWidows = getattr(self,'allowWidows',getattr(style,'allowWidows',1))
906fc3087160 paragraph.py: try to pick up allowWidows/Orphans from style
rgbecker
parents: 3493
diff changeset
  1008
        allowOrphans = getattr(self,'allowOrphans',getattr(style,'allowOrphans',0))
2921
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1009
        if not allowOrphans:
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1010
            if s<=1:    #orphan?
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1011
                del self.blPara
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1012
                return []
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1013
        if n<=s: return [self]
2921
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1014
        if not allowWidows:
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1015
            if n==s+1: #widow?
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1016
                if (allowOrphans and n==3) or n>3:
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1017
                    s -= 1  #give the widow some company
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1018
                else:
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1019
                    del self.blPara #no room for adjustment; force the whole para onwards
d0bcee3e3785 reportlab: add in some widows/orphans control
rgbecker
parents: 2912
diff changeset
  1020
                    return []
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1021
        func = self._get_split_blParaFunc()
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
  1022
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1023
        P1=self.__class__(None,style,bulletText=self.bulletText,frags=func(blPara,0,s))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1024
        #this is a major hack
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1025
        P1.blPara = ParaLines(kind=1,lines=blPara.lines[0:s],aH=availHeight,aW=availWidth)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1026
        P1._JustifyLast = 1
2529
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2467
diff changeset
  1027
        P1._splitpara = 1
2836
66fb84201abe platypus: add support for autoLeading
rgbecker
parents: 2791
diff changeset
  1028
        P1.height = height
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1029
        P1.width = availWidth
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1030
        if style.firstLineIndent != 0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1031
            style = deepcopy(style)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1032
            style.firstLineIndent = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1033
        P2=self.__class__(None,style,bulletText=None,frags=func(blPara,s,n))
3027
702100ee1f8c paragraph.py: propagate some direct attributes
rgbecker
parents: 3022
diff changeset
  1034
        #propagate attributes that might be on self; suggestion from Dirk Holtwick
702100ee1f8c paragraph.py: propagate some direct attributes
rgbecker
parents: 3022
diff changeset
  1035
        for a in ('autoLeading',    #possible attributes that might be directly on self.
702100ee1f8c paragraph.py: propagate some direct attributes
rgbecker
parents: 3022
diff changeset
  1036
                ):
702100ee1f8c paragraph.py: propagate some direct attributes
rgbecker
parents: 3022
diff changeset
  1037
            if hasattr(self,a):
702100ee1f8c paragraph.py: propagate some direct attributes
rgbecker
parents: 3022
diff changeset
  1038
                setattr(P1,a,getattr(self,a))
702100ee1f8c paragraph.py: propagate some direct attributes
rgbecker
parents: 3022
diff changeset
  1039
                setattr(P2,a,getattr(self,a))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1040
        return [P1,P2]
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
  1041
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1042
    def draw(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1043
        #call another method for historical reasons.  Besides, I
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1044
        #suspect I will be playing with alternate drawing routines
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1045
        #so not doing it here makes it easier to switch.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1046
        self.drawPara(self.debug)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
  1047
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1048
    def breakLines(self, width):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1049
        """
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1050
        Returns a broken line structure. There are two cases
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
  1051
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1052
        A) For the simple case of a single formatting input fragment the output is
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1053
            A fragment specifier with
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1054
                - kind = 0
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1055
                - fontName, fontSize, leading, textColor
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1056
                - lines=  A list of lines
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1057
                        
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1058
                        Each line has two items.
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1059
                        
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1060
                        1. unused width in points
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1061
                        2. word list
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
  1062
2593
3adaab508968 reportlab: minor fixes to platypus, tests and fix jap splitting bug
rgbecker
parents: 2584
diff changeset
  1063
        B) When there is more than one input formatting fragment the output is
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1064
            A fragment specifier with
3031
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1065
               - kind = 1
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1066
               - lines=  A list of fragments each having fields
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1067
                            - extraspace (needed for justified)
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1068
                            - fontSize
6f90e7668adb docstrings cleaned up for epydoc
tim
parents: 3027
diff changeset
  1069
                            - words=word list
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1070
                                each word is itself a fragment with
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1071
                                various settings
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
  1072
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1073
        This structure can be used to easily draw paragraphs with the various alignments.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1074
        You can supply either a single width or a list of widths; the latter will have its
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1075
        last item repeated until necessary. A 2-element list is useful when there is a
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1076
        different first line indent; a longer list could be created to facilitate custom wraps
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1077
        around irregular objects."""
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
  1078
2932
bcdff7b8f469 platypus: initial try at textTransform style attribute
rgbecker
parents: 2923
diff changeset
  1079
        if not isinstance(width,(tuple,list)): maxWidths = [width]
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1080
        else: maxWidths = width
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1081
        lines = []
3192
d7d90caf7b4e paragraph.py: CJK splitting bug fix thanks to Volker Haas
rgbecker
parents: 3189
diff changeset
  1082
        self.height = lineno = 0
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1083
        style = self.style
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
  1084
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1085
        #for bullets, work out width and ensure we wrap the right amount onto line one
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1086
        _handleBulletWidth(self.bulletText,style,maxWidths)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
  1087
2366
7dd247980b7d minor twitching on Indenter
rgbecker
parents: 2341
diff changeset
  1088
        maxWidth = maxWidths[0]
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
  1089
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
  1090
        autoLeading = getattr(self,'autoLeading',getattr(style,'autoLeading',''))
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
  1091
        calcBounds = autoLeading not in ('','off')
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1092
        frags = self.frags
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1093
        nFrags= len(frags)
2750
05229265aff3 reportlab: fix special case <a> tag problem, add AnchorFlowable class
rgbecker
parents: 2745
diff changeset
  1094
        if nFrags==1 and not hasattr(frags[0],'cbDefn'):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1095
            f = frags[0]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1096
            fontSize = f.fontSize
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1097
            fontName = f.fontName
2888
edf4cc50dbc1 paragraph.py: better initialization for maxSize/maxAscent etc
rgbecker
parents: 2887
diff changeset
  1098
            ascent, descent = getAscentDescent(fontName,fontSize)
3493
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1099
            if hasattr(f,'text'):
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1100
                text = strip(f.text)
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1101
                if not text:
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1102
                    return f.clone(kind=0, lines=[],ascent=ascent,descent=descent,fontSize=fontSize)
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1103
                else:
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1104
                    words = split(text)
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1105
            else:
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1106
                words = f.words
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1107
                for w in words:
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1108
                    if strip(w): break
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1109
                else:
cff04ae591d7 paragraph.py: fix up some special cases for whitespace
rgbecker
parents: 3492
diff changeset
  1110
                    return f.clone(kind=0, lines=[],ascent=ascent,descent=descent,fontSize=fontSize)
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
  1111
            spaceWidth = stringWidth(' ', fontName, fontSize, self.encoding)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1112
            cLine = []
2883
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
  1113
            currentWidth = -spaceWidth   # hack to get around extra space for word 1
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1114
            for word in words:
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
  1115
                #this underscores my feeling that Unicode throughout would be easier!
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
  1116
                wordWidth = stringWidth(word, fontName, fontSize, self.encoding)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1117
                newWidth = currentWidth + spaceWidth + wordWidth
2670
3fdd642a7b76 minor cosmetic changes
rgbecker
parents: 2664
diff changeset
  1118
                if newWidth <= maxWidth or not len(cLine):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1119
                    # fit one more on this line
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1120
                    cLine.append(word)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1121
                    currentWidth = newWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1122
                else:
2575
0cba68b93555 reportlab-utf8 moved to trunk
rgbecker
parents: 2561
diff changeset
  1123
                    if currentWidth > self.width: self.width = currentWidth
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1124
                    #end of line
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1125
                    lines.append((maxWidth - currentWidth, cLine))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1126
                    cLine = [word]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1127
                    currentWidth = wordWidth
2593
3adaab508968 reportlab: minor fixes to platypus, tests and fix jap splitting bug
rgbecker
parents: 2584
diff changeset
  1128
                    lineno += 1
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1129
                    try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1130
                        maxWidth = maxWidths[lineno]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1131
                    except IndexError:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1132
                        maxWidth = maxWidths[-1]  # use the last one
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
  1133
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1134
            #deal with any leftovers on the final line
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1135
            if cLine!=[]:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1136
                if currentWidth>self.width: self.width = currentWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1137
                lines.append((maxWidth - currentWidth, cLine))
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
  1138
2886
7c66d24b6845 paragraph.py: fix some bugs in paragraph and bring xpreformatted nearer
rgbecker
parents: 2884
diff changeset
  1139
            return f.clone(kind=0, lines=lines,ascent=ascent,descent=descent,fontSize=fontSize)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1140
        elif nFrags<=0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1141
            return ParaLines(kind=0, fontSize=style.fontSize, fontName=style.fontName,
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
  1142
                            textColor=style.textColor, ascent=style.fontSize,descent=-0.2*style.fontSize,
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
  1143
                            lines=[])
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1144
        else:
2529
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2467
diff changeset
  1145
            if hasattr(self,'blPara') and getattr(self,'_splitpara',0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1146
                #NB this is an utter hack that awaits the proper information
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1147
                #preserving splitting algorithm
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1148
                return self.blPara
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1149
            n = 0
2758
c404102cb7e3 paragraph: add border styling and fix trailing <br/> bug
rgbecker
parents: 2750
diff changeset
  1150
            words = []
3434
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
  1151
            for w in _getFragWords(frags,maxWidth):
2883
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
  1152
                f=w[-1][0]
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
  1153
                fontName = f.fontName
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
  1154
                fontSize = f.fontSize
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
  1155
                spaceWidth = stringWidth(' ',fontName, fontSize)
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
  1156
2888
edf4cc50dbc1 paragraph.py: better initialization for maxSize/maxAscent etc
rgbecker
parents: 2887
diff changeset
  1157
                if not words:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1158
                    currentWidth = -spaceWidth   # hack to get around extra space for word 1
2883
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
  1159
                    maxSize = fontSize
2888
edf4cc50dbc1 paragraph.py: better initialization for maxSize/maxAscent etc
rgbecker
parents: 2887
diff changeset
  1160
                    maxAscent, minDescent = getAscentDescent(fontName,fontSize)
496
bb47cf5c2739 Layout error fixes
rgbecker
parents: 494
diff changeset
  1161
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1162
                wordWidth = w[0]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1163
                f = w[1][0]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1164
                if wordWidth>0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1165
                    newWidth = currentWidth + spaceWidth + wordWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1166
                else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1398
diff changeset
  1167
                    newWidth = currentWidth
2664
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
  1168
2758
c404102cb7e3 paragraph: add border styling and fix trailing <br/> bug
rgbecker
parents: 2750
diff changeset
  1169
                #test to see if this frag is a line break. If it is we will only act on it
2664
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
  1170
                #if the current width is non-negative or the previous thing was a deliberate lineBreak
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
  1171
                lineBreak = hasattr(f,'lineBreak')
2681
eb733ebd1ee7 paragraph.py: fix splitting cases for br tag
rgbecker
parents: 2670
diff changeset
  1172
                endLine = (newWidth>maxWidth and n>0) or lineBreak
2664
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
  1173
                if not endLine:
c9faa3a99e93 reportlab/platypus: <br/> tags now working
rgbecker
parents: 2663
diff changeset
  1174
                    if lineBreak: continue      #throw it away
2735
70cf084e5811 reportlab: fix justification space counting bug and improve tests
rgbecker
parents: 2708
diff changeset
  1175
                    nText = w[1][1]
70cf084e5811 reportlab: fix justification space counting bug and improve tests
rgbecker
parents: 2708
diff changeset
  1176
                    if nText: n += 1
2883
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
  1177
                    fontSize = f.fontSize
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
  1178
                    if calcBounds:
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
  1179
                        cbDefn = getattr(f,'cbDefn',None)
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
  1180
                        if getattr(cbDefn,'width',0):
3434
3c14212cc997 platypus: preliminary working version of % height/width for <img> tag
rgbecker
parents: 3373
diff changeset
  1181
                            descent,ascent = imgVRange(imgNormV(cbDefn.height,fontSize),cbDefn.valign,fontSize)
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
  1182
                        else:
2888
edf4cc50dbc1 paragraph.py: better initialization for maxSize/maxAscent etc
rgbecker
parents: 2887
diff changeset
  1183
                            ascent, descent = getAscentDescent(f.fontName,fontSize)
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
  1184
                    else:
2888
edf4cc50dbc1 paragraph.py: better initialization for maxSize/maxAscent etc
rgbecker
parents: 2887
diff changeset
  1185
                        ascent, descent = getAscentDescent(f.fontName,fontSize)
2883
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
  1186
                    maxSize = max(maxSize,fontSize)
212d93981b3c paragraph.py: use proper ascent/descent info
rgbecker
parents: 2882
diff changeset
  1187
                    maxAscent = max(maxAscent,ascent)
2863
63a40c330032 paragraph.py: restore & fix the attempt at ascent/descent auto leading
rgbecker
parents: 2862
diff changeset
  1188
                    minDescent = min(minDescent,descent)
2888
edf4cc50dbc1 paragraph.py: better initialization for maxSize/maxAscent etc
rgbecker
parents: 2887
diff changeset
  1189
                    if not words:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: