reportlab/platypus/flowables.py
author rgbecker
Thu, 01 Jun 2000 15:23:06 +0000
changeset 253 cfcf8d555a2c
child 255 ee9e321e747d
permissions -rw-r--r--
Platypus re-organisation
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     1
###############################################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     2
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     3
#	ReportLab Public License Version 1.0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     4
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     5
#	Except for the change of names the spirit and intention of this
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     6
#	license is the same as that of Python
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     7
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     8
#	(C) Copyright ReportLab Inc. 1998-2000.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     9
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    10
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    11
# All Rights Reserved
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    12
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    13
# Permission to use, copy, modify, and distribute this software and its
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    14
# documentation for any purpose and without fee is hereby granted, provided
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    15
# that the above copyright notice appear in all copies and that both that
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    16
# copyright notice and this permission notice appear in supporting
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    17
# documentation, and that the name of ReportLab not be used
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    18
# in advertising or publicity pertaining to distribution of the software
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    19
# without specific, written prior permission.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    20
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    21
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    22
# Disclaimer
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    23
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    24
# ReportLab Inc. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    25
# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    26
# IN NO EVENT SHALL ReportLab BE LIABLE FOR ANY SPECIAL, INDIRECT
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    27
# OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    28
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    29
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    30
# PERFORMANCE OF THIS SOFTWARE.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    31
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    32
###############################################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    33
#	$Log: flowables.py,v $
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    34
#	Revision 1.1  2000/06/01 15:23:06  rgbecker
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    35
#	Platypus re-organisation
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    36
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    37
#	
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    38
__version__=''' $Id: flowables.py,v 1.1 2000/06/01 15:23:06 rgbecker Exp $ '''
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    39
__doc__="""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    40
"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    41
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    42
# 200-10-13 gmcm
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    43
#	packagizing
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    44
#	rewrote grid stuff - now in tables.py
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    45
import os
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    46
import string
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    47
from copy import deepcopy
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    48
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    49
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    50
from reportlab.pdfgen import canvas
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    51
from reportlab.lib.units import inch
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    52
from reportlab.lib.colors import red
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    53
from reportlab.pdfbase import pdfutils
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    54
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    55
from reportlab.lib.pagesizes import DEFAULT_PAGE_SIZE
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    56
PAGE_HEIGHT = DEFAULT_PAGE_SIZE[1]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    57
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    58
#############################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    59
#	Flowable Objects - a base class and a few examples.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    60
#	One is just a box to get some metrics.	We also have
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    61
#	a paragraph, an image and a special 'page break'
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    62
#	object which fills the space.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    63
#############################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    64
class Flowable:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    65
	"""Abstract base class for things to be drawn.	Key concepts:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    66
	1. It knows its size
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    67
	2. It draws in its own coordinate system (this requires the
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    68
		base API to provide a translate() function.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    69
	"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    70
	def __init__(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    71
		self.width = 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    72
		self.height = 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    73
		self.wrapped = 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    74
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    75
	def drawOn(self, canvas, x, y):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    76
		"Tell it to draw itself on the canvas.	Do not override"
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    77
		self.canv = canvas
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    78
		self.canv.saveState()
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    79
		self.canv.translate(x, y)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    80
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    81
		self.draw()   #this is the bit you overload
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    82
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    83
		self.canv.restoreState()
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    84
		del self.canv
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    85
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    86
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    87
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    88
		"""This will be called by the enclosing frame before objects
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    89
		are asked their size, drawn or whatever.  It returns the
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    90
		size actually used."""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    91
		return (self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    92
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    93
	def split(self, availWidth, availheight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    94
		"""This will be called by more sophisticated frames when
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    95
		wrap fails. Stupid flowables should return []. Clever flowables
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    96
		should split themselves and return a list of flowables"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    97
		return []
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    98
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    99
	def getSpaceAfter(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   100
		if hasattr(self,'spaceAfter'): return self.spaceAfter
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   101
		elif hasattr(self,'style') and hasattr(self.style,'spaceAfter'): return self.style.spaceAfter
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   102
		else: return 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   103
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   104
	def getSpaceBefore(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   105
		if hasattr(self,'spaceBefore'): return self.spaceBefore
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   106
		elif hasattr(self,'style') and hasattr(self.style,'spaceBefore'): return self.style.spaceBefore
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   107
		else: return 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   108
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   109
class XBox(Flowable):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   110
	"""Example flowable - a box with an x through it and a caption.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   111
	This has a known size, so does not need to respond to wrap()."""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   112
	def __init__(self, width, height, text = 'A Box'):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   113
		Flowable.__init__(self)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   114
		self.width = width
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   115
		self.height = height
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   116
		self.text = text
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   117
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   118
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   119
		self.canv.rect(0, 0, self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   120
		self.canv.line(0, 0, self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   121
		self.canv.line(0, self.height, self.width, 0)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   122
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   123
		#centre the text
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   124
		self.canv.setFont('Times-Roman',12)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   125
		self.canv.drawCentredString(0.5*self.width, 0.5*self.height, self.text)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   126
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   127
class Preformatted(Flowable):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   128
	"""This is like the HTML <PRE> tag.  The line breaks are exactly where you put
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   129
	them, and it will not be wrapped.  So it is much simpler to implement!"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   130
	def __init__(self, text, style, bulletText = None, dedent=0):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   131
		self.style = style
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   132
		self.bulletText = bulletText
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   133
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   134
		#tidy up text - carefully, it is probably code.  If people want to
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   135
		#indent code within a source script, you can supply an arg to dedent
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   136
		#and it will chop off that many character, otherwise it leaves
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   137
		#left edge intact.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   138
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   139
		templines = string.split(text, '\n')
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   140
		self.lines = []
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   141
		for line in templines:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   142
			line = string.rstrip(line[dedent:])
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   143
			self.lines.append(line)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   144
		#don't want the first or last to be empty
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   145
		while string.strip(self.lines[0]) == '':
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   146
			self.lines = self.lines[1:]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   147
		while string.strip(self.lines[-1]) == '':
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   148
			self.lines = self.lines[:-1]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   149
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   150
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   151
		self.width = availWidth
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   152
		self.height = self.style.leading*len(self.lines)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   153
		return (self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   154
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   155
	def split(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   156
		#returns two Preformatted objects
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   157
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   158
		#not sure why they can be called with a negative height		
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   159
		if availHeight < self.style.leading:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   160
			return []
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   161
		
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   162
		linesThatFit = int(availHeight * 1.0 / self.style.leading)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   163
		
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   164
		text1 = string.join(self.lines[0:linesThatFit], '\n')
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   165
		text2 = string.join(self.lines[linesThatFit:], '\n')
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   166
		style = self.style
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   167
		if style.firstLineIndent != 0:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   168
			style = deepcopy(style)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   169
			style.firstLineIndent = 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   170
		return [Preformatted(text1, self.style), Preformatted(text2, style)]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   171
		
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   172
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   173
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   174
		#call another method for historical reasons.  Besides, I
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   175
		#suspect I will be playing with alternate drawing routines
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   176
		#so not doing it here makes it easier to switch.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   177
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   178
		cur_x = self.style.leftIndent
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   179
		cur_y = self.height - self.style.fontSize
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   180
		self.canv.addLiteral('%PreformattedPara')
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   181
		if self.style.textColor:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   182
			self.canv.setFillColor(self.style.textColor)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   183
		tx = self.canv.beginText(cur_x, cur_y)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   184
		#set up the font etc.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   185
		tx.setFont(self.style.fontName,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   186
				   self.style.fontSize,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   187
				   self.style.leading)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   188
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   189
		for text in self.lines:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   190
			tx.textLine(text)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   191
		self.canv.drawText(tx)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   192
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   193
class Image(Flowable):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   194
	def __init__(self, filename, width=None, height=None):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   195
		"""If size to draw at not specified, get it from the image."""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   196
		import Image  #this will raise an error if they do not have PIL.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   197
		self.filename = filename
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   198
		# if it is a JPEG, will be inlined within the file -
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   199
		# but we still need to know its size now
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   200
		if os.path.splitext(filename)[1] in ['.jpg', '.JPG', '.jpeg', '.JPEG']:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   201
			info = pdfutils.readJPEGInfo(open(filename, 'rb'))
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   202
			self.imageWidth = info[0]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   203
			self.imageHeight = info[1]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   204
		else:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   205
			img = Image.open(filename)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   206
			(self.imageWidth, self.imageHeight) = img.size
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   207
		if width:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   208
			self.drawWidth = width
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   209
		else:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   210
			self.drawWidth = self.imageWidth
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   211
		if height:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   212
			self.drawHeight = height
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   213
		else:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   214
			self.drawHeight = self.imageHeight
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   215
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   216
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   217
		#the caller may decide it does not fit.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   218
		self.availWidth = availWidth
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   219
		return (self.drawWidth, self.drawHeight)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   220
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   221
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   222
		#center it
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   223
		startx = 0.5 * (self.availWidth - self.drawWidth)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   224
		self.canv.drawInlineImage(self.filename,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   225
								  startx,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   226
								  0,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   227
								  self.drawWidth,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   228
								  self.drawHeight
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   229
								  )
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   230
class Spacer(Flowable):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   231
	"""A spacer just takes up space and doesn't draw anything - it can
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   232
	ensure a gap between objects."""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   233
	def __init__(self, width, height):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   234
		self.width = width
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   235
		self.height = height
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   236
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   237
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   238
		return (self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   239
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   240
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   241
		pass
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   242
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   243
class PageBreak(Flowable):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   244
	"""This works by consuming all remaining space in the frame!"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   245
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   246
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   247
		self.width = availWidth
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   248
		self.height = availHeight
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   249
		return (availWidth,availHeight)  #step back a point
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   250
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   251
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   252
		pass
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   254
class Macro(Flowable):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   255
	"""This is not actually drawn (i.e. it has zero height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   256
	but is executed when it would fit in the frame.  Allows direct
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   257
	access to the canvas through the object 'canvas'"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   258
	def __init__(self, command):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   259
		self.command = command
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   260
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   261
		return (0,0)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   262
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   263
		exec self.command in globals(), {'canvas':self.canv}
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   264
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   265
from paragraph import Paragraph