author | robin |
Thu, 24 Oct 2019 16:07:15 +0100 | |
changeset 4551 | d357e2acc856 |
parent 4528 | e09377955af8 |
child 4635 | b60508f2fd12 |
permissions | -rw-r--r-- |
4330 | 1 |
#Copyright ReportLab Europe Ltd. 2000-2017 |
817 | 2 |
#see license.txt for license details |
4528 | 3 |
#history https://hg.reportlab.com/hg-public/reportlab/log/tip/src/reportlab/graphics/renderPDF.py |
568 | 4 |
# renderPDF - draws Drawings onto a canvas |
3032 | 5 |
|
4252 | 6 |
__version__='3.3.0' |
3032 | 7 |
__doc__="""Render Drawing objects within others PDFs or standalone |
8 |
||
9 |
Usage:: |
|
10 |
||
11 |
import renderpdf |
|
12 |
renderpdf.draw(drawing, canvas, x, y) |
|
13 |
||
568 | 14 |
Execute the script to see some test drawings. |
15 |
changed |
|
16 |
""" |
|
17 |
||
18 |
from reportlab.graphics.shapes import * |
|
19 |
from reportlab.pdfgen.canvas import Canvas |
|
20 |
from reportlab.pdfbase.pdfmetrics import stringWidth |
|
3723
99aa837b6703
second stage of port to Python 3.3; working hello world
rptlab
parents:
3721
diff
changeset
|
21 |
from reportlab.lib.utils import getBytesIO |
4367
9960d82643bf
remove ascii, cmp & xrange builtins abuse; version-->3.4.15
robin <robin@reportlab.com>
parents:
4345
diff
changeset
|
22 |
from reportlab import ascii, rl_config |
4274
ec03159b74bb
changes to Render class; allow drawings to specify initialFontName/Size version-->3.3.9
robin
parents:
4252
diff
changeset
|
23 |
from reportlab.graphics.renderbase import Renderer, StateTracker, getStateDelta, renderScaledDrawing, STATE_DEFAULTS |
568 | 24 |
|
25 |
# the main entry point for users... |
|
2360
0fbaee224de1
rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents:
2341
diff
changeset
|
26 |
def draw(drawing, canvas, x, y, showBoundary=rl_config._unset_): |
568 | 27 |
"""As it says""" |
28 |
R = _PDFRenderer() |
|
2553
a880f43d10bd
reprotlab/graphics: fix so renderScale is used properly
rgbecker
parents:
2544
diff
changeset
|
29 |
R.draw(renderScaledDrawing(drawing), canvas, x, y, showBoundary=showBoundary) |
568 | 30 |
|
31 |
class _PDFRenderer(Renderer): |
|
32 |
"""This draws onto a PDF document. It needs to be a class |
|
33 |
rather than a function, as some PDF-specific state tracking is |
|
34 |
needed outside of the state info in the SVG model.""" |
|
35 |
||
36 |
def __init__(self): |
|
37 |
self._stroke = 0 |
|
38 |
self._fill = 0 |
|
39 |
||
40 |
def drawNode(self, node): |
|
41 |
"""This is the recursive method called for each node |
|
42 |
in the tree""" |
|
43 |
#print "pdf:drawNode", self |
|
44 |
#if node.__class__ is Wedge: stop |
|
1230 | 45 |
if not (isinstance(node, Path) and node.isClipPath): |
46 |
self._canvas.saveState() |
|
568 | 47 |
|
48 |
#apply state changes |
|
49 |
deltas = getStateDelta(node) |
|
50 |
self._tracker.push(deltas) |
|
51 |
self.applyStateChanges(deltas, {}) |
|
52 |
||
53 |
#draw the object, or recurse |
|
54 |
self.drawNodeDispatcher(node) |
|
55 |
||
56 |
self._tracker.pop() |
|
1230 | 57 |
if not (isinstance(node, Path) and node.isClipPath): |
58 |
self._canvas.restoreState() |
|
568 | 59 |
|
60 |
def drawRect(self, rect): |
|
61 |
if rect.rx == rect.ry == 0: |
|
62 |
#plain old rectangle |
|
63 |
self._canvas.rect( |
|
64 |
rect.x, rect.y, |
|
65 |
rect.width, rect.height, |
|
66 |
stroke=self._stroke, |
|
67 |
fill=self._fill |
|
68 |
) |
|
69 |
else: |
|
70 |
#cheat and assume ry = rx; better to generalize |
|
71 |
#pdfgen roundRect function. TODO |
|
72 |
self._canvas.roundRect( |
|
73 |
rect.x, rect.y, |
|
74 |
rect.width, rect.height, rect.rx, |
|
75 |
fill=self._fill, |
|
76 |
stroke=self._stroke |
|
77 |
) |
|
78 |
||
1609
34ab63314b38
Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents:
1587
diff
changeset
|
79 |
def drawImage(self, image): |
3562
ad5ccec5b07f
allow PIL Image in image.path for renderPDF & renderPM
rgbecker
parents:
3495
diff
changeset
|
80 |
path = image.path |
1609
34ab63314b38
Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents:
1587
diff
changeset
|
81 |
# currently not implemented in other renderers |
3562
ad5ccec5b07f
allow PIL Image in image.path for renderPDF & renderPM
rgbecker
parents:
3495
diff
changeset
|
82 |
if path and (hasattr(path,'mode') or os.path.exists(image.path)): |
1609
34ab63314b38
Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents:
1587
diff
changeset
|
83 |
self._canvas.drawInlineImage( |
3562
ad5ccec5b07f
allow PIL Image in image.path for renderPDF & renderPM
rgbecker
parents:
3495
diff
changeset
|
84 |
path, |
1609
34ab63314b38
Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents:
1587
diff
changeset
|
85 |
image.x, image.y, |
34ab63314b38
Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents:
1587
diff
changeset
|
86 |
image.width, image.height |
34ab63314b38
Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents:
1587
diff
changeset
|
87 |
) |
34ab63314b38
Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents:
1587
diff
changeset
|
88 |
|
568 | 89 |
def drawLine(self, line): |
90 |
if self._stroke: |
|
91 |
self._canvas.line(line.x1, line.y1, line.x2, line.y2) |
|
92 |
||
93 |
def drawCircle(self, circle): |
|
94 |
self._canvas.circle( |
|
95 |
circle.cx, circle.cy, circle.r, |
|
96 |
fill=self._fill, |
|
4325
fc03e6396da5
add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents:
4306
diff
changeset
|
97 |
stroke=self._stroke, |
568 | 98 |
) |
99 |
||
100 |
def drawPolyLine(self, polyline): |
|
101 |
if self._stroke: |
|
102 |
assert len(polyline.points) >= 2, 'Polyline must have 2 or more points' |
|
103 |
head, tail = polyline.points[0:2], polyline.points[2:], |
|
104 |
path = self._canvas.beginPath() |
|
105 |
path.moveTo(head[0], head[1]) |
|
106 |
for i in range(0, len(tail), 2): |
|
107 |
path.lineTo(tail[i], tail[i+1]) |
|
108 |
self._canvas.drawPath(path) |
|
109 |
||
110 |
def drawWedge(self, wedge): |
|
4132
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
111 |
if wedge.annular: |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
112 |
self.drawPath(wedge.asPolygon()) |
1952 | 113 |
else: |
4132
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
114 |
centerx, centery, radius, startangledegrees, endangledegrees = \ |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
115 |
wedge.centerx, wedge.centery, wedge.radius, wedge.startangledegrees, wedge.endangledegrees |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
116 |
yradius, radius1, yradius1 = wedge._xtraRadii() |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
117 |
if yradius is None: yradius = radius |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
118 |
angle = endangledegrees-startangledegrees |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
119 |
path = self._canvas.beginPath() |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
120 |
if (radius1==0 or radius1 is None) and (yradius1==0 or yradius1 is None): |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
121 |
path.moveTo(centerx, centery) |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
122 |
path.arcTo(centerx-radius, centery-yradius, centerx+radius, centery+yradius, |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
123 |
startangledegrees, angle) |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
124 |
else: |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
125 |
path.arc(centerx-radius, centery-yradius, centerx+radius, centery+yradius, |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
126 |
startangledegrees, angle) |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
127 |
path.arcTo(centerx-radius1, centery-yradius1, centerx+radius1, centery+yradius1, |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
128 |
endangledegrees, -angle) |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
129 |
path.close() |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
130 |
self._canvas.drawPath(path, |
28379377462b
fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents:
3977
diff
changeset
|
131 |
fill=self._fill, |
4325
fc03e6396da5
add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents:
4306
diff
changeset
|
132 |
stroke=self._stroke, |
fc03e6396da5
add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents:
4306
diff
changeset
|
133 |
) |
568 | 134 |
|
135 |
def drawEllipse(self, ellipse): |
|
136 |
#need to convert to pdfgen's bounding box representation |
|
137 |
x1 = ellipse.cx - ellipse.rx |
|
138 |
x2 = ellipse.cx + ellipse.rx |
|
139 |
y1 = ellipse.cy - ellipse.ry |
|
140 |
y2 = ellipse.cy + ellipse.ry |
|
1587 | 141 |
self._canvas.ellipse(x1,y1,x2,y2,fill=self._fill,stroke=self._stroke) |
568 | 142 |
|
143 |
def drawPolygon(self, polygon): |
|
144 |
assert len(polygon.points) >= 2, 'Polyline must have 2 or more points' |
|
145 |
head, tail = polygon.points[0:2], polygon.points[2:], |
|
146 |
path = self._canvas.beginPath() |
|
147 |
path.moveTo(head[0], head[1]) |
|
148 |
for i in range(0, len(tail), 2): |
|
149 |
path.lineTo(tail[i], tail[i+1]) |
|
150 |
path.close() |
|
151 |
self._canvas.drawPath( |
|
152 |
path, |
|
153 |
stroke=self._stroke, |
|
4325
fc03e6396da5
add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents:
4306
diff
changeset
|
154 |
fill=self._fill, |
568 | 155 |
) |
156 |
||
157 |
def drawString(self, stringObj): |
|
158 |
if self._fill: |
|
159 |
S = self._tracker.getState() |
|
2575 | 160 |
text_anchor, x, y, text, enc = S['textAnchor'], stringObj.x,stringObj.y,stringObj.text, stringObj.encoding |
568 | 161 |
if not text_anchor in ['start','inherited']: |
1683 | 162 |
font, font_size = S['fontName'], S['fontSize'] |
2575 | 163 |
textLen = stringWidth(text, font, font_size, enc) |
568 | 164 |
if text_anchor=='end': |
3214
f7e2da62a5a0
pdfmetrics.py: use findInPaths to improve font file finding
rgbecker
parents:
3200
diff
changeset
|
165 |
x -= textLen |
568 | 166 |
elif text_anchor=='middle': |
3214
f7e2da62a5a0
pdfmetrics.py: use findInPaths to improve font file finding
rgbecker
parents:
3200
diff
changeset
|
167 |
x -= textLen*0.5 |
3219
b28d6eef8227
reportlab: add support for String anchor 'numeric'
rgbecker
parents:
3214
diff
changeset
|
168 |
elif text_anchor=='numeric': |
b28d6eef8227
reportlab: add support for String anchor 'numeric'
rgbecker
parents:
3214
diff
changeset
|
169 |
x -= numericXShift(text_anchor,text,textLen,font,font_size,enc) |
568 | 170 |
else: |
3721 | 171 |
raise ValueError('bad value for textAnchor '+str(text_anchor)) |
2142 | 172 |
t = self._canvas.beginText(x,y) |
173 |
t.textLine(text) |
|
174 |
self._canvas.drawText(t) |
|
568 | 175 |
|
1071 | 176 |
def drawPath(self, path): |
177 |
from reportlab.graphics.shapes import _renderPath |
|
178 |
pdfPath = self._canvas.beginPath() |
|
179 |
drawFuncs = (pdfPath.moveTo, pdfPath.lineTo, pdfPath.curveTo, pdfPath.close) |
|
4306
8ffb2ffc283b
support for Path autoclose & fillMode; version --> 3.3.29
robin
parents:
4305
diff
changeset
|
180 |
autoclose = getattr(path,'autoclose','') |
4305
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
181 |
fill = self._fill |
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
182 |
stroke = self._stroke |
4306
8ffb2ffc283b
support for Path autoclose & fillMode; version --> 3.3.29
robin
parents:
4305
diff
changeset
|
183 |
isClosed = _renderPath(path, drawFuncs, forceClose=fill and autoclose=='pdf') |
4305
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
184 |
dP = self._canvas.drawPath |
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
185 |
cP = self._canvas.clipPath if path.isClipPath else dP |
4306
8ffb2ffc283b
support for Path autoclose & fillMode; version --> 3.3.29
robin
parents:
4305
diff
changeset
|
186 |
fillMode = getattr(path,'fillMode',None) |
8ffb2ffc283b
support for Path autoclose & fillMode; version --> 3.3.29
robin
parents:
4305
diff
changeset
|
187 |
if autoclose=='svg': |
4305
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
188 |
if fill and stroke and not isClosed: |
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
189 |
cP(pdfPath, fill=fill, stroke=0) |
4306
8ffb2ffc283b
support for Path autoclose & fillMode; version --> 3.3.29
robin
parents:
4305
diff
changeset
|
190 |
dP(pdfPath, stroke=stroke, fill=0, fillMode=fillMode) |
4305
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
191 |
else: |
4306
8ffb2ffc283b
support for Path autoclose & fillMode; version --> 3.3.29
robin
parents:
4305
diff
changeset
|
192 |
cP(pdfPath, fill=fill, stroke=stroke, fillMode=fillMode) |
8ffb2ffc283b
support for Path autoclose & fillMode; version --> 3.3.29
robin
parents:
4305
diff
changeset
|
193 |
elif autoclose=='pdf': |
8ffb2ffc283b
support for Path autoclose & fillMode; version --> 3.3.29
robin
parents:
4305
diff
changeset
|
194 |
cP(pdfPath, fill=fill, stroke=stroke, fillMode=fillMode) |
1071 | 195 |
else: |
4305
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
196 |
#our old broken default |
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
197 |
if not isClosed: |
41faca6e9c0b
add support for different fill policies in renderXX drawPath; version-->3.3.28
robin
parents:
4274
diff
changeset
|
198 |
fill = 0 |
4306
8ffb2ffc283b
support for Path autoclose & fillMode; version --> 3.3.29
robin
parents:
4305
diff
changeset
|
199 |
cP(pdfPath, fill=fill, stroke=stroke, fillMode=fillMode) |
1071 | 200 |
|
3222
2dcbd41f9c82
renderPDF.py: add overridable setFillColor/setStrokeColor to _PDFRenderer
rgbecker
parents:
3219
diff
changeset
|
201 |
def setStrokeColor(self,c): |
2dcbd41f9c82
renderPDF.py: add overridable setFillColor/setStrokeColor to _PDFRenderer
rgbecker
parents:
3219
diff
changeset
|
202 |
self._canvas.setStrokeColor(c) |
2dcbd41f9c82
renderPDF.py: add overridable setFillColor/setStrokeColor to _PDFRenderer
rgbecker
parents:
3219
diff
changeset
|
203 |
|
2dcbd41f9c82
renderPDF.py: add overridable setFillColor/setStrokeColor to _PDFRenderer
rgbecker
parents:
3219
diff
changeset
|
204 |
def setFillColor(self,c): |
2dcbd41f9c82
renderPDF.py: add overridable setFillColor/setStrokeColor to _PDFRenderer
rgbecker
parents:
3219
diff
changeset
|
205 |
self._canvas.setFillColor(c) |
2dcbd41f9c82
renderPDF.py: add overridable setFillColor/setStrokeColor to _PDFRenderer
rgbecker
parents:
3219
diff
changeset
|
206 |
|
568 | 207 |
def applyStateChanges(self, delta, newState): |
208 |
"""This takes a set of states, and outputs the PDF operators |
|
209 |
needed to set those properties""" |
|
4345 | 210 |
for key, value in (sorted(delta.items()) if rl_config.invariant else delta.items()): |
568 | 211 |
if key == 'transform': |
212 |
self._canvas.transform(value[0], value[1], value[2], |
|
213 |
value[3], value[4], value[5]) |
|
214 |
elif key == 'strokeColor': |
|
215 |
#this has different semantics in PDF to SVG; |
|
216 |
#we always have a color, and either do or do |
|
217 |
#not apply it; in SVG one can have a 'None' color |
|
218 |
if value is None: |
|
219 |
self._stroke = 0 |
|
220 |
else: |
|
221 |
self._stroke = 1 |
|
3222
2dcbd41f9c82
renderPDF.py: add overridable setFillColor/setStrokeColor to _PDFRenderer
rgbecker
parents:
3219
diff
changeset
|
222 |
self.setStrokeColor(value) |
568 | 223 |
elif key == 'strokeWidth': |
224 |
self._canvas.setLineWidth(value) |
|
225 |
elif key == 'strokeLineCap': #0,1,2 |
|
226 |
self._canvas.setLineCap(value) |
|
227 |
elif key == 'strokeLineJoin': |
|
228 |
self._canvas.setLineJoin(value) |
|
229 |
# elif key == 'stroke_dasharray': |
|
230 |
# self._canvas.setDash(array=value) |
|
231 |
elif key == 'strokeDashArray': |
|
232 |
if value: |
|
3495
0b8d32884a1e
renderPM.py & renderPDF.py make dash phase more explicit
rgbecker
parents:
3417
diff
changeset
|
233 |
if isinstance(value,(list,tuple)) and len(value)==2 and isinstance(value[1],(tuple,list)): |
0b8d32884a1e
renderPM.py & renderPDF.py make dash phase more explicit
rgbecker
parents:
3417
diff
changeset
|
234 |
phase = value[0] |
0b8d32884a1e
renderPM.py & renderPDF.py make dash phase more explicit
rgbecker
parents:
3417
diff
changeset
|
235 |
value = value[1] |
0b8d32884a1e
renderPM.py & renderPDF.py make dash phase more explicit
rgbecker
parents:
3417
diff
changeset
|
236 |
else: |
0b8d32884a1e
renderPM.py & renderPDF.py make dash phase more explicit
rgbecker
parents:
3417
diff
changeset
|
237 |
phase = 0 |
0b8d32884a1e
renderPM.py & renderPDF.py make dash phase more explicit
rgbecker
parents:
3417
diff
changeset
|
238 |
self._canvas.setDash(value,phase) |
568 | 239 |
else: |
240 |
self._canvas.setDash() |
|
241 |
elif key == 'fillColor': |
|
242 |
#this has different semantics in PDF to SVG; |
|
243 |
#we always have a color, and either do or do |
|
244 |
#not apply it; in SVG one can have a 'None' color |
|
245 |
if value is None: |
|
246 |
self._fill = 0 |
|
247 |
else: |
|
248 |
self._fill = 1 |
|
3222
2dcbd41f9c82
renderPDF.py: add overridable setFillColor/setStrokeColor to _PDFRenderer
rgbecker
parents:
3219
diff
changeset
|
249 |
self.setFillColor(value) |
568 | 250 |
elif key in ['fontSize', 'fontName']: |
251 |
# both need setting together in PDF |
|
252 |
# one or both might be in the deltas, |
|
253 |
# so need to get whichever is missing |
|
578
f797bf806ee5
Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents:
574
diff
changeset
|
254 |
fontname = delta.get('fontName', self._canvas._fontname) |
f797bf806ee5
Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents:
574
diff
changeset
|
255 |
fontsize = delta.get('fontSize', self._canvas._fontsize) |
568 | 256 |
self._canvas.setFont(fontname, fontsize) |
3198
683ca9eb6b18
reportlab: added in support for Overprint/Opacity & Separated colours (Opacity inspired by Simon King)
rgbecker
parents:
3032
diff
changeset
|
257 |
elif key=='fillOpacity': |
3280
2ac121cd0ee5
shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents:
3230
diff
changeset
|
258 |
if value is not None: |
2ac121cd0ee5
shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents:
3230
diff
changeset
|
259 |
self._canvas.setFillAlpha(value) |
3198
683ca9eb6b18
reportlab: added in support for Overprint/Opacity & Separated colours (Opacity inspired by Simon King)
rgbecker
parents:
3032
diff
changeset
|
260 |
elif key=='strokeOpacity': |
3280
2ac121cd0ee5
shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents:
3230
diff
changeset
|
261 |
if value is not None: |
2ac121cd0ee5
shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents:
3230
diff
changeset
|
262 |
self._canvas.setStrokeAlpha(value) |
3198
683ca9eb6b18
reportlab: added in support for Overprint/Opacity & Separated colours (Opacity inspired by Simon King)
rgbecker
parents:
3032
diff
changeset
|
263 |
elif key=='fillOverprint': |
683ca9eb6b18
reportlab: added in support for Overprint/Opacity & Separated colours (Opacity inspired by Simon King)
rgbecker
parents:
3032
diff
changeset
|
264 |
self._canvas.setFillOverprint(value) |
683ca9eb6b18
reportlab: added in support for Overprint/Opacity & Separated colours (Opacity inspired by Simon King)
rgbecker
parents:
3032
diff
changeset
|
265 |
elif key=='strokeOverprint': |
3200 | 266 |
self._canvas.setStrokeOverprint(value) |
3417 | 267 |
elif key=='overprintMask': |
268 |
self._canvas.setOverprintMask(value) |
|
4325
fc03e6396da5
add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents:
4306
diff
changeset
|
269 |
elif key=='fillMode': |
fc03e6396da5
add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents:
4306
diff
changeset
|
270 |
self._canvas._fillMode = value |
568 | 271 |
|
272 |
from reportlab.platypus import Flowable |
|
273 |
class GraphicsFlowable(Flowable): |
|
274 |
"""Flowable wrapper around a Pingo drawing""" |
|
275 |
def __init__(self, drawing): |
|
276 |
self.drawing = drawing |
|
277 |
self.width = self.drawing.width |
|
278 |
self.height = self.drawing.height |
|
279 |
||
280 |
def draw(self): |
|
281 |
draw(self.drawing, self.canv, 0, 0) |
|
282 |
||
4274
ec03159b74bb
changes to Render class; allow drawings to specify initialFontName/Size version-->3.3.9
robin
parents:
4252
diff
changeset
|
283 |
def drawToFile(d, fn, msg="", showBoundary=rl_config._unset_, autoSize=1, canvasKwds={}): |
1003
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
284 |
"""Makes a one-page PDF with just the drawing. |
1683 | 285 |
|
1003
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
286 |
If autoSize=1, the PDF will be the same size as |
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
287 |
the drawing; if 0, it will place the drawing on |
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
288 |
an A4 page with a title above it - possibly overflowing |
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
289 |
if too big.""" |
2544
a6b9aa99b3c3
graphics: added Drawing.renderScale hack for renderer terminal drawing scales
rgbecker
parents:
2360
diff
changeset
|
290 |
d = renderScaledDrawing(d) |
4274
ec03159b74bb
changes to Render class; allow drawings to specify initialFontName/Size version-->3.3.9
robin
parents:
4252
diff
changeset
|
291 |
for x in ('Name','Size'): |
ec03159b74bb
changes to Render class; allow drawings to specify initialFontName/Size version-->3.3.9
robin
parents:
4252
diff
changeset
|
292 |
a = 'initialFont'+x |
ec03159b74bb
changes to Render class; allow drawings to specify initialFontName/Size version-->3.3.9
robin
parents:
4252
diff
changeset
|
293 |
canvasKwds[a] = getattr(d,a,canvasKwds.pop(a,STATE_DEFAULTS['font'+x])) |
ec03159b74bb
changes to Render class; allow drawings to specify initialFontName/Size version-->3.3.9
robin
parents:
4252
diff
changeset
|
294 |
c = Canvas(fn,**canvasKwds) |
3230
33c6da34f9b1
renderPDF.py: fix Times-Roman default usage in drawToFile, contributed by Volker haas
rgbecker
parents:
3222
diff
changeset
|
295 |
if msg: |
33c6da34f9b1
renderPDF.py: fix Times-Roman default usage in drawToFile, contributed by Volker haas
rgbecker
parents:
3222
diff
changeset
|
296 |
c.setFont(rl_config.defaultGraphicsFontName, 36) |
33c6da34f9b1
renderPDF.py: fix Times-Roman default usage in drawToFile, contributed by Volker haas
rgbecker
parents:
3222
diff
changeset
|
297 |
c.drawString(80, 750, msg) |
1003
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
298 |
c.setTitle(msg) |
1683 | 299 |
|
1003
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
300 |
if autoSize: |
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
301 |
c.setPageSize((d.width, d.height)) |
1072
9863f43fb323
drawToFile(): also pass showBoundary when doing autosize
jvr
parents:
1071
diff
changeset
|
302 |
draw(d, c, 0, 0, showBoundary=showBoundary) |
1003
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
303 |
else: |
3230
33c6da34f9b1
renderPDF.py: fix Times-Roman default usage in drawToFile, contributed by Volker haas
rgbecker
parents:
3222
diff
changeset
|
304 |
#show with a title |
33c6da34f9b1
renderPDF.py: fix Times-Roman default usage in drawToFile, contributed by Volker haas
rgbecker
parents:
3222
diff
changeset
|
305 |
c.setFont(rl_config.defaultGraphicsFontName, 12) |
1003
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
306 |
y = 740 |
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
307 |
i = 1 |
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
308 |
y = y - d.height |
2e5e95fba8e1
Added autoSize option to rendderPDF, and allowed "no border" around
andy_robinson
parents:
977
diff
changeset
|
309 |
draw(d, c, 80, y, showBoundary=showBoundary) |
568 | 310 |
|
2142 | 311 |
c.showPage() |
568 | 312 |
c.save() |
1969
4793febe488f
Now sets the file association correctly when producing PDFs on Apple Macs
johnprecedo
parents:
1952
diff
changeset
|
313 |
if sys.platform=='mac' and not hasattr(fn, "write"): |
4793febe488f
Now sets the file association correctly when producing PDFs on Apple Macs
johnprecedo
parents:
1952
diff
changeset
|
314 |
try: |
4793febe488f
Now sets the file association correctly when producing PDFs on Apple Macs
johnprecedo
parents:
1952
diff
changeset
|
315 |
import macfs, macostools |
4793febe488f
Now sets the file association correctly when producing PDFs on Apple Macs
johnprecedo
parents:
1952
diff
changeset
|
316 |
macfs.FSSpec(fn).SetCreatorType("CARO", "PDF ") |
4793febe488f
Now sets the file association correctly when producing PDFs on Apple Macs
johnprecedo
parents:
1952
diff
changeset
|
317 |
macostools.touched(fn) |
4793febe488f
Now sets the file association correctly when producing PDFs on Apple Macs
johnprecedo
parents:
1952
diff
changeset
|
318 |
except: |
4793febe488f
Now sets the file association correctly when producing PDFs on Apple Macs
johnprecedo
parents:
1952
diff
changeset
|
319 |
pass |
568 | 320 |
|
4274
ec03159b74bb
changes to Render class; allow drawings to specify initialFontName/Size version-->3.3.9
robin
parents:
4252
diff
changeset
|
321 |
def drawToString(d, msg="", showBoundary=rl_config._unset_,autoSize=1,canvasKwds={}): |
1728
4cc7ea74b2b3
Added drawToString method as suggested by Dirk Datzert
andy_robinson
parents:
1683
diff
changeset
|
322 |
"Returns a PDF as a string in memory, without touching the disk" |
3723
99aa837b6703
second stage of port to Python 3.3; working hello world
rptlab
parents:
3721
diff
changeset
|
323 |
s = getBytesIO() |
4274
ec03159b74bb
changes to Render class; allow drawings to specify initialFontName/Size version-->3.3.9
robin
parents:
4252
diff
changeset
|
324 |
drawToFile(d, s, msg=msg, showBoundary=showBoundary,autoSize=autoSize, canvasKwds=canvasKwds) |
1728
4cc7ea74b2b3
Added drawToString method as suggested by Dirk Datzert
andy_robinson
parents:
1683
diff
changeset
|
325 |
return s.getvalue() |
4cc7ea74b2b3
Added drawToString method as suggested by Dirk Datzert
andy_robinson
parents:
1683
diff
changeset
|
326 |
|
568 | 327 |
######################################################### |
328 |
# |
|
2678
38d18a697cd0
reportlab: Python2.5 changes + minor cosmetics and improvements
rgbecker
parents:
2575
diff
changeset
|
329 |
# test code. First, define a bunch of drawings. |
568 | 330 |
# Routine to draw them comes at the end. |
331 |
# |
|
332 |
######################################################### |
|
3977
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
333 |
def test(outDir='pdfout',shout=False): |
3368
afa025c34493
reportlab: new base font mechanism more fully applied
rgbecker
parents:
3280
diff
changeset
|
334 |
from reportlab.graphics.shapes import _baseGFontName, _baseGFontNameBI |
3977
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
335 |
from reportlab.rl_config import verbose |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
336 |
import os |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
337 |
if not os.path.isdir(outDir): |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
338 |
os.mkdir(outDir) |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
339 |
fn = os.path.join(outDir,'renderPDF.pdf') |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
340 |
c = Canvas(fn) |
3368
afa025c34493
reportlab: new base font mechanism more fully applied
rgbecker
parents:
3280
diff
changeset
|
341 |
c.setFont(_baseGFontName, 36) |
568 | 342 |
c.drawString(80, 750, 'Graphics Test') |
343 |
||
344 |
# print all drawings and their doc strings from the test |
|
345 |
# file |
|
346 |
||
347 |
#grab all drawings from the test module |
|
587 | 348 |
from reportlab.graphics import testshapes |
568 | 349 |
drawings = [] |
587 | 350 |
for funcname in dir(testshapes): |
568 | 351 |
if funcname[0:10] == 'getDrawing': |
4551 | 352 |
func = getattr(testshapes,funcname) |
353 |
drawing = func() #execute it |
|
354 |
docstring = getattr(func,'__doc__','') |
|
568 | 355 |
drawings.append((drawing, docstring)) |
356 |
||
357 |
#print in a loop, with their doc strings |
|
3368
afa025c34493
reportlab: new base font mechanism more fully applied
rgbecker
parents:
3280
diff
changeset
|
358 |
c.setFont(_baseGFontName, 12) |
568 | 359 |
y = 740 |
360 |
i = 1 |
|
361 |
for (drawing, docstring) in drawings: |
|
362 |
assert (docstring is not None), "Drawing %d has no docstring!" % i |
|
363 |
if y < 300: #allows 5-6 lines of text |
|
364 |
c.showPage() |
|
365 |
y = 740 |
|
366 |
# draw a title |
|
367 |
y = y - 30 |
|
3368
afa025c34493
reportlab: new base font mechanism more fully applied
rgbecker
parents:
3280
diff
changeset
|
368 |
c.setFont(_baseGFontNameBI,12) |
568 | 369 |
c.drawString(80, y, 'Drawing %d' % i) |
3368
afa025c34493
reportlab: new base font mechanism more fully applied
rgbecker
parents:
3280
diff
changeset
|
370 |
c.setFont(_baseGFontName,12) |
568 | 371 |
y = y - 14 |
372 |
textObj = c.beginText(80, y) |
|
373 |
textObj.textLines(docstring) |
|
374 |
c.drawText(textObj) |
|
375 |
y = textObj.getY() |
|
376 |
y = y - drawing.height |
|
377 |
draw(drawing, c, 80, y) |
|
378 |
i = i + 1 |
|
2142 | 379 |
if y!=740: c.showPage() |
568 | 380 |
|
381 |
c.save() |
|
3977
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
382 |
if shout or verbose>2: |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
383 |
print('saved %s' % ascii(fn)) |
568 | 384 |
|
385 |
if __name__=='__main__': |
|
3977
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
386 |
test(shout=True) |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
387 |
import sys |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
388 |
if len(sys.argv)>1: |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
389 |
outdir = sys.argv[1] |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
390 |
else: |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
391 |
outdir = 'pdfout' |
06da9dfa6e20
renderPDF/PM.py: make tests configuarble and add a unittest to call test()
robin
parents:
3975
diff
changeset
|
392 |
test(outdir,shout=True) |
1952 | 393 |
#testFlowable() |