summaryrefslogtreecommitdiff
path: root/bin/reportlab/graphics/renderPM.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/reportlab/graphics/renderPM.py')
-rw-r--r--bin/reportlab/graphics/renderPM.py663
1 files changed, 663 insertions, 0 deletions
diff --git a/bin/reportlab/graphics/renderPM.py b/bin/reportlab/graphics/renderPM.py
new file mode 100644
index 00000000000..35960a25b75
--- /dev/null
+++ b/bin/reportlab/graphics/renderPM.py
@@ -0,0 +1,663 @@
+#Copyright ReportLab Europe Ltd. 2000-2004
+#see license.txt for license details
+#history www.reportlab.co.uk/rl-cgi/viewcvs.cgi/rlextra/graphics/Csrc/renderPM/renderP.py
+__version__=''' $Id: renderPM.py 2830 2006-04-05 15:18:32Z rgbecker $ '''
+"""Usage:
+ from reportlab.graphics import renderPM
+ renderPM.drawToFile(drawing,filename,fmt='GIF',configPIL={....})
+Other functions let you create a PM drawing as string or into a PM buffer.
+Execute the script to see some test drawings."""
+
+from reportlab.graphics.shapes import *
+from reportlab.graphics.renderbase import StateTracker, getStateDelta, renderScaledDrawing
+from reportlab.pdfbase.pdfmetrics import getFont, unicode2T1
+from math import sin, cos, pi, ceil
+from reportlab.lib.utils import getStringIO, open_and_read
+from reportlab import rl_config
+
+class RenderPMError(Exception):
+ pass
+
+import string, os, sys
+
+try:
+ import _renderPM
+except ImportError, errMsg:
+ raise ImportError, "No module named _renderPM\n" + \
+ (str(errMsg)!='No module named _renderPM' and "it may be the wrong version or badly installed!" or
+ "see http://www.reportlab.org/rl_addons.html")
+
+from types import TupleType, ListType
+_SeqTypes = (TupleType,ListType)
+
+def _getImage():
+ try:
+ from PIL import Image
+ except ImportError:
+ import Image
+ return Image
+
+def Color2Hex(c):
+ #assert isinstance(colorobj, colors.Color) #these checks don't work well RGB
+ if c: return ((0xFF&int(255*c.red)) << 16) | ((0xFF&int(255*c.green)) << 8) | (0xFF&int(255*c.blue))
+ return c
+
+# the main entry point for users...
+def draw(drawing, canvas, x, y, showBoundary=rl_config._unset_):
+ """As it says"""
+ R = _PMRenderer()
+ R.draw(renderScaledDrawing(drawing), canvas, x, y, showBoundary=showBoundary)
+
+from reportlab.graphics.renderbase import Renderer
+class _PMRenderer(Renderer):
+ """This draws onto a pix map image. It needs to be a class
+ rather than a function, as some image-specific state tracking is
+ needed outside of the state info in the SVG model."""
+
+ def __init__(self):
+ self._tracker = StateTracker()
+
+ def pop(self):
+ self._tracker.pop()
+ self.applyState()
+
+ def push(self,node):
+ deltas = getStateDelta(node)
+ self._tracker.push(deltas)
+ self.applyState()
+
+ def applyState(self):
+ s = self._tracker.getState()
+ self._canvas.ctm = s['ctm']
+ self._canvas.strokeWidth = s['strokeWidth']
+ self._canvas.strokeColor = Color2Hex(s['strokeColor'])
+ self._canvas.lineCap = s['strokeLineCap']
+ self._canvas.lineJoin = s['strokeLineJoin']
+ da = s['strokeDashArray']
+ da = da and (0,da) or None
+ self._canvas.dashArray = da
+ self._canvas.fillColor = Color2Hex(s['fillColor'])
+ self._canvas.setFont(s['fontName'], s['fontSize'])
+
+ def initState(self,x,y):
+ deltas = STATE_DEFAULTS.copy()
+ deltas['transform'] = self._canvas._baseCTM[0:4]+(x,y)
+ self._tracker.push(deltas)
+ self.applyState()
+
+ def drawNode(self, node):
+ """This is the recursive method called for each node
+ in the tree"""
+
+ #apply state changes
+ self.push(node)
+
+ #draw the object, or recurse
+ self.drawNodeDispatcher(node)
+
+ # restore the state
+ self.pop()
+
+ def drawRect(self, rect):
+ c = self._canvas
+ if rect.rx == rect.ry == 0:
+ #plain old rectangle, draw clockwise (x-axis to y-axis) direction
+ c.rect(rect.x,rect.y, rect.width, rect.height)
+ else:
+ c.roundRect(rect.x,rect.y, rect.width, rect.height, rect.rx, rect.ry)
+
+ def drawLine(self, line):
+ self._canvas.line(line.x1,line.y1,line.x2,line.y2)
+
+ def drawImage(self, image):
+ if image.path and os.path.exists(image.path):
+ if type(image.path) is type(''):
+ im = _getImage().open(image.path).convert('RGB')
+ else:
+ im = image.path.convert('RGB')
+ srcW, srcH = im.size
+ dstW, dstH = image.width, image.height
+ if dstW is None: dstW = srcW
+ if dstH is None: dstH = srcH
+ self._canvas._aapixbuf(
+ image.x, image.y, dstW, dstH,
+ im.tostring(), srcW, srcH, 3,
+ )
+
+ def drawCircle(self, circle):
+ c = self._canvas
+ c.circle(circle.cx,circle.cy, circle.r)
+ c.fillstrokepath()
+
+ def drawPolyLine(self, polyline, _doClose=0):
+ P = polyline.points
+ assert len(P) >= 2, 'Polyline must have 1 or more points'
+ c = self._canvas
+ c.pathBegin()
+ c.moveTo(P[0], P[1])
+ for i in range(2, len(P), 2):
+ c.lineTo(P[i], P[i+1])
+ if _doClose:
+ c.pathClose()
+ c.pathFill()
+ c.pathStroke()
+
+ def drawEllipse(self, ellipse):
+ c=self._canvas
+ c.ellipse(ellipse.cx, ellipse.cy, ellipse.rx,ellipse.ry)
+ c.fillstrokepath()
+
+ def drawPolygon(self, polygon):
+ self.drawPolyLine(polygon,_doClose=1)
+
+ def drawString(self, stringObj):
+ canv = self._canvas
+ fill = canv.fillColor
+ if fill is not None:
+ S = self._tracker.getState()
+ text_anchor = S['textAnchor']
+ fontName = S['fontName']
+ fontSize = S['fontSize']
+ font = getFont(fontName)
+ text = stringObj.text
+ x = stringObj.x
+ y = stringObj.y
+ if not text_anchor in ['start','inherited']:
+ textLen = stringWidth(text, fontName,fontSize)
+ if text_anchor=='end':
+ x = x-textLen
+ elif text_anchor=='middle':
+ x = x - textLen/2
+ else:
+ raise ValueError, 'bad value for textAnchor '+str(text_anchor)
+ if getattr(font,'_dynamicFont',None):
+ if isinstance(text,unicode): text = text.encode('utf8')
+ canv.drawString(x,y,text)
+ else:
+ fc = font
+ if not isinstance(text,unicode):
+ try:
+ text = text.decode('utf8')
+ except UnicodeDecodeError,e:
+ i,j = e.args[2:4]
+ raise UnicodeDecodeError(*(e.args[:4]+('%s\n%s-->%s<--%s' % (e.args[4],text[i-10:i],text[i:j],text[j:j+10]),)))
+
+ FT = unicode2T1(text,[font]+font.substitutionFonts)
+ n = len(FT)
+ nm1 = n-1
+ wscale = 0.001*fontSize
+ for i in xrange(n):
+ f, t = FT[i]
+ if f!=fc:
+ canv.setFont(f.fontName,fontSize)
+ fc = f
+ canv.drawString(x,y,t)
+ if i!=nm1:
+ x += wscale*sum(map(f.widths.__getitem__,map(ord,t)))
+ if font!=fc:
+ canv.setFont(fontName,fontSize)
+
+ def drawPath(self, path):
+ c = self._canvas
+ if path is EmptyClipPath:
+ del c._clipPaths[-1]
+ if c._clipPaths:
+ P = c._clipPaths[-1]
+ icp = P.isClipPath
+ P.isClipPath = 1
+ self.drawPath(P)
+ P.isClipPath = icp
+ else:
+ c.clipPathClear()
+ return
+ c.pathBegin()
+ drawFuncs = (c.moveTo, c.lineTo, c.curveTo, c.pathClose)
+ from reportlab.graphics.shapes import _renderPath
+ isClosed = _renderPath(path, drawFuncs)
+ if path.isClipPath:
+ c.clipPathSet()
+ c._clipPaths.append(path)
+ else:
+ if isClosed: c.pathFill()
+ c.pathStroke()
+
+def _setFont(gs,fontName,fontSize):
+ try:
+ gs.setFont(fontName,fontSize)
+ except _renderPM.Error, errMsg:
+ if errMsg.args[0]!="Can't find font!": raise
+ #here's where we try to add a font to the canvas
+ try:
+ f = getFont(fontName)
+ if _renderPM._version<='0.98': #added reader arg in 0.99
+ _renderPM.makeT1Font(fontName,f.face.findT1File(),f.encoding.vector)
+ else:
+ _renderPM.makeT1Font(fontName,f.face.findT1File(),f.encoding.vector,open_and_read)
+ except:
+ s1, s2 = map(str,sys.exc_info()[:2])
+ raise RenderPMError, "Can't setFont(%s) missing the T1 files?\nOriginally %s: %s" % (fontName,s1,s2)
+ gs.setFont(fontName,fontSize)
+
+def _convert2pilp(im):
+ Image = _getImage()
+ return im.convert("P", dither=Image.NONE, palette=Image.ADAPTIVE)
+
+def _saveAsPICT(im,fn,fmt,transparent=None):
+ im = _convert2pilp(im)
+ cols, rows = im.size
+ #s = _renderPM.pil2pict(cols,rows,im.tostring(),im.im.getpalette(),transparent is not None and Color2Hex(transparent) or -1)
+ s = _renderPM.pil2pict(cols,rows,im.tostring(),im.im.getpalette())
+ if not hasattr(fn,'write'):
+ open(os.path.splitext(fn)[0]+'.'+string.lower(fmt),'wb').write(s)
+ if os.name=='mac':
+ from reportlab.lib.utils import markfilename
+ markfilename(fn,ext='PICT')
+ else:
+ fn.write(s)
+
+BEZIER_ARC_MAGIC = 0.5522847498 #constant for drawing circular arcs w/ Beziers
+class PMCanvas:
+ def __init__(self,w,h,dpi=72,bg=0xffffff,configPIL=None):
+ '''configPIL dict is passed to image save method'''
+ scale = dpi/72.0
+ w = int(w*scale+0.5)
+ h = int(h*scale+0.5)
+ self.__dict__['_gs'] = _renderPM.gstate(w,h,bg=bg)
+ self.__dict__['_bg'] = bg
+ self.__dict__['_baseCTM'] = (scale,0,0,scale,0,0)
+ self.__dict__['_clipPaths'] = []
+ self.__dict__['configPIL'] = configPIL
+ self.__dict__['_dpi'] = dpi
+ self.ctm = self._baseCTM
+
+ def _drawTimeResize(self,w,h,bg=None):
+ if bg is None: bg = self._bg
+ self._drawing.width, self._drawing.height = w, h
+ A = {'ctm':None, 'strokeWidth':None, 'strokeColor':None, 'lineCap':None, 'lineJoin':None, 'dashArray':None, 'fillColor':None}
+ gs = self._gs
+ fN,fS = gs.fontName, gs.fontSize
+ for k in A.keys():
+ A[k] = getattr(gs,k)
+ del gs, self._gs
+ gs = self.__dict__['_gs'] = _renderPM.gstate(w,h,bg=bg)
+ for k in A.keys():
+ setattr(self,k,A[k])
+ gs.setFont(fN,fS)
+
+ def toPIL(self):
+ im = _getImage().new('RGB', size=(self._gs.width, self._gs.height))
+ im.fromstring(self._gs.pixBuf)
+ return im
+
+ def saveToFile(self,fn,fmt=None):
+ im = self.toPIL()
+ if fmt is None:
+ if type(fn) is not StringType:
+ raise ValueError, "Invalid type '%s' for fn when fmt is None" % type(fn)
+ fmt = os.path.splitext(fn)[1]
+ if fmt.startswith('.'): fmt = fmt[1:]
+ configPIL = self.configPIL or {}
+ fmt = string.upper(fmt)
+ if fmt in ['GIF']:
+ im = _convert2pilp(im)
+ elif fmt in ['PCT','PICT']:
+ return _saveAsPICT(im,fn,fmt,transparent=configPIL.get('transparent',None))
+ elif fmt in ['PNG','TIFF','BMP', 'PPM', 'TIF']:
+ if fmt=='TIF': fmt = 'TIFF'
+ if fmt=='PNG':
+ try:
+ from PIL import PngImagePlugin
+ except ImportError:
+ import PngImagePlugin
+ elif fmt=='BMP':
+ try:
+ from PIL import BmpImagePlugin
+ except ImportError:
+ import BmpImagePlugin
+ elif fmt in ('JPG','JPEG'):
+ fmt = 'JPEG'
+ else:
+ raise RenderPMError,"Unknown image kind %s" % fmt
+ if fmt=='TIFF':
+ tc = configPIL.get('transparent',None)
+ if tc:
+ from PIL import ImageChops, Image
+ T = 768*[0]
+ for o, c in zip((0,256,512), tc.bitmap_rgb()):
+ T[o+c] = 255
+ #if type(fn) is type(''): ImageChops.invert(im.point(T).convert('L').point(255*[0]+[255])).save(fn+'_mask.gif','GIF')
+ im = Image.merge('RGBA', im.split()+(ImageChops.invert(im.point(T).convert('L').point(255*[0]+[255])),))
+ #if type(fn) is type(''): im.save(fn+'_masked.gif','GIF')
+ for a,d in ('resolution',self._dpi),('resolution unit','inch'):
+ configPIL[a] = configPIL.get(a,d)
+ apply(im.save,(fn,fmt),configPIL)
+ if not hasattr(fn,'write') and os.name=='mac':
+ from reportlab.lib.utils import markfilename
+ markfilename(fn,ext=fmt)
+
+ def saveToString(self,fmt='GIF'):
+ s = getStringIO()
+ self.saveToFile(s,fmt=fmt)
+ return s.getvalue()
+
+ def _saveToBMP(self,f):
+ '''
+ Niki Spahiev, <niki@vintech.bg>, asserts that this is a respectable way to get BMP without PIL
+ f is a file like object to which the BMP is written
+ '''
+ import struct
+ gs = self._gs
+ pix, width, height = gs.pixBuf, gs.width, gs.height
+ f.write(struct.pack('=2sLLLLLLhh24x','BM',len(pix)+54,0,54,40,width,height,1,24))
+ rowb = width * 3
+ for o in range(len(pix),0,-rowb):
+ f.write(pix[o-rowb:o])
+ f.write( '\0' * 14 )
+
+ def setFont(self,fontName,fontSize,leading=None):
+ _setFont(self._gs,fontName,fontSize)
+
+ def __setattr__(self,name,value):
+ setattr(self._gs,name,value)
+
+ def __getattr__(self,name):
+ return getattr(self._gs,name)
+
+ def fillstrokepath(self,stroke=1,fill=1):
+ if fill: self.pathFill()
+ if stroke: self.pathStroke()
+
+ def _bezierArcSegmentCCW(self, cx,cy, rx,ry, theta0, theta1):
+ """compute the control points for a bezier arc with theta1-theta0 <= 90.
+ Points are computed for an arc with angle theta increasing in the
+ counter-clockwise (CCW) direction. returns a tuple with starting point
+ and 3 control points of a cubic bezier curve for the curvto opertator"""
+
+ # Requires theta1 - theta0 <= 90 for a good approximation
+ assert abs(theta1 - theta0) <= 90
+ cos0 = cos(pi*theta0/180.0)
+ sin0 = sin(pi*theta0/180.0)
+ x0 = cx + rx*cos0
+ y0 = cy + ry*sin0
+
+ cos1 = cos(pi*theta1/180.0)
+ sin1 = sin(pi*theta1/180.0)
+
+ x3 = cx + rx*cos1
+ y3 = cy + ry*sin1
+
+ dx1 = -rx * sin0
+ dy1 = ry * cos0
+
+ #from pdfgeom
+ halfAng = pi*(theta1-theta0)/(2.0 * 180.0)
+ k = abs(4.0 / 3.0 * (1.0 - cos(halfAng) ) /(sin(halfAng)) )
+ x1 = x0 + dx1 * k
+ y1 = y0 + dy1 * k
+
+ dx2 = -rx * sin1
+ dy2 = ry * cos1
+
+ x2 = x3 - dx2 * k
+ y2 = y3 - dy2 * k
+ return ((x0,y0), ((x1,y1), (x2,y2), (x3,y3)) )
+
+ def bezierArcCCW(self, cx,cy, rx,ry, theta0, theta1):
+ """return a set of control points for Bezier approximation to an arc
+ with angle increasing counter clockwise. No requirement on |theta1-theta0| <= 90
+ However, it must be true that theta1-theta0 > 0."""
+
+ # I believe this is also clockwise
+ # pretty much just like Robert Kern's pdfgeom.BezierArc
+ angularExtent = theta1 - theta0
+ # break down the arc into fragments of <=90 degrees
+ if abs(angularExtent) <= 90.0: # we just need one fragment
+ angleList = [(theta0,theta1)]
+ else:
+ Nfrag = int( ceil( abs(angularExtent)/90.) )
+ fragAngle = float(angularExtent)/ Nfrag # this could be negative
+ angleList = []
+ for ii in range(Nfrag):
+ a = theta0 + ii * fragAngle
+ b = a + fragAngle # hmm.. is I wonder if this is precise enought
+ angleList.append((a,b))
+
+ ctrlpts = []
+ for (a,b) in angleList:
+ if not ctrlpts: # first time
+ [(x0,y0), pts] = self._bezierArcSegmentCCW(cx,cy, rx,ry, a,b)
+ ctrlpts.append(pts)
+ else:
+ [(tmpx,tmpy), pts] = self._bezierArcSegmentCCW(cx,cy, rx,ry, a,b)
+ ctrlpts.append(pts)
+ return ((x0,y0), ctrlpts)
+
+ def addEllipsoidalArc(self, cx,cy, rx, ry, ang1, ang2):
+ """adds an ellisesoidal arc segment to a path, with an ellipse centered
+ on cx,cy and with radii (major & minor axes) rx and ry. The arc is
+ drawn in the CCW direction. Requires: (ang2-ang1) > 0"""
+
+ ((x0,y0), ctrlpts) = self.bezierArcCCW(cx,cy, rx,ry,ang1,ang2)
+
+ self.lineTo(x0,y0)
+ for ((x1,y1), (x2,y2),(x3,y3)) in ctrlpts:
+ self.curveTo(x1,y1,x2,y2,x3,y3)
+
+ def drawCentredString(self, x, y, text, text_anchor='middle'):
+ if self.fillColor is not None:
+ textLen = stringWidth(text, self.fontName,self.fontSize)
+ if text_anchor=='end':
+ x -= textLen
+ elif text_anchor=='middle':
+ x -= textLen/2.
+ self.drawString(x,y,text)
+
+ def drawRightString(self, text, x, y):
+ self.drawCentredString(text,x,y,text_anchor='end')
+
+ def line(self,x1,y1,x2,y2):
+ if self.strokeColor is not None:
+ self.pathBegin()
+ self.moveTo(x1,y1)
+ self.lineTo(x2,y2)
+ self.pathStroke()
+
+ def rect(self,x,y,width,height,stroke=1,fill=1):
+ self.pathBegin()
+ self.moveTo(x, y)
+ self.lineTo(x+width, y)
+ self.lineTo(x+width, y + height)
+ self.lineTo(x, y + height)
+ self.pathClose()
+ self.fillstrokepath(stroke=stroke,fill=fill)
+
+ def roundRect(self, x, y, width, height, rx,ry):
+ """rect(self, x, y, width, height, rx,ry):
+ Draw a rectangle if rx or rx and ry are specified the corners are
+ rounded with ellipsoidal arcs determined by rx and ry
+ (drawn in the counter-clockwise direction)"""
+ if rx==0: rx = ry
+ if ry==0: ry = rx
+ x2 = x + width
+ y2 = y + height
+ self.pathBegin()
+ self.moveTo(x+rx,y)
+ self.addEllipsoidalArc(x2-rx, y+ry, rx, ry, 270, 360 )
+ self.addEllipsoidalArc(x2-rx, y2-ry, rx, ry, 0, 90)
+ self.addEllipsoidalArc(x+rx, y2-ry, rx, ry, 90, 180)
+ self.addEllipsoidalArc(x+rx, y+ry, rx, ry, 180, 270)
+ self.pathClose()
+ self.fillstrokepath()
+
+ def circle(self, cx, cy, r):
+ "add closed path circle with center cx,cy and axes r: counter-clockwise orientation"
+ self.ellipse(cx,cy,r,r)
+
+ def ellipse(self, cx,cy,rx,ry):
+ """add closed path ellipse with center cx,cy and axes rx,ry: counter-clockwise orientation
+ (remember y-axis increases downward) """
+ self.pathBegin()
+ # first segment
+ x0 = cx + rx # (x0,y0) start pt
+ y0 = cy
+
+ x3 = cx # (x3,y3) end pt of arc
+ y3 = cy-ry
+
+ x1 = cx+rx
+ y1 = cy-ry*BEZIER_ARC_MAGIC
+
+ x2 = x3 + rx*BEZIER_ARC_MAGIC
+ y2 = y3
+ self.moveTo(x0, y0)
+ self.curveTo(x1,y1,x2,y2,x3,y3)
+ # next segment
+ x0 = x3
+ y0 = y3
+
+ x3 = cx-rx
+ y3 = cy
+
+ x1 = cx-rx*BEZIER_ARC_MAGIC
+ y1 = cy-ry
+
+ x2 = x3
+ y2 = cy- ry*BEZIER_ARC_MAGIC
+ self.curveTo(x1,y1,x2,y2,x3,y3)
+ # next segment
+ x0 = x3
+ y0 = y3
+
+ x3 = cx
+ y3 = cy+ry
+
+ x1 = cx-rx
+ y1 = cy+ry*BEZIER_ARC_MAGIC
+
+ x2 = cx -rx*BEZIER_ARC_MAGIC
+ y2 = cy+ry
+ self.curveTo(x1,y1,x2,y2,x3,y3)
+ #last segment
+ x0 = x3
+ y0 = y3
+
+ x3 = cx+rx
+ y3 = cy
+
+ x1 = cx+rx*BEZIER_ARC_MAGIC
+ y1 = cy+ry
+
+ x2 = cx+rx
+ y2 = cy+ry*BEZIER_ARC_MAGIC
+ self.curveTo(x1,y1,x2,y2,x3,y3)
+ self.pathClose()
+
+ def saveState(self):
+ '''do nothing for compatibility'''
+ pass
+
+ def setFillColor(self,aColor):
+ self.fillColor = Color2Hex(aColor)
+
+ def setStrokeColor(self,aColor):
+ self.strokeColor = Color2Hex(aColor)
+
+ restoreState = saveState
+
+ # compatibility routines
+ def setLineCap(self,cap):
+ self.lineCap = cap
+
+ def setLineWidth(self,width):
+ self.strokeWidth = width
+
+def drawToPMCanvas(d, dpi=72, bg=0xffffff, configPIL=None, showBoundary=rl_config._unset_):
+ d = renderScaledDrawing(d)
+ c = PMCanvas(d.width, d.height, dpi=dpi, bg=bg, configPIL=configPIL)
+ draw(d, c, 0, 0, showBoundary=showBoundary)
+ return c
+
+def drawToPIL(d, dpi=72, bg=0xffffff, configPIL=None, showBoundary=rl_config._unset_):
+ return drawToPMCanvas(d, dpi=dpi, bg=bg, configPIL=configPIL, showBoundary=showBoundary).toPIL()
+
+def drawToPILP(d, dpi=72, bg=0xffffff, configPIL=None, showBoundary=rl_config._unset_):
+ Image = _getImage()
+ im = drawToPIL(d, dpi=dpi, bg=bg, configPIL=configPIL, showBoundary=showBoundary)
+ return im.convert("P", dither=Image.NONE, palette=Image.ADAPTIVE)
+
+def drawToFile(d,fn,fmt='GIF', dpi=72, bg=0xffffff, configPIL=None, showBoundary=rl_config._unset_):
+ '''create a pixmap and draw drawing, d to it then save as a file
+ configPIL dict is passed to image save method'''
+ c = drawToPMCanvas(d, dpi=dpi, bg=bg, configPIL=configPIL, showBoundary=showBoundary)
+ c.saveToFile(fn,fmt)
+
+def drawToString(d,fmt='GIF', dpi=72, bg=0xffffff, configPIL=None, showBoundary=rl_config._unset_):
+ s = getStringIO()
+ drawToFile(d,s,fmt=fmt, dpi=dpi, bg=bg, configPIL=configPIL)
+ return s.getvalue()
+
+save = drawToFile
+
+def test():
+ def ext(x):
+ if x=='tiff': x='tif'
+ return x
+ #grab all drawings from the test module and write out.
+ #make a page of links in HTML to assist viewing.
+ import os
+ from reportlab.graphics import testshapes
+ getAllTestDrawings = testshapes.getAllTestDrawings
+ drawings = []
+ if not os.path.isdir('pmout'):
+ os.mkdir('pmout')
+ htmlTop = """<html><head><title>renderPM output results</title></head>
+ <body>
+ <h1>renderPM results of output</h1>
+ """
+ htmlBottom = """</body>
+ </html>
+ """
+ html = [htmlTop]
+
+ i = 0
+ #print in a loop, with their doc strings
+ for (drawing, docstring, name) in getAllTestDrawings(doTTF=hasattr(_renderPM,'ft_get_face')):
+ fnRoot = 'renderPM%d' % i
+ if 1 or i==10:
+ w = int(drawing.width)
+ h = int(drawing.height)
+ html.append('<hr><h2>Drawing %s %d</h2>\n<pre>%s</pre>' % (name, i, docstring))
+
+ for k in ['gif','tiff', 'png', 'jpg', 'pct']:
+ if k in ['gif','png','jpg','pct']:
+ html.append('<p>%s format</p>\n' % string.upper(k))
+ try:
+ filename = '%s.%s' % (fnRoot, ext(k))
+ fullpath = os.path.join('pmout', filename)
+ if os.path.isfile(fullpath):
+ os.remove(fullpath)
+ if k=='pct':
+ from reportlab.lib.colors import white
+ drawToFile(drawing,fullpath,fmt=k,configPIL={'transparent':white})
+ else:
+ drawToFile(drawing,fullpath,fmt=k)
+ if k in ['gif','png','jpg']:
+ html.append('<img src="%s" border="1"><br>\n' % filename)
+ print 'wrote',fullpath
+ except AttributeError:
+ print 'Problem drawing %s file'%k
+ raise
+ if os.environ.get('RL_NOEPSPREVIEW','0')=='1': drawing.__dict__['preview'] = 0
+ drawing.save(formats=['eps','pdf'],outDir='pmout',fnRoot=fnRoot)
+ i = i + 1
+ #if i==10: break
+ html.append(htmlBottom)
+ htmlFileName = os.path.join('pmout', 'index.html')
+ open(htmlFileName, 'w').writelines(html)
+ if sys.platform=='mac':
+ from reportlab.lib.utils import markfilename
+ markfilename(htmlFileName,ext='HTML')
+ print 'wrote %s' % htmlFileName
+
+if __name__=='__main__':
+ test()