reportlab/platypus/flowables.py
author rgbecker
Thu, 02 Mar 2006 13:54:39 +0000
changeset 2569 f7ac857ad20d
parent 2562 3c77a70414d9
child 2575 0cba68b93555
permissions -rw-r--r--
flowables.py: attempt to fix up keepInFrame for one more case
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 2321
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2004
494
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 445
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/flowables.py
2321
3454f5b41760 Unicode and UTF8 support changes
andy
parents: 2284
diff changeset
     4
__version__=''' $Id$ '''
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     5
__doc__="""
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
     6
A flowable is a "floating element" in a document whose exact position is determined by the
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
     7
other elements that precede it, such as a paragraph, a diagram interspersed between paragraphs,
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
     8
a section header, etcetera.  Examples of non-flowables include page numbering annotations,
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
     9
headers, footers, fixed diagrams or logos, among others.
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    10
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    11
Flowables are defined here as objects which know how to determine their size and which
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    12
can draw themselves onto a page with respect to a relative "origin" position determined
426
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    13
at a higher level. The object's draw() method should assume that (0,0) corresponds to the
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    14
bottom left corner of the enclosing rectangle that will contain the object. The attributes
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    15
vAlign and hAlign may be used by 'packers' as hints as to how the object should be placed.
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    16
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    17
Some Flowables also know how to "split themselves".  For example a
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    18
long paragraph might split itself between one page and the next.
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    19
1490
d6d958390ff0 Added api instructions
rgbecker
parents: 1486
diff changeset
    20
Packers should set the canv attribute during wrap, split & draw operations to allow
d6d958390ff0 Added api instructions
rgbecker
parents: 1486
diff changeset
    21
the flowable to work out sizes etc in the proper context.
d6d958390ff0 Added api instructions
rgbecker
parents: 1486
diff changeset
    22
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    23
The "text" of a document usually consists mainly of a sequence of flowables which
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    24
flow into a document from top to bottom (with column and page breaks controlled by
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    25
higher level components).
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    26
"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    27
import os
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    28
import string
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    29
from copy import deepcopy
557
0ed50942f243 Allow for non string file names in Image.__init__
rgbecker
parents: 541
diff changeset
    30
from types import ListType, TupleType, StringType
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    31
2276
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
    32
from reportlab.lib.colors import red, gray, lightgrey
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
    33
from reportlab.lib.utils import fp_str
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    34
from reportlab.pdfbase import pdfutils
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    35
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
    36
from reportlab.rl_config import _FUZZ, overlapAttachedSpace
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
    37
__all__=('TraceInfo','Flowable','XBox','Preformatted','Image','Spacer','PageBreak','SlowPageBreak',
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
    38
        'CondPageBreak','KeepTogether','Macro','CallerMacro','ParagraphAndImage',
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
    39
        'FailOnWrap','HRFlowable','PTOContainer','KeepInFrame','UseUpSpace')
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    40
2113
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    41
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    42
class TraceInfo:
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    43
    "Holder for info about where an object originated"
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    44
    def __init__(self):
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    45
        self.srcFile = '(unknown)'
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    46
        self.startLineNo = -1
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    47
        self.startLinePos = -1
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    48
        self.endLineNo = -1
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    49
        self.endLinePos = -1
2200
be0cfccc662a Fixed up tabs and whitespace in all source files
andy_robinson
parents: 2192
diff changeset
    50
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    51
#############################################################
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    52
#   Flowable Objects - a base class and a few examples.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    53
#   One is just a box to get some metrics.  We also have
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    54
#   a paragraph, an image and a special 'page break'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    55
#   object which fills the space.
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    56
#############################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    57
class Flowable:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    58
    """Abstract base class for things to be drawn.  Key concepts:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    59
    1. It knows its size
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    60
    2. It draws in its own coordinate system (this requires the
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    61
        base API to provide a translate() function.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    62
    """
1917
25b37daf5ab7 Prepare for a more general idea of cell size
rgbecker
parents: 1882
diff changeset
    63
    _fixedWidth = 0         #assume wrap results depend on arguments?
25b37daf5ab7 Prepare for a more general idea of cell size
rgbecker
parents: 1882
diff changeset
    64
    _fixedHeight = 0
25b37daf5ab7 Prepare for a more general idea of cell size
rgbecker
parents: 1882
diff changeset
    65
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    66
    def __init__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    67
        self.width = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    68
        self.height = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    69
        self.wrapped = 0
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    70
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    71
        #these are hints to packers/frames as to how the floable should be positioned
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    72
        self.hAlign = 'LEFT'    #CENTER/CENTRE or RIGHT
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    73
        self.vAlign = 'BOTTOM'  #MIDDLE or TOP
426
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    74
2113
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    75
        #optional holder for trace info
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
    76
        self._traceInfo = None
2158
e9c34b93e317 Whoops, platform specific slashes.
andy_robinson
parents: 2113
diff changeset
    77
        self._showBoundary = None
2200
be0cfccc662a Fixed up tabs and whitespace in all source files
andy_robinson
parents: 2192
diff changeset
    78
1494
b0707e45102e Added _drawOn method
rgbecker
parents: 1491
diff changeset
    79
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    80
    def _drawOn(self,canv):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    81
        '''ensure canv is set on and then draw'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    82
        self.canv = canv
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    83
        self.draw()#this is the bit you overload
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    84
        del self.canv
1494
b0707e45102e Added _drawOn method
rgbecker
parents: 1491
diff changeset
    85
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    86
    def drawOn(self, canvas, x, y, _sW=0):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    87
        "Tell it to draw itself on the canvas.  Do not override"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    88
        if _sW and hasattr(self,'hAlign'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    89
            a = self.hAlign
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    90
            if a in ['CENTER','CENTRE']:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    91
                x = x + 0.5*_sW
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    92
            elif a == 'RIGHT':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    93
                x = x + _sW
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    94
            elif a != 'LEFT':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    95
                raise ValueError, "Bad hAlign value "+str(a)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    96
        canvas.saveState()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    97
        canvas.translate(x, y)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
    98
        self._drawOn(canvas)
2158
e9c34b93e317 Whoops, platform specific slashes.
andy_robinson
parents: 2113
diff changeset
    99
        if hasattr(self, '_showBoundary') and self._showBoundary:
e9c34b93e317 Whoops, platform specific slashes.
andy_robinson
parents: 2113
diff changeset
   100
            #diagnostic tool support
e9c34b93e317 Whoops, platform specific slashes.
andy_robinson
parents: 2113
diff changeset
   101
            canvas.setStrokeColor(gray)
e9c34b93e317 Whoops, platform specific slashes.
andy_robinson
parents: 2113
diff changeset
   102
            canvas.rect(0,0,self.width, self.height)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   103
        canvas.restoreState()
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   104
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   105
    def wrapOn(self, canv, aW, aH):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   106
        '''intended for use by packers allows setting the canvas on
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   107
        during the actual wrap'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   108
        self.canv = canv
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   109
        w, h = self.wrap(aW,aH)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   110
        del self.canv
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   111
        return w, h
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   112
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   113
    def wrap(self, availWidth, availHeight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   114
        """This will be called by the enclosing frame before objects
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   115
        are asked their size, drawn or whatever.  It returns the
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   116
        size actually used."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   117
        return (self.width, self.height)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   118
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   119
    def minWidth(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   120
        """This should return the minimum required width"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   121
        return getattr(self,'_minWidth',self.width)
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 760
diff changeset
   122
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   123
    def splitOn(self, canv, aW, aH):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   124
        '''intended for use by packers allows setting the canvas on
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   125
        during the actual split'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   126
        self.canv = canv
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   127
        S = self.split(aW,aH)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   128
        del self.canv
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   129
        return S
1491
8cb77f6ac40d Introduce wrapOn & splitOn
rgbecker
parents: 1490
diff changeset
   130
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   131
    def split(self, availWidth, availheight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   132
        """This will be called by more sophisticated frames when
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   133
        wrap fails. Stupid flowables should return []. Clever flowables
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   134
        should split themselves and return a list of flowables"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   135
        return []
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   136
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   137
    def getKeepWithNext(self):
1879
c1dc90e2f470 Fix trivial spelling burble
rgbecker
parents: 1768
diff changeset
   138
        """returns boolean determining whether the next flowable should stay with this one"""
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   139
        if hasattr(self,'keepWithNext'): return self.keepWithNext
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   140
        elif hasattr(self,'style') and hasattr(self.style,'keepWithNext'): return self.style.keepWithNext
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   141
        else: return 0
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   142
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   143
    def getSpaceAfter(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   144
        """returns how much space should follow this item if another item follows on the same page."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   145
        if hasattr(self,'spaceAfter'): return self.spaceAfter
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   146
        elif hasattr(self,'style') and hasattr(self.style,'spaceAfter'): return self.style.spaceAfter
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   147
        else: return 0
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   148
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   149
    def getSpaceBefore(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   150
        """returns how much space should precede this item if another item precedess on the same page."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   151
        if hasattr(self,'spaceBefore'): return self.spaceBefore
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   152
        elif hasattr(self,'style') and hasattr(self.style,'spaceBefore'): return self.style.spaceBefore
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   153
        else: return 0
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   154
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   155
    def isIndexing(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   156
        """Hook for IndexingFlowables - things which have cross references"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   157
        return 0
512
c12ae96634d5 Added working table of contents framework
andy_robinson
parents: 496
diff changeset
   158
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   159
    def identity(self, maxLen=None):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   160
        '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   161
        This method should attempt to return a string that can be used to identify
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   162
        a particular flowable uniquely. The result can then be used for debugging
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   163
        and or error printouts
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   164
        '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   165
        if hasattr(self, 'getPlainText'):
2172
2740f571bd24 Fixes to cope with rml2pdf weirds
rgbecker
parents: 2158
diff changeset
   166
            r = self.getPlainText(identify=1)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   167
        elif hasattr(self, 'text'):
2461
9c24d39d05e8 enhanced decimal alignment
andy
parents: 2451
diff changeset
   168
            r = str(self.text)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   169
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   170
            r = '...'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   171
        if r and maxLen:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   172
            r = r[:maxLen]
2531
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   173
        return "<%s at %s%s>%s" % (self.__class__.__name__, hex(id(self)), self._frameName(), r)
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   174
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   175
    def _frameName(self):
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   176
        f = getattr(self,'_frame',None)
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   177
        if f and f.id: return ' frame=%s' % f.id
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   178
        return ''
1103
857af510186d Added identity method to Flowables
rgbecker
parents: 1036
diff changeset
   179
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   180
class XBox(Flowable):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   181
    """Example flowable - a box with an x through it and a caption.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   182
    This has a known size, so does not need to respond to wrap()."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   183
    def __init__(self, width, height, text = 'A Box'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   184
        Flowable.__init__(self)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   185
        self.width = width
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   186
        self.height = height
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   187
        self.text = text
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   188
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   189
    def __repr__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   190
        return "XBox(w=%s, h=%s, t=%s)" % (self.width, self.height, self.text)
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 512
diff changeset
   191
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   192
    def draw(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   193
        self.canv.rect(0, 0, self.width, self.height)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   194
        self.canv.line(0, 0, self.width, self.height)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   195
        self.canv.line(0, self.height, self.width, 0)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   196
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   197
        #centre the text
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   198
        self.canv.setFont('Times-Roman',12)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   199
        self.canv.drawCentredString(0.5*self.width, 0.5*self.height, self.text)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   200
445
8b64b9812ca6 Fixes to _dedenter
rgbecker
parents: 442
diff changeset
   201
def _trimEmptyLines(lines):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   202
    #don't want the first or last to be empty
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   203
    while len(lines) and string.strip(lines[0]) == '':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   204
        lines = lines[1:]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   205
    while len(lines) and string.strip(lines[-1]) == '':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   206
        lines = lines[:-1]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   207
    return lines
445
8b64b9812ca6 Fixes to _dedenter
rgbecker
parents: 442
diff changeset
   208
442
e3eac15cddbd XPreformatted first fixes; now runs
rgbecker
parents: 426
diff changeset
   209
def _dedenter(text,dedent=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   210
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   211
    tidy up text - carefully, it is probably code.  If people want to
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   212
    indent code within a source script, you can supply an arg to dedent
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   213
    and it will chop off that many character, otherwise it leaves
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   214
    left edge intact.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   215
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   216
    lines = string.split(text, '\n')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   217
    if dedent>0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   218
        templines = _trimEmptyLines(lines)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   219
        lines = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   220
        for line in templines:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   221
            line = string.rstrip(line[dedent:])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   222
            lines.append(line)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   223
    else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   224
        lines = _trimEmptyLines(lines)
445
8b64b9812ca6 Fixes to _dedenter
rgbecker
parents: 442
diff changeset
   225
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   226
    return lines
442
e3eac15cddbd XPreformatted first fixes; now runs
rgbecker
parents: 426
diff changeset
   227
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   228
class Preformatted(Flowable):
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   229
    """This is like the HTML <PRE> tag.
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   230
    It attempts to display text exactly as you typed it in a fixed width "typewriter" font.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   231
    The line breaks are exactly where you put
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   232
    them, and it will not be wrapped."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   233
    def __init__(self, text, style, bulletText = None, dedent=0):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   234
        """text is the text to display. If dedent is set then common leading space
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   235
        will be chopped off the front (for example if the entire text is indented
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   236
        6 spaces or more then each line will have 6 spaces removed from the front).
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   237
        """
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   238
        self.style = style
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   239
        self.bulletText = bulletText
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   240
        self.lines = _dedenter(text,dedent)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   241
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   242
    def __repr__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   243
        bT = self.bulletText
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   244
        H = "Preformatted("
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   245
        if bT is not None:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   246
            H = "Preformatted(bulletText=%s," % repr(bT)
2023
2d5def514733 Fix typo found by Christoph Devenoges
rgbecker
parents: 1994
diff changeset
   247
        return "%s'''\\ \n%s''')" % (H, string.join(self.lines,'\n'))
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 512
diff changeset
   248
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   249
    def wrap(self, availWidth, availHeight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   250
        self.width = availWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   251
        self.height = self.style.leading*len(self.lines)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   252
        return (self.width, self.height)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   253
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   254
    def split(self, availWidth, availHeight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   255
        #returns two Preformatted objects
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   256
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   257
        #not sure why they can be called with a negative height
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   258
        if availHeight < self.style.leading:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   259
            return []
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   260
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   261
        linesThatFit = int(availHeight * 1.0 / self.style.leading)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   262
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   263
        text1 = string.join(self.lines[0:linesThatFit], '\n')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   264
        text2 = string.join(self.lines[linesThatFit:], '\n')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   265
        style = self.style
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   266
        if style.firstLineIndent != 0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   267
            style = deepcopy(style)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   268
            style.firstLineIndent = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   269
        return [Preformatted(text1, self.style), Preformatted(text2, style)]
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   270
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   271
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   272
    def draw(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   273
        #call another method for historical reasons.  Besides, I
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   274
        #suspect I will be playing with alternate drawing routines
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   275
        #so not doing it here makes it easier to switch.
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   276
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   277
        cur_x = self.style.leftIndent
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   278
        cur_y = self.height - self.style.fontSize
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   279
        self.canv.addLiteral('%PreformattedPara')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   280
        if self.style.textColor:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   281
            self.canv.setFillColor(self.style.textColor)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   282
        tx = self.canv.beginText(cur_x, cur_y)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   283
        #set up the font etc.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   284
        tx.setFont( self.style.fontName,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   285
                    self.style.fontSize,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   286
                    self.style.leading)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   287
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   288
        for text in self.lines:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   289
            tx.textLine(text)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   290
        self.canv.drawText(tx)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   291
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   292
class Image(Flowable):
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2023
diff changeset
   293
    """an image (digital picture).  Formats supported by PIL/Java 1.4 (the Python/Java Imaging Library
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   294
       are supported.  At the present time images as flowables are always centered horozontally
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   295
       in the frame. We allow for two kinds of lazyness to allow for many images in a document
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   296
       which could lead to file handle starvation.
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   297
       lazy=1 don't open image until required.
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   298
       lazy=2 open image when required then shut it.
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   299
    """
1917
25b37daf5ab7 Prepare for a more general idea of cell size
rgbecker
parents: 1882
diff changeset
   300
    _fixedWidth = 1
25b37daf5ab7 Prepare for a more general idea of cell size
rgbecker
parents: 1882
diff changeset
   301
    _fixedHeight = 1
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   302
    def __init__(self, filename, width=None, height=None, kind='direct', mask="auto", lazy=1):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   303
        """If size to draw at not specified, get it from the image."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   304
        self.hAlign = 'CENTER'
1880
5444027dd195 Allow for image transparancy mask
rgbecker
parents: 1879
diff changeset
   305
        self._mask = mask
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   306
        # if it is a JPEG, will be inlined within the file -
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   307
        # but we still need to know its size now
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   308
        fp = hasattr(filename,'read')
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   309
        if fp:
2237
005d070deb87 Fix up more Image cases
rgbecker
parents: 2200
diff changeset
   310
            self._file = filename
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   311
            self.filename = `filename`
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   312
        else:
2237
005d070deb87 Fix up more Image cases
rgbecker
parents: 2200
diff changeset
   313
            self._file = self.filename = filename
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   314
        if not fp and os.path.splitext(filename)[1] in ['.jpg', '.JPG', '.jpeg', '.JPEG']:
2241
5bf5d0f03603 Make Image to use open_for_read
rgbecker
parents: 2237
diff changeset
   315
            from reportlab.lib.utils import open_for_read
5bf5d0f03603 Make Image to use open_for_read
rgbecker
parents: 2237
diff changeset
   316
            f = open_for_read(filename, 'b')
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   317
            info = pdfutils.readJPEGInfo(f)
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   318
            f.close()
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   319
            self.imageWidth = info[0]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   320
            self.imageHeight = info[1]
2404
8bc8743cc5ec flowables.py: fix no PIL jpg problem reported by Martin.Zohlhuber@tttech.com
rgbecker
parents: 2403
diff changeset
   321
            self._img = None
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   322
            self._setup(width,height,kind,0)
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   323
        elif fp:
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   324
            self._setup(width,height,kind,0)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   325
        else:
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   326
            self._setup(width,height,kind,lazy)
1477
dc5c2ba1005a Allow for various Image kinds
rgbecker
parents: 1426
diff changeset
   327
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   328
    def _setup(self,width,height,kind,lazy):
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   329
        self._lazy = lazy
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   330
        self._width = width
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   331
        self._height = height
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   332
        self._kind = kind
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   333
        if lazy<=0: self._setup_inner()
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   334
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   335
    def _setup_inner(self):
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   336
        width = self._width
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   337
        height = self._height
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   338
        kind = self._kind
2404
8bc8743cc5ec flowables.py: fix no PIL jpg problem reported by Martin.Zohlhuber@tttech.com
rgbecker
parents: 2403
diff changeset
   339
        img = self._img
8bc8743cc5ec flowables.py: fix no PIL jpg problem reported by Martin.Zohlhuber@tttech.com
rgbecker
parents: 2403
diff changeset
   340
        if img: self.imageWidth, self.imageHeight = img.getSize()
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   341
        if self._lazy>=2: del self._img
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   342
        if kind in ['direct','absolute']:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   343
            self.drawWidth = width or self.imageWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   344
            self.drawHeight = height or self.imageHeight
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   345
        elif kind in ['percentage','%']:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   346
            self.drawWidth = self.imageWidth*width*0.01
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   347
            self.drawHeight = self.imageHeight*height*0.01
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   348
        elif kind in ['bound','proportional']:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   349
            factor = min(float(width)/self.imageWidth,float(height)/self.imageHeight)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   350
            self.drawWidth = self.imageWidth*factor
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   351
            self.drawHeight = self.imageHeight*factor
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   352
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   353
    def __getattr__(self,a):
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   354
        if a=='_img':
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   355
            from reportlab.lib.utils import ImageReader  #this may raise an error
2237
005d070deb87 Fix up more Image cases
rgbecker
parents: 2200
diff changeset
   356
            self._img = ImageReader(self._file)
005d070deb87 Fix up more Image cases
rgbecker
parents: 2200
diff changeset
   357
            del self._file
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   358
            return self._img
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   359
        elif a in ('drawWidth','drawHeight','imageWidth','imageHeight'):
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   360
            self._setup_inner()
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   361
            return self.__dict__[a]
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   362
        raise AttributeError(a)
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   363
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   364
    def wrap(self, availWidth, availHeight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   365
        #the caller may decide it does not fit.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   366
        return (self.drawWidth, self.drawHeight)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   367
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   368
    def draw(self):
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   369
        lazy = self._lazy
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   370
        if lazy>=2: self._lazy = 1
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   371
        self.canv.drawImage(    self._img or self.filename,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   372
                                0,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   373
                                0,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   374
                                self.drawWidth,
1880
5444027dd195 Allow for image transparancy mask
rgbecker
parents: 1879
diff changeset
   375
                                self.drawHeight,
1882
ce334775a5b2 Fixed mask bug (lexical/dynamic scoping?)
andy_robinson
parents: 1880
diff changeset
   376
                                mask=self._mask,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   377
                                )
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   378
        if lazy>=2:
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   379
            self._img = None
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   380
            self._lazy = lazy
1103
857af510186d Added identity method to Flowables
rgbecker
parents: 1036
diff changeset
   381
2192
955d4bf3b9d2 Candidate fix for infinite looping
andy_robinson
parents: 2172
diff changeset
   382
    def identity(self,maxLen=None):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   383
        r = Flowable.identity(self,maxLen)
2080
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   384
        if r[-4:]=='>...' and type(self.filename) is StringType:
39156f56ab6f Added in lazy Image stuff
rgbecker
parents: 2045
diff changeset
   385
            r = "%s filename=%s>" % (r[:-4],self.filename)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   386
        return r
1103
857af510186d Added identity method to Flowables
rgbecker
parents: 1036
diff changeset
   387
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   388
class Spacer(Flowable):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   389
    """A spacer just takes up space and doesn't draw anything - it guarantees
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   390
       a gap between objects."""
1917
25b37daf5ab7 Prepare for a more general idea of cell size
rgbecker
parents: 1882
diff changeset
   391
    _fixedWidth = 1
25b37daf5ab7 Prepare for a more general idea of cell size
rgbecker
parents: 1882
diff changeset
   392
    _fixedHeight = 1
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   393
    def __init__(self, width, height):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   394
        self.width = width
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   395
        self.height = height
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   396
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   397
    def __repr__(self):
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   398
        return "%s(%s, %s)" % (self.__class__.__name__,self.width, self.height)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   399
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   400
    def draw(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   401
        pass
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   402
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   403
class UseUpSpace(Flowable):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   404
    def __init__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   405
        pass
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   406
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   407
    def __repr__(self):
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   408
        return "%s()" % self.__class__.__name__
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   409
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   410
    def wrap(self, availWidth, availHeight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   411
        self.width = availWidth
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   412
        self.height = availHeight
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   413
        return (availWidth,availHeight)  #step back a point
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   414
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   415
    def draw(self):
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   416
        pass
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   417
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   418
class PageBreak(UseUpSpace):
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   419
    """Move on to the next page in the document.
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   420
       This works by consuming all remaining space in the frame!"""
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   421
2408
1c5e79611b59 flowables: add SlowPageBreak
rgbecker
parents: 2404
diff changeset
   422
class SlowPageBreak(PageBreak):
1c5e79611b59 flowables: add SlowPageBreak
rgbecker
parents: 2404
diff changeset
   423
    pass
1c5e79611b59 flowables: add SlowPageBreak
rgbecker
parents: 2404
diff changeset
   424
307
c439e402b404 Added CondPageBreak
rgbecker
parents: 268
diff changeset
   425
class CondPageBreak(Spacer):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   426
    """Throw a page if not enough vertical space"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   427
    def __init__(self, height):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   428
        self.height = height
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   429
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   430
    def __repr__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   431
        return "CondPageBreak(%s)" %(self.height,)
307
c439e402b404 Added CondPageBreak
rgbecker
parents: 268
diff changeset
   432
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   433
    def wrap(self, availWidth, availHeight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   434
        if availHeight<self.height:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   435
            return (availWidth, availHeight)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   436
        return (0, 0)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   437
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   438
def _listWrapOn(F,availWidth,canv,mergeSpace=1,obj=None):
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   439
    '''return max width, required height for a list of flowables F'''
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   440
    W = 0
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   441
    H = 0
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   442
    pS = 0
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   443
    atTop = 1
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   444
    for f in F:
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   445
        w,h = f.wrapOn(canv,availWidth,0xfffffff)
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   446
        if w<=_FUZZ or h<=_FUZZ: continue
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   447
        W = max(W,w)
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   448
        H += h
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   449
        if not atTop:
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   450
            h = f.getSpaceBefore()
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   451
            if mergeSpace: h = max(h-pS,0) 
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   452
            H += h
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   453
        else:
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   454
            if obj is not None: obj._spaceBefore = f.getSpaceBefore()
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   455
            atTop = 0
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   456
        pS = f.getSpaceAfter()
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   457
        H += pS
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   458
    if obj is not None: obj._spaceAfter = pS
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   459
    return W, H-pS
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   460
2449
47b15f941325 platypus: attempt to make KeepTogether/keepWithNext more robust
rgbecker
parents: 2408
diff changeset
   461
def _flowableSublist(V):
2392
6c59b0eb312d table color cycle changes
andy
parents: 2388
diff changeset
   462
    "if it isn't a list or tuple, wrap it in a list"
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   463
    if type(V) not in (ListType, TupleType): V = V is not None and [V] or []
2450
f2ae0122a66a platypus: make LCActionFlowable the bad ones
rgbecker
parents: 2449
diff changeset
   464
    from doctemplate import LCActionFlowable
2451
19bf750c3c26 flowables.py: fix 2.1 breakage
rgbecker
parents: 2450
diff changeset
   465
    assert not [x for x in V if isinstance(x,LCActionFlowable)],'LCActionFlowables not allowed in sublists'
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   466
    return V
558
f9013e25af9d Added a random text module
andy_robinson
parents: 557
diff changeset
   467
367
ca1adb0294f0 Added KeepTogether
rgbecker
parents: 307
diff changeset
   468
class KeepTogether(Flowable):
1994
fdb2334c338a Attempt to allow for overlong KeepTogethers
rgbecker
parents: 1917
diff changeset
   469
    def __init__(self,flowables,maxHeight=None):
2449
47b15f941325 platypus: attempt to make KeepTogether/keepWithNext more robust
rgbecker
parents: 2408
diff changeset
   470
        self._flowables = _flowableSublist(flowables)
1994
fdb2334c338a Attempt to allow for overlong KeepTogethers
rgbecker
parents: 1917
diff changeset
   471
        self._maxHeight = maxHeight
367
ca1adb0294f0 Added KeepTogether
rgbecker
parents: 307
diff changeset
   472
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   473
    def __repr__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   474
        f = self._flowables
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   475
        L = map(repr,f)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   476
        import string
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   477
        L = "\n"+string.join(L, "\n")
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   478
        L = string.replace(L, "\n", "\n  ")
1994
fdb2334c338a Attempt to allow for overlong KeepTogethers
rgbecker
parents: 1917
diff changeset
   479
        return "KeepTogether(%s,maxHeight=%s) # end KeepTogether" % (L,self._maxHeight)
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 512
diff changeset
   480
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   481
    def wrap(self, aW, aH):
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   482
        W,H = _listWrapOn(self._flowables,aW,self.canv)
1994
fdb2334c338a Attempt to allow for overlong KeepTogethers
rgbecker
parents: 1917
diff changeset
   483
        self._CPage = (H>aH) and (not self._maxHeight or H<=self._maxHeight)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   484
        return W, 0xffffff  # force a split
367
ca1adb0294f0 Added KeepTogether
rgbecker
parents: 307
diff changeset
   485
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   486
    def split(self, aW, aH):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   487
        S = getattr(self,'_CPage',1) and [CondPageBreak(aH+1)] or []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   488
        for f in self._flowables: S.append(f)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   489
        return S
367
ca1adb0294f0 Added KeepTogether
rgbecker
parents: 307
diff changeset
   490
2461
9c24d39d05e8 enhanced decimal alignment
andy
parents: 2451
diff changeset
   491
    def identity(self):
2531
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   492
        return "<KeepTogether at %s%s> containing :%s" % (hex(id(self)),self._frameName(),"\n".join([f.identity() for f in self._flowables]))
2461
9c24d39d05e8 enhanced decimal alignment
andy
parents: 2451
diff changeset
   493
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   494
class Macro(Flowable):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   495
    """This is not actually drawn (i.e. it has zero height)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   496
    but is executed when it would fit in the frame.  Allows direct
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   497
    access to the canvas through the object 'canvas'"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   498
    def __init__(self, command):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   499
        self.command = command
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   500
    def __repr__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   501
        return "Macro(%s)" % repr(self.command)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   502
    def wrap(self, availWidth, availHeight):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   503
        return (0,0)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1554
diff changeset
   504
    def draw(self):
1768
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   505
        exec self.command in globals(), {'canvas':self.canv}
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   506
2403
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   507
class CallerMacro(Flowable):
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   508
    '''
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   509
    like Macro, but with callable command(s)
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   510
    drawCallable(self)
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   511
    wrapCallable(self,aW,aH)
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   512
    '''
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   513
    def __init__(self, drawCallable=None, wrapCallable=None):
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   514
        _ = lambda *args: None
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   515
        self._drawCallable = drawCallable or _
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   516
        self._wrapCallable = wrapCallable or _
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   517
    def __repr__(self):
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   518
        return "CallerMacro(%s)" % repr(self.command)
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   519
    def wrap(self, aW, aH):
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   520
        self._wrapCallable(self,aW,aH)
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   521
        return (0,0)
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   522
    def draw(self):
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   523
        self._drawCallable(self)
cbfa501fb840 canvasadapter.py fixes
rgbecker
parents: 2392
diff changeset
   524
1768
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   525
class ParagraphAndImage(Flowable):
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   526
    '''combine a Paragraph and an Image'''
2557
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   527
    def __init__(self,P,I,xpad=3,ypad=3,side='right'):
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   528
        self.P = P
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   529
        self.I = I
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   530
        self.xpad = xpad
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   531
        self.ypad = ypad
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   532
        self._side = side
1768
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   533
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   534
    def wrap(self,availWidth,availHeight):
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   535
        wI, hI = self.I.wrap(availWidth,availHeight)
2557
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   536
        self.wI = wI
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   537
        self.hI = hI
1768
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   538
        # work out widths array for breaking
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   539
        self.width = availWidth
2557
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   540
        P = self.P
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   541
        style = P.style
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   542
        xpad = self.xpad
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   543
        ypad = self.ypad
1768
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   544
        leading = style.leading
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   545
        leftIndent = style.leftIndent
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   546
        later_widths = availWidth - leftIndent - style.rightIndent
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   547
        intermediate_widths = later_widths - xpad - wI
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   548
        first_line_width = intermediate_widths - style.firstLineIndent
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   549
        P.width = 0
2557
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   550
        nIW = int((hI+ypad)/leading)
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   551
        P.blPara = P.breakLines([first_line_width] + nIW*[intermediate_widths]+[later_widths])
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   552
        if self._side=='left':
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   553
            self._offsets = [wI+xpad]*(1+nIW)+[0]
1768
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   554
        P.height = len(P.blPara.lines)*leading
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   555
        self.height = max(hI,P.height)
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   556
        return (self.width, self.height)
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   557
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   558
    def split(self,availWidth, availHeight):
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   559
        P, wI, hI, ypad = self.P, self.wI, self.hI, self.ypad
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   560
        if hI+ypad>availHeight or len(P.frags)<=0: return []
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   561
        S = P.split(availWidth,availHeight)
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   562
        if not S: return S
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   563
        P = self.P = S[0]
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   564
        del S[0]
2557
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   565
        style = P.style
1768
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   566
        P.height = len(self.P.blPara.lines)*style.leading
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   567
        self.height = max(hI,P.height)
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   568
        return [self]+S
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   569
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   570
    def draw(self):
ea95b92748cc Added ParagraphAndImage
rgbecker
parents: 1683
diff changeset
   571
        canv = self.canv
2557
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   572
        if self._side=='left':
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   573
            self.I.drawOn(canv,0,self.height-self.hI)
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   574
            self.P._offsets = self._offsets
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   575
            try:
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   576
                self.P.drawOn(canv,0,0)
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   577
            finally:
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   578
                del self.P._offsets
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   579
        else:
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   580
            self.I.drawOn(canv,self.width-self.wI-self.xpad,self.height-self.hI)
d84c18fb377f added _offsets handling to paragraph for flow around on left side
rgbecker
parents: 2542
diff changeset
   581
            self.P.drawOn(canv,0,0)
2113
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   582
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   583
class FailOnWrap(Flowable):
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   584
    def wrap(self, availWidth, availHeight):
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   585
        raise ValueError("FailOnWrap flowable wrapped and failing as ordered!")
2200
be0cfccc662a Fixed up tabs and whitespace in all source files
andy_robinson
parents: 2192
diff changeset
   586
2113
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   587
    def draw(self):
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   588
        pass
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   589
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   590
class FailOnDraw(Flowable):
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   591
    def wrap(self, availWidth, availHeight):
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   592
        return (0,0)
2200
be0cfccc662a Fixed up tabs and whitespace in all source files
andy_robinson
parents: 2192
diff changeset
   593
2113
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   594
    def draw(self):
e82d8b3880d8 Preliminary support for tracing through doc builds
andy_robinson
parents: 2080
diff changeset
   595
        raise ValueError("FailOnDraw flowable drawn, and failing as ordered!")
2276
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   596
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   597
class HRFlowable(Flowable):
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   598
    '''Like the hr tag'''
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   599
    def __init__(self,
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   600
            width="80%",
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   601
            thickness=1,
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   602
            lineCap='round',
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   603
            color=lightgrey,
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   604
            spaceBefore=1, spaceAfter=1,
2523
0473810aff11 platypus: fix up None defaults for table line commands, add HRFlowable dash arg
rgbecker
parents: 2461
diff changeset
   605
            hAlign='CENTER', vAlign='BOTTOM',
0473810aff11 platypus: fix up None defaults for table line commands, add HRFlowable dash arg
rgbecker
parents: 2461
diff changeset
   606
            dash=None):
2276
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   607
        Flowable.__init__(self)
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   608
        self.width = width
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   609
        self.lineWidth = thickness
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   610
        self.lineCap=lineCap
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   611
        self.spaceBefore = spaceBefore
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   612
        self.spaceAfter = spaceAfter
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   613
        self.color = color
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   614
        self.hAlign = hAlign
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   615
        self.vAlign = vAlign
2523
0473810aff11 platypus: fix up None defaults for table line commands, add HRFlowable dash arg
rgbecker
parents: 2461
diff changeset
   616
        self.dash = dash
2276
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   617
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   618
    def __repr__(self):
2284
b181b45c6792 Minor changes
rgbecker
parents: 2276
diff changeset
   619
        return "HRFlowable(width=%s, height=%s)" % (self.width, self.height)
2276
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   620
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   621
    def wrap(self, availWidth, availHeight):
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   622
        w = self.width
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   623
        if type(w) is type(''):
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   624
            w = w.strip()
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   625
            if w.endswith('%'): w = availWidth*float(w[:-1])*0.01
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   626
            else: w = float(w)
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   627
        w = min(w,availWidth)
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   628
        self._width = w
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   629
        return w, self.lineWidth
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   630
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   631
    def draw(self):
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   632
        canv = self.canv
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   633
        canv.saveState()
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   634
        canv.setLineWidth(self.lineWidth)
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   635
        canv.setLineCap({'butt':0,'round':1, 'square': 2}[self.lineCap.lower()])
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   636
        canv.setStrokeColor(self.color)
2523
0473810aff11 platypus: fix up None defaults for table line commands, add HRFlowable dash arg
rgbecker
parents: 2461
diff changeset
   637
        if self.dash: canv.setDash(self.dash)
2276
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   638
        canv.line(0, 0, self._width, self.height)
10fc2ce1114f Added HRFlowable
rgbecker
parents: 2241
diff changeset
   639
        canv.restoreState()
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   640
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   641
class _PTOInfo:
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   642
    def __init__(self,trailer,header):
2449
47b15f941325 platypus: attempt to make KeepTogether/keepWithNext more robust
rgbecker
parents: 2408
diff changeset
   643
        self.trailer = _flowableSublist(trailer)
47b15f941325 platypus: attempt to make KeepTogether/keepWithNext more robust
rgbecker
parents: 2408
diff changeset
   644
        self.header = _flowableSublist(header)
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   645
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   646
class _Container:   #Abstract some common container like behaviour
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   647
    def getSpaceBefore(self):
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   648
        for c in self._content:
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   649
            if not hasattr(c,'frameAction'):
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   650
                return c.getSpaceBefore()
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   651
        return 0
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   652
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   653
    def getSpaceAfter(self,content=None):
2542
19f89b15936e removed a 2.4-ism
andy
parents: 2535
diff changeset
   654
        #this needs 2.4
19f89b15936e removed a 2.4-ism
andy
parents: 2535
diff changeset
   655
        #for c in reversed(self._content):
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   656
        reverseContent = (content or self._content)[:]
2542
19f89b15936e removed a 2.4-ism
andy
parents: 2535
diff changeset
   657
        reverseContent.reverse()
19f89b15936e removed a 2.4-ism
andy
parents: 2535
diff changeset
   658
        for c in reverseContent:
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   659
            if not hasattr(c,'frameAction'):
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   660
                return c.getSpaceAfter()
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   661
        return 0
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   662
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   663
    def drawOn(self, canv, x, y, _sW=0, scale=1.0, content=None, aW=None):
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   664
        '''we simulate being added to a frame'''
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   665
        pS = 0
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   666
        if aW is None: aW = self.width
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   667
        aW = scale*(aW+_sW)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   668
        if content is None:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   669
            content = self._content
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   670
        y += self.height*scale
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   671
        for c in content:
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   672
            w, h = c.wrapOn(canv,aW,0xfffffff)
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   673
            if w<_FUZZ or h<_FUZZ: continue
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   674
            if c is not content[0]: h += max(c.getSpaceBefore()-pS,0)
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   675
            y -= h
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   676
            c.drawOn(canv,x,y,_sW=aW-w)
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   677
            if c is not content[-1]:
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   678
                pS = c.getSpaceAfter()
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   679
                y -= pS
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   680
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   681
class PTOContainer(_Container,Flowable):
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   682
    '''PTOContainer(contentList,trailerList,headerList)
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   683
    
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   684
    A container for flowables decorated with trailer & header lists.
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   685
    If the split operation would be called then the trailer and header
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   686
    lists are injected before and after the split. This allows specialist
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   687
    "please turn over" and "continued from previous" like behaviours.''' 
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   688
    def __init__(self,content,trailer=None,header=None):
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   689
        I = _PTOInfo(trailer,header)
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   690
        self._content = C = []
2449
47b15f941325 platypus: attempt to make KeepTogether/keepWithNext more robust
rgbecker
parents: 2408
diff changeset
   691
        for _ in _flowableSublist(content):
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   692
            if isinstance(_,PTOContainer):
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   693
                C.extend(_._content)
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   694
            else:
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   695
                C.append(_)
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   696
                if not hasattr(_,'_ptoinfo'): _._ptoinfo = I
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   697
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   698
    def wrap(self,availWidth,availHeight):
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   699
        self.width, self.height = _listWrapOn(self._content,availWidth,self.canv)
2384
6d44252e1042 platypus: added ptocontainer, moved tables test
rgbecker
parents: 2376
diff changeset
   700
        return self.width,self.height
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   701
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   702
    def split(self, availWidth, availHeight):
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   703
        if availHeight<0: return []
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   704
        canv = self.canv
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   705
        C = self._content
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   706
        x = i = H = pS = hx = 0
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   707
        n = len(C)
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   708
        I2W = {}
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   709
        for x in xrange(n):
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   710
            c = C[x]
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   711
            I = c._ptoinfo
2388
5fa400f5d46b flowables.py: remove 2.1 incompatibility
rgbecker
parents: 2387
diff changeset
   712
            if I not in I2W.keys():
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   713
                T = I.trailer
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   714
                Hdr = I.header
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   715
                tW, tH = _listWrapOn(T, availWidth, self.canv)
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   716
                tSB = T[0].getSpaceBefore()
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   717
                I2W[I] = T,tW,tH,tSB
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   718
            else:
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   719
                T,tW,tH,tSB = I2W[I]
2384
6d44252e1042 platypus: added ptocontainer, moved tables test
rgbecker
parents: 2376
diff changeset
   720
            _, h = c.wrapOn(canv,availWidth,0xfffffff)
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   721
            if x:
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   722
                hx = max(c.getSpaceBefore()-pS,0)
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   723
                h += hx
2384
6d44252e1042 platypus: added ptocontainer, moved tables test
rgbecker
parents: 2376
diff changeset
   724
            pS = c.getSpaceAfter()
6d44252e1042 platypus: added ptocontainer, moved tables test
rgbecker
parents: 2376
diff changeset
   725
            H += h+pS
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   726
            tHS = tH+max(tSB,pS)
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   727
            if H+tHS>=availHeight-_FUZZ: break
2384
6d44252e1042 platypus: added ptocontainer, moved tables test
rgbecker
parents: 2376
diff changeset
   728
            i += 1
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   729
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   730
        #first retract last thing we tried
2384
6d44252e1042 platypus: added ptocontainer, moved tables test
rgbecker
parents: 2376
diff changeset
   731
        H -= (h+pS)
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   732
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   733
        #attempt a sub split on the last one we have
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   734
        aH = (availHeight-H-tHS-hx)*0.99999
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   735
        if aH>=0.05*availHeight:
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   736
            SS = c.splitOn(canv,availWidth,aH)
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   737
        else:
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   738
            SS = []
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   739
        F = [UseUpSpace()]
2376
7e70411a7236 flowables.py: minor change to PTOContainer
rgbecker
parents: 2375
diff changeset
   740
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   741
        if len(SS)>1:
2387
75caa41a818f platypus/test: working pto (& inner pto)
rgbecker
parents: 2384
diff changeset
   742
            R1 = C[:i] + SS[:1] + T + F
2376
7e70411a7236 flowables.py: minor change to PTOContainer
rgbecker
parents: 2375
diff changeset
   743
            R2 = Hdr + SS[1:]+C[i+1:]
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   744
        elif not i:
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   745
            return []
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   746
        else:
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   747
            R1 = C[:i]+T+F
2376
7e70411a7236 flowables.py: minor change to PTOContainer
rgbecker
parents: 2375
diff changeset
   748
            R2 = Hdr + C[i:]
2535
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   749
        T =  R1 + [PTOContainer(R2,deepcopy(I.trailer),deepcopy(I.header))]
714a951e4f64 flowables.py: fixes to PTOContainer
rgbecker
parents: 2534
diff changeset
   750
        return T
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   751
2528
39a609be559a renamed FrameFlowable to KeepInFrame
andy
parents: 2527
diff changeset
   752
#utility functions used by KeepInFrame
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   753
def _hmodel(s0,s1,h0,h1):
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   754
    # calculate the parameters in the model
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   755
    # h = a/s**2 + b/s
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   756
    a11 = 1./s0**2
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   757
    a12 = 1./s0
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   758
    a21 = 1./s1**2
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   759
    a22 = 1./s1
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   760
    det = a11*a22-a12*a21
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   761
    b11 = a22/det
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   762
    b12 = -a12/det
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   763
    b21 = -a21/det
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   764
    b22 = a11/det
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   765
    a = b11*h0+b12*h1
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   766
    b = b21*h0+b22*h1
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   767
    return a,b
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   768
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   769
def _qsolve(h,(a,b)):
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   770
    '''solve the model v = a/s**2 + b/s for an s which gives us v==h'''
2569
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   771
    if abs(a)<=_FUZZ:
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   772
        return b/h
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   773
    t = 0.5*b/a
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   774
    from math import sqrt
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   775
    f = -h/a
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   776
    r = t*t-f
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   777
    if r<0: return None
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   778
    r = sqrt(r)
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   779
    if t>=0:
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   780
        s1 = -t - r 
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   781
    else:
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   782
        s1 = -t + r
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   783
    s2 = f/s1
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   784
    return max(1./s1, 1./s2)
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   785
2528
39a609be559a renamed FrameFlowable to KeepInFrame
andy
parents: 2527
diff changeset
   786
class KeepInFrame(_Container,Flowable):
2531
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   787
    def __init__(self, maxWidth, maxHeight, content=[], mergeSpace=1, mode='shrink', name=''):
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   788
        '''mode describes the action to take when overflowing
2529
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   789
            error       raise an error in the normal way
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   790
            continue    ignore ie just draw it and report maxWidth, maxHeight
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   791
            shrink      shrinkToFit
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   792
            truncate    fit as much as possible
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   793
        '''
2531
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   794
        self.name = name
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   795
        self.maxWidth = maxWidth
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   796
        self.maxHeight = maxHeight
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   797
        self.mode = mode
2529
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   798
        assert mode in ('error','overflow','shrink','truncate'), '%s invalid mode value %s' % (self.identity(),mode)
2528
39a609be559a renamed FrameFlowable to KeepInFrame
andy
parents: 2527
diff changeset
   799
        assert maxHeight>=0,  '%s invalid maxHeight value %s' % (self.identity(),maxHeight)
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   800
        if mergeSpace is None: mergeSpace = overlapAttachedSpace
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   801
        self.mergespace = mergeSpace
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   802
        self._content = content
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   803
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   804
    def _getAvailableWidth(self):
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   805
        return self.maxWidth - self._leftExtraIndent - self._rightExtraIndent
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   806
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   807
    def identity(self, maxLen=None):
2531
40b6f4b41f7c platypus: changes to make identity more useful
rgbecker
parents: 2529
diff changeset
   808
        return "<%s at %s%s%s> size=%sx%s" % (self.__class__.__name__, hex(id(self)), self._frameName(), self.name and ' name="%s"'%self.name or '', fp_str(self.maxWidth),fp_str(self.maxHeight))
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   809
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   810
    def wrap(self,availWidth,availHeight):
2534
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   811
        from doctemplate import LayoutError
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   812
        mode = self.mode
2526
eaaa012dffd9 flowables.py: minor fixes revealed by rml2pdf use
rgbecker
parents: 2525
diff changeset
   813
        maxWidth = float(self.maxWidth or availWidth)
2528
39a609be559a renamed FrameFlowable to KeepInFrame
andy
parents: 2527
diff changeset
   814
        maxHeight = float(self.maxHeight or availHeight)
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   815
        W, H = _listWrapOn(self._content,availWidth,self.canv)
2534
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   816
        if (mode=='error' and (W>availWidth+_FUZZ or H>availHeight+_FUZZ)):
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   817
            ident = 'content %sx%s too large for %s' % (W,H,self.identity(30))
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   818
            #leave to keep apart from the raise
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   819
            raise LayoutError(ident)
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   820
        elif W<=availWidth+_FUZZ and H<=availHeight+_FUZZ:
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   821
            self.width = W-_FUZZ      #we take what we get
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   822
            self.height = H-_FUZZ
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   823
        elif (maxWidth>=availWidth+_FUZZ or maxHeight>=availHeight+_FUZZ):
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   824
            ident = 'Specified size too large for available space %sx%s in %s' % (availWidth,availHeight,self.identity(30))
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   825
            #leave to keep apart from the raise
809c000dbbb3 platypus: fixup KeepInFrame error handling
rgbecker
parents: 2533
diff changeset
   826
            raise LayoutError(ident)
2529
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   827
        elif mode in ('overflow','truncate'):   #we lie
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   828
            self.width = min(maxWidth,W)-_FUZZ
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   829
            self.height = min(maxHeight,H)-_FUZZ
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   830
        else:
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   831
            def func(x):
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   832
                W, H = _listWrapOn(self._content,x*availWidth,self.canv)
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   833
                W /= x
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   834
                H /= x
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   835
                return W, H
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   836
            W0 = W
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   837
            H0 = H
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   838
            s0 = 1
2527
edff938c5e89 flowablse.py: minor fix and hack to FrameFlowable
rgbecker
parents: 2526
diff changeset
   839
            if W>maxWidth+_FUZZ:
2569
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   840
                #squeeze out the excess width and or Height
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   841
                s1 = W/maxWidth
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   842
                W, H = func(s1)
2569
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   843
                if H<=maxHeight+_FUZZ:
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   844
                    self.width = W-_FUZZ
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   845
                    self.height = H-_FUZZ
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   846
                    self._scale = s1
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   847
                    return W,H
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   848
                s0 = s1
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   849
                H0 = H
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   850
                W0 = W
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   851
            s1 = H/maxHeight
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   852
            W, H = func(s1)
2569
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   853
            self.width = W-_FUZZ
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   854
            self.height = H-_FUZZ
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   855
            self._scale = s1
2569
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   856
            if H<min(0.95*maxHeight,maxHeight-10) or H>=maxHeight+_FUZZ:
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   857
                #the standard case W should be OK, H is short we want
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   858
                #to find the smallest s with H<=maxHeight
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   859
                H1 = H
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   860
                for f in 0, 0.01, 0.05, 0.10, 0.15:
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   861
                    #apply the quadratic model
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   862
                    s = _qsolve(maxHeight*(1-f),_hmodel(s0,s1,H0,H1))
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   863
                    W, H = func(s)
2569
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   864
                    if H<=maxHeight+_FUZZ and W<=maxWidth+_FUZZ:
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   865
                        self.width = W-_FUZZ
f7ac857ad20d flowables.py: attempt to fix up keepInFrame for one more case
rgbecker
parents: 2562
diff changeset
   866
                        self.height = H-_FUZZ
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   867
                        self._scale = s
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   868
                        break
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   869
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   870
        return self.width, self.height
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   871
2375
1e175a4474d0 platypus: almost finished PTOContainer
rgbecker
parents: 2341
diff changeset
   872
    def drawOn(self, canv, x, y, _sW=0):
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   873
        scale = getattr(self,'_scale',1.0)
2529
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   874
        truncate = self.mode=='truncate'
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   875
        ss = scale!=1.0 or truncate
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   876
        if ss:
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   877
            canv.saveState()
2529
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   878
            if truncate:
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   879
                p = canv.beginPath()
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   880
                p.rect(x, y, self.width,self.height)
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   881
                canv.clipPath(p,stroke=0)
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   882
            else:
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   883
                canv.translate(x,y)
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   884
                x=y=0
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   885
                canv.scale(1.0/scale, 1.0/scale)
2525
634ec1f48514 platypus: initial FrameFlowable implementation
rgbecker
parents: 2523
diff changeset
   886
        _Container.drawOn(self, canv, x, y, _sW=_sW, scale=scale)
2529
dced304f8584 flowables.py: keepInFrame now truncates etc properly, doctemplate.py: fix handle_frameEnd
rgbecker
parents: 2528
diff changeset
   887
        if ss: canv.restoreState()
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   888
2562
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   889
class ImageAndFlowables(_Container,Flowable):
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   890
    '''combine a list of flowables and an Image'''
2562
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   891
    def __init__(self,I,F,imageLeftPadding=0,imageRightPadding=3,imageTopPadding=0,imageBottomPadding=3,
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   892
                    imageSide='right'):
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   893
        self._content = _flowableSublist(F)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   894
        self._I = I
2562
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   895
        self._irpad = imageRightPadding
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   896
        self._ilpad = imageLeftPadding
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   897
        self._ibpad = imageBottomPadding
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   898
        self._itpad = imageTopPadding
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   899
        self._side = imageSide
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   900
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   901
    def getSpaceAfter(self):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   902
        if hasattr(self,'_C1'):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   903
            C = self._C1
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   904
        elif hasattr(self,'_C0'):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   905
            C = self._C0
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   906
        else:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   907
            C = self._content
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   908
        return _Container.getSpaceAfter(self,C)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   909
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   910
    def getSpaceBefore(self):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   911
        return max(self._I.getSpaceBefore(),_Container.getSpaceBefore(self))
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   912
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   913
    def _reset(self):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   914
        for a in ('_wrapArgs','_C0','_C1'):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   915
            try:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   916
                delattr(self,a)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   917
            except:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   918
                pass
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   919
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   920
    def wrap(self,availWidth,availHeight):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   921
        canv = self.canv
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   922
        if hasattr(self,'_wrapArgs'):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   923
            if self._wrapArgs==(availWidth,availHeight):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   924
                return self.width,self.height
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   925
            self._reset()
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   926
        self._wrapArgs = availWidth, availHeight
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   927
        wI, hI = self._I.wrap(availWidth,availHeight)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   928
        self._wI = wI
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   929
        self._hI = hI
2562
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   930
        ilpad = self._ilpad
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   931
        irpad = self._irpad
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   932
        ibpad = self._ibpad
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   933
        itpad = self._itpad
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   934
        self._iW = availWidth - irpad - wI - ilpad
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   935
        aH = itpad + hI + ibpad
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   936
        W,H0,self._C0,self._C1 = self._findSplit(canv,self._iW,aH)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   937
        self.width = availWidth
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   938
        aH = self._aH = max(aH,H0)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   939
        if not self._C1:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   940
            self.height = aH
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   941
        else:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   942
            W1,H1 = _listWrapOn(self._C1,availWidth,canv)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   943
            self.height = aH+H1
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   944
        return self.width, self.height
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   945
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   946
    def split(self,availWidth, availHeight):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   947
        if hasattr(self,'_wrapArgs'):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   948
            if self._wrapArgs!=(availWidth,availHeight):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   949
                self._reset()
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   950
        W,H=self.wrap(availWidth,availHeight)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   951
        if self._aH>availHeight: return []
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   952
        C1 = self._C1
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   953
        if C1:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   954
            c0 = C1[0]
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   955
            S = c0.split(availWidth,availHeight-self._aH)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   956
            if not S:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   957
                self._C1 = []
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   958
                self.height = self._aH
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   959
            else:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   960
                self._C1 = [S[0]]
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   961
                self.height = self._aH + S[0].height
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   962
                C1 = S[1:]+C1[1:]
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   963
        else:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   964
            self._C1 = []
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   965
            self.height = self._aH
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   966
        return [self]+C1
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   967
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   968
    def drawOn(self, canv, x, y, _sW=0):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   969
        if self._side=='left':
2562
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   970
            Ix = x + self._ilpad
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   971
            Fx = Ix+ self._irpad + self._wI
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   972
        else:
2562
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   973
            Ix = x + self.width-self._wI-self._irpad - self._ilpad
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   974
            Fx = x
2562
3c77a70414d9 platypus: ImagesAndFlowables in final form
rgbecker
parents: 2561
diff changeset
   975
        self._I.drawOn(canv,Ix,y+self.height-self._itpad-self._hI)
2561
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   976
        _Container.drawOn(self, canv, Fx, y, content=self._C0, aW=self._iW)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   977
        if self._C1:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   978
            _Container.drawOn(self, canv, x, y-self._aH,content=self._C1)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   979
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   980
    def _findSplit(self,canv,availWidth,availHeight,mergeSpace=1,obj=None):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   981
        '''return max width, required height for a list of flowables F'''
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   982
        W = 0
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   983
        H = 0
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   984
        pS = sB = 0
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   985
        atTop = 1
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   986
        F = self._content
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   987
        for i,f in enumerate(F):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   988
            w,h = f.wrapOn(canv,availWidth,0xfffffff)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   989
            if w<=_FUZZ or h<=_FUZZ: continue
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   990
            W = max(W,w)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   991
            if not atTop:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   992
                s = f.getSpaceBefore()
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   993
                if mergeSpace: s = max(s-pS,0)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   994
                H += s
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   995
            else:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   996
                if obj is not None: obj._spaceBefore = f.getSpaceBefore()
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   997
                atTop = 0
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   998
            if H>=availHeight:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
   999
                return W, availHeight, F[:i],F[i:]
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1000
            H += h
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1001
            if H>availHeight:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1002
                from paragraph import Paragraph
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1003
                aH = availHeight-(H-h)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1004
                if isinstance(f,(Paragraph,Preformatted)):
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1005
                    leading = f.style.leading
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1006
                    nH = leading*int(aH/float(leading))+_FUZZ
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1007
                    if nH<aH: nH += leading
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1008
                    availHeight += nH-aH
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1009
                    aH = nH
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1010
                S = deepcopy(f).split(availWidth,aH)
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1011
                if not S:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1012
                    return W, availHeight, F[:i],F[i:]
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1013
                else:
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1014
                    return W,availHeight,F[:i]+S[:1],S[1:]+F[i+1:]
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1015
            pS = f.getSpaceAfter()
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1016
            H += pS
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1017
        if obj is not None: obj._spaceAfter = pS
a2409b6627e6 reportlab: added FlowablesAndImage
rgbecker
parents: 2557
diff changeset
  1018
        return W, H-pS, F, []