def sample2(): drawing = Drawing(400, 200) data = [(13, 5, 20, 22, 37, 45, 19, 4), (5, 20, 46, 38, 23, 21, 6, 14)] lc = HorizontalLineChart() lc.x = 50 lc.y = 50 lc.height = 125 lc.width = 300 lc.data = data lc.joinedLines = 1 lc.lines.symbol = makeMarker("Smiley") lc.lineLabelFormat = "%2.0f" lc.strokeColor = colors.black lc.fillColor = colors.lightblue catNames = "Jan Feb Mar Apr May Jun Jul Aug".split(" ") lc.categoryAxis.categoryNames = catNames lc.categoryAxis.labels.boxAnchor = "n" lc.valueAxis.valueMin = 0 lc.valueAxis.valueMax = 60 lc.valueAxis.valueStep = 15 drawing.add(lc) return drawing
def demo(self): D = Drawing(100, 100) g = Grid() D.add(g) return D
def sample2(): "Make a pie chart with nine slices." d = Drawing(400, 200) pc = Pie() pc.x = 125 pc.y = 25 pc.data = [0.31, 0.148, 0.108, 0.076, 0.033, 0.03, 0.019, 0.126, 0.15] pc.labels = ['1', '2', '3', '4', '5', '6', '7', '8', 'X'] pc.width = 150 pc.height = 150 pc.slices.strokeWidth=1#0.5 pc.slices[0].fillColor = colors.steelblue pc.slices[1].fillColor = colors.thistle pc.slices[2].fillColor = colors.cornflower pc.slices[3].fillColor = colors.lightsteelblue pc.slices[4].fillColor = colors.aquamarine pc.slices[5].fillColor = colors.cadetblue pc.slices[6].fillColor = colors.lightcoral pc.slices[7].fillColor = colors.tan pc.slices[8].fillColor = colors.darkseagreen d.add(pc) return d
def generate_histogram(data, left=True): chart = HorizontalBarChart() drawing = Drawing(300, 400) chart.bars.strokeColor = None chart.bars[0].fillColor = chartreuse if left else coral chart.x = 20 if left else 0 chart.y = 0 chart.width = 245 chart.height = 400 chart.data = [[data['hist'][c] for c in data['hist']]] chart.strokeColor = None chart.fillColor = None chart.valueAxis.valueMin = 0 chart.valueAxis.valueMax = max(chart.data[0]) * 1.1 # chart.valueAxis.visibleTicks = False # chart.valueAxis.valueStep = 10 chart.valueAxis.reverseDirection = 1 if left else 0 chart.categoryAxis.labels.boxAnchor = 'nw' if left else 'ne' chart.categoryAxis.labels.dx = 6 if left else -6 chart.categoryAxis.labels.dy = 8 chart.categoryAxis.categoryNames = [c for c in data['hist']] chart.categoryAxis.joinAxisMode = 'right' if left else 'left' chart.categoryAxis.reverseDirection = 1 chart.categoryAxis.visibleTicks = False chart.categoryAxis.visibleAxis = False chart.categoryAxis.strokeColor = None drawing.add(chart) return drawing
def sample2(): "Make a spider chart with markers, but no fill" d = Drawing(400, 400) sp = SpiderChart() sp.x = 50 sp.y = 50 sp.width = 300 sp.height = 300 sp.data = [[10,12,14,16,14,12], [6,8,10,12,9,15],[7,8,17,4,12,8]] sp.labels = ['U','V','W','X','Y','Z'] sp.strands.strokeWidth = 1 sp.strands[0].fillColor = colors.pink sp.strands[1].fillColor = colors.lightblue sp.strands[2].fillColor = colors.palegreen sp.strands[0].strokeColor = colors.red sp.strands[1].strokeColor = colors.blue sp.strands[2].strokeColor = colors.green sp.strands.symbol = "FilledDiamond" sp.strands[1].symbol = makeMarker("Circle") sp.strands[1].symbol.strokeWidth = 0.5 sp.strands[1].symbol.fillColor = colors.yellow sp.strands.symbolSize = 6 sp.strandLabels[0,3]._text = 'special' sp.strandLabels[0,1]._text = 'one' sp.strandLabels[0,0]._text = 'zero' sp.strandLabels[1,0]._text = 'Earth' sp.strandLabels[2,2]._text = 'Mars' sp.strandLabels.format = 'values' sp.strandLabels.dR = -5 d.add(sp) return d
class PieRender(IRender): def __init__(self, width, height, labels, data): IRender.__init__(self, width, height, labels, data) #self.w = self.width #self.h = self.height #data = {} #for value in self.data: # data[value[0]] = int(value[1]) #plot = cairoplot.PiePlot('/tmp/tmp.png', data, self.w*2, self.h*2, gradient=True) ##plot.font_size *= 2 #plot.render() #plot.commit() #with open('/tmp/tmp.png') as f: # self.image = Image(StringIO(f.read()), self.w, self.h) pc = Pie() pc.width = min(self.height,self.width - 150) pc.height = min(self.height - 50,self.width) pc.width = pc.height = min(pc.height, pc.width) pc.x = self.width / 2 - pc.width / 2 pc.y = self.height / 2 - pc.height / 2 pc.data = [int(line[1]) for line in self.data] pc.labels = [line[0] for line in self.data] for i in xrange(len(self.data)): pc.slices[i].fillColor = COLORS[i % len(COLORS)] pc.slices[i].strokeColor = COLORS[i % len(COLORS)] self.drawing = Drawing(self.width, self.height) self.drawing.add(pc) def render(self): return self.drawing
def demo(self): d = Drawing(200, 100) pc = Pie() pc.x = 50 pc.y = 10 pc.width = 100 pc.height = 80 pc.data = [10,20,30,40,50,60] pc.labels = ['a','b','c','d','e','f'] pc.slices.strokeWidth=0.5 pc.slices[3].popout = 10 pc.slices[3].strokeWidth = 2 pc.slices[3].strokeDashArray = [2,2] pc.slices[3].labelRadius = 1.75 pc.slices[3].fontColor = colors.red pc.slices[0].fillColor = colors.darkcyan pc.slices[1].fillColor = colors.blueviolet pc.slices[2].fillColor = colors.blue pc.slices[3].fillColor = colors.cyan pc.slices[4].fillColor = colors.aquamarine pc.slices[5].fillColor = colors.cadetblue pc.slices[6].fillColor = colors.lightcoral self.slices[1].visible = 0 self.slices[3].visible = 1 self.slices[4].visible = 1 self.slices[5].visible = 1 self.slices[6].visible = 0 d.add(pc) return d
def sample2(): "Make a spider chart with markers, but no fill" d = Drawing(400, 400) pc = SpiderChart() pc.x = 50 pc.y = 50 pc.width = 300 pc.height = 300 pc.data = [[10,12,14,16,14,12], [6,8,10,12,9,15],[7,8,17,4,12,8,3]] pc.labels = ['U','V','W','X','Y','Z'] pc.strands.strokeWidth = 2 pc.strands[0].fillColor = None pc.strands[1].fillColor = None pc.strands[2].fillColor = None pc.strands[0].strokeColor = colors.red pc.strands[1].strokeColor = colors.blue pc.strands[2].strokeColor = colors.green pc.strands.markers = 1 pc.strands.markerType = "FilledDiamond" pc.strands.markerSize = 6 d.add(pc) return d
def demo(self): d = Drawing(200, 100) dn = Doughnut() dn.x = 50 dn.y = 10 dn.width = 100 dn.height = 80 dn.data = [10, 20, 30, 40, 50, 60] dn.labels = ["a", "b", "c", "d", "e", "f"] dn.slices.strokeWidth = 0.5 dn.slices[3].popout = 10 dn.slices[3].strokeWidth = 2 dn.slices[3].strokeDashArray = [2, 2] dn.slices[3].labelRadius = 1.75 dn.slices[3].fontColor = colors.red dn.slices[0].fillColor = colors.darkcyan dn.slices[1].fillColor = colors.blueviolet dn.slices[2].fillColor = colors.blue dn.slices[3].fillColor = colors.cyan dn.slices[4].fillColor = colors.aquamarine dn.slices[5].fillColor = colors.cadetblue dn.slices[6].fillColor = colors.lightcoral d.add(dn) return d
def demo(self,drawing=None): from reportlab.lib import colors if not drawing: drawing = Drawing(400, 200) lp = AdjLinePlot() lp.x = 50 lp.y = 50 lp.height = 125 lp.width = 300 lp.data = _monthlyIndexData lp.joinedLines = 1 lp.strokeColor = colors.black c0 = colors.PCMYKColor(100,65,0,30, spotName='PANTONE 288 CV', density=100) lp.lines[0].strokeColor = c0 lp.lines[0].strokeWidth = 2 lp.lines[0].strokeDashArray = None c1 = colors.PCMYKColor(0,79,91,0, spotName='PANTONE Wm Red CV', density=100) lp.lines[1].strokeColor = c1 lp.lines[1].strokeWidth = 1 lp.lines[1].strokeDashArray = [3,1] lp.xValueAxis.labels.fontSize = 10 lp.xValueAxis.labels.textAnchor = 'start' lp.xValueAxis.labels.boxAnchor = 'w' lp.xValueAxis.labels.angle = -45 lp.xValueAxis.labels.dx = 0 lp.xValueAxis.labels.dy = -8 lp.xValueAxis.xLabelFormat = '{mm}/{yy}' lp.yValueAxis.labelTextFormat = '%5d%% ' lp.yValueAxis.tickLeft = 5 lp.yValueAxis.labels.fontSize = 10 lp.background = Grid() lp.background.stripeColors = [colors.pink, colors.lightblue] lp.background.orientation = 'vertical' drawing.add(lp,'plot') return drawing
def sample1b(): "A line plot with non-equidistant points in x-axis." drawing = Drawing(400, 200) data = [ ((1,1), (2,2), (2.5,1), (3,3), (4,5)), ((1,2), (2,3), (2.5,2), (3.5,5), (4,6)) ] lp = LinePlot() lp.x = 50 lp.y = 50 lp.height = 125 lp.width = 300 lp.data = data lp.joinedLines = 1 lp.lines.symbol = makeMarker('Circle') lp.lineLabelFormat = '%2.0f' lp.strokeColor = colors.black lp.xValueAxis.valueMin = 0 lp.xValueAxis.valueMax = 5 lp.xValueAxis.valueSteps = [1, 2, 2.5, 3, 4, 5] lp.xValueAxis.labelTextFormat = '%2.1f' lp.yValueAxis.valueMin = 0 lp.yValueAxis.valueMax = 7 lp.yValueAxis.valueStep = 1 drawing.add(lp) return drawing
def sample3(): drawing = Drawing(400, 200) data = [ (13, 5, 20, 22, 37, 45, 19, 4), (5, 20, 46, 38, 23, 21, 6, 14) ] lc = HorizontalLineChart() lc.x = 50 lc.y = 50 lc.height = 125 lc.width = 300 lc.data = data lc.joinedLines = 1 lc.lineLabelFormat = '%2.0f' lc.strokeColor = colors.black lc.lines[0].symbol = makeMarker('Smiley') lc.lines[1].symbol = NoEntry lc.lines[0].strokeWidth = 2 lc.lines[1].strokeWidth = 4 catNames = 'Jan Feb Mar Apr May Jun Jul Aug'.split(' ') lc.categoryAxis.categoryNames = catNames lc.categoryAxis.labels.boxAnchor = 'n' lc.valueAxis.valueMin = 0 lc.valueAxis.valueMax = 60 lc.valueAxis.valueStep = 15 drawing.add(lc) return drawing
def drawOn(self, canvas): logo = self.logo x, y = logo.x, logo.y w, h = logo.width, logo.height D = Drawing(w, h) D.add(logo) D.drawOn(canvas, 0, 0)
def get_drawing(self, chart): """Create and returns the drawing, to be generated""" drawing = Drawing(self.width, self.height) # Make the title title = self.make_title(drawing) # Setting chart dimensions chart.height = self.height chart.width = self.width # Make the legend legend = self.make_legend(drawing, chart) if title: chart.height -= self.title.get('height', DEFAULT_TITLE_HEIGHT) self.top += self.title.get('height', DEFAULT_TITLE_HEIGHT) # Setting additional chart attributes self.set_chart_style(chart) # Adds the chart to drawing to return drawing.add(chart) # Resizes to make sure everything is fitting drawing = drawing.resized() return drawing
def sample1a(): drawing = Drawing(400, 200) data = [ (13, 5, 20, 22, 37, 45, 19, 4), (5, 20, 46, 38, 23, 21, 6, 14) ] lc = SampleHorizontalLineChart() lc.x = 50 lc.y = 50 lc.height = 125 lc.width = 300 lc.data = data lc.joinedLines = 1 lc.strokeColor = colors.white lc.fillColor = colors.HexColor(0xCCCCCC) lc.lines.symbol = makeMarker('FilledDiamond') lc.lineLabelFormat = '%2.0f' catNames = 'Jan Feb Mar Apr May Jun Jul Aug'.split(' ') lc.categoryAxis.categoryNames = catNames lc.categoryAxis.labels.boxAnchor = 'n' lc.valueAxis.valueMin = 0 lc.valueAxis.valueMax = 60 lc.valueAxis.valueStep = 15 drawing.add(lc) return drawing
def draw_bar_chart(pdf_text, page_height): '''Currently generates a dummy graph. Next, need to pass in data that shall be the reactors temp throughout the sequence. ''' pdf_text.showPage() drawing = Drawing(400, 200) data = [ (13, 5, 20, 22, 37, 45, 19, 4), (14, 6, 21, 23, 38, 46, 20, 5) ] bc = VerticalBarChart() bc.x = 50 bc.y = 50 bc.height = 125 bc.width = 300 bc.data = data bc.strokeColor = colors.black bc.valueAxis.valueMin = 0 bc.valueAxis.valueMax = 50 bc.valueAxis.valueStep = 10 bc.categoryAxis.labels.boxAnchor = 'ne' bc.categoryAxis.labels.dx = 8 bc.categoryAxis.labels.dy = -2 bc.categoryAxis.labels.angle = 30 bc.categoryAxis.categoryNames = ['Jan-99','Feb-99','Mar-99','Apr-99','May-99','Jun-99','Jul-99','Aug-99'] drawing.add(bc) renderPDF.draw(drawing, pdf_text, inch, inch) return page_height
def test(outDir='out-svg'): # print all drawings and their doc strings from the test # file if not os.path.isdir(outDir): os.mkdir(outDir) #grab all drawings from the test module from reportlab.graphics import testshapes drawings = [] for funcname in dir(testshapes): #if funcname[0:11] == 'getDrawing2': # print 'hacked to only show drawing 2' if funcname[0:10] == 'getDrawing': drawing = eval('testshapes.' + funcname + '()') docstring = eval('testshapes.' + funcname + '.__doc__') drawings.append((drawing, docstring)) i = 0 for (d, docstring) in drawings: filename = os.path.join(outDir,'renderSVG_%d.svg' % i) drawToFile(d, filename) i += 1 from reportlab.graphics.testshapes import getDrawing01 d = getDrawing01() drawToFile(d, os.path.join(outDir,"test.svg")) from reportlab.lib.corp import RL_CorpLogo from reportlab.graphics.shapes import Drawing rl = RL_CorpLogo() d = Drawing(rl.width,rl.height) d.add(rl) drawToFile(d, os.path.join(outDir,"corplogo.svg"))
def barChart(daten,Versuch,Phaenomene,path=None,vMin=1,vMax=6): """ Plots data to a Drawing and returns the Drawing """ #Festlegen der Gesamtgröße in Pixel d = Drawing(500,160) #Daten für das Diagramm #daten = [(10,6,8)] #Anlegen des Diagramms diagramm = HorizontalBarChart() #Positionierung und Größe des Diagramms diagramm.x = 10 diagramm.y = 30 diagramm.height = 100 diagramm.width = 400 #Hinzufügen der Daten #diagramm.reversePlotOrder = 1 diagramm.data = daten #Y-Achse (in ReportLab „valueAxis“) formatieren diagramm.valueAxis.valueMin = vMin diagramm.valueAxis.valueMax = vMax diagramm.valueAxis.valueStep = 1 #X-Achse (in ReportLab „categoryAxis“) formatieren diagramm.categoryAxis.categoryNames = Phaenomene #Diagramm zeichnen d.add(diagramm) if not path == None: Versuch = path + Versuch renderPM.drawToFile(d, Versuch + ".png", 'PNG') #d = Paragraph(d, centered) d.scale(0.8,0.8) return d
def conversion_chart(data, labels): """Create chart that can be drawn as a gif with given data/labels""" drawing = Drawing(500, 400) bc = VerticalBarChart() bc.x = 80 bc.y = 80 bc.height = 290 bc.width = 390 bc.data = data bc.valueAxis.valueMin = 0 bc.valueAxis.valueMax = 100 bc.valueAxis.valueStep = 10 bc.valueAxis.labelTextFormat = '%2.2f' bc.barLabels.fontSize = 15 bc.barLabelFormat = '%2.2f' bc.barLabels.boxAnchor = 's' bc.categoryAxis.labels.boxAnchor = 'ne' bc.categoryAxis.labels.dx = 8 bc.categoryAxis.labels.dy = 2 bc.categoryAxis.labels.angle = 30 bc.categoryAxis.categoryNames = labels drawing.add(bc) return drawing
def createBarCodes(path, barcode_value): from reportlab.graphics.barcode import eanbc from reportlab.graphics.shapes import Drawing from reportlab.pdfgen import canvas from reportlab.graphics import renderPDF from reportlab.lib.units import cm, mm from reportlab.lib.styles import getSampleStyleSheet from reportlab.platypus.para import Paragraph # draw the eanbc13 code barcode_eanbc13 = eanbc.Ean13BarcodeWidget(barcode_value) bounds = barcode_eanbc13.getBounds() barcode_eanbc13.barHeight = 19*mm width = bounds[2] - bounds[0] height = bounds[3] - bounds[1] d = Drawing() d.add(barcode_eanbc13) c = canvas.Canvas(path, pagesize=(43*mm, 25*mm)) # print width, height text = "%s.%s" % (150, '00') p = Paragraph(text, getSampleStyleSheet()["Normal"]) p.wrapOn(c, 43*mm, 5*mm) p.drawOn(c, 16*mm, 20*mm) renderPDF.draw(d, c, 3*mm, 1*mm) c.save()
def print_chunks_chart(self): nChunks = len(self.filechunks) d = Drawing(400, 140) traffic_MB = [n/(1024*1024) for n in self.traffic] data = [traffic_MB] bc = VerticalBarChart() ## bc.x = 0 ## bc.y = 10 bc.height = 100 bc.width = 370 bc.data = data bc.categoryAxis.tickUp = 0.5 bc.categoryAxis.tickDown = 1.5 bc.categoryAxis.categoryNames = [] for n in range(nChunks): if n%5 == 0: bc.categoryAxis.categoryNames.append( str(n) ) else: bc.categoryAxis.categoryNames.append('') bc.bars.strokeWidth = 0.3 bc.valueAxis.labels.fontSize = 6 bc.categoryAxis.labels.fontSize = 6 bc.bars[0].fillColor = colors.lightblue bc.valueAxis.valueMin = 0 d.add(bc) drawing = GraphicsDrawing(d, 'Traffic per chunk in MB') self.story.append(drawing) self.story.append(Spacer(0.01,1.0*cm))
def draw_qr_sdaps_info(canvas, survey, page): # The page number is one based here already # The survey_id is a 32bit number, which means we need # 10 decimal digits to encode it, then we need to encode the # the page with at least 3 digits(just in case someone is insane enough # to have a questionnaire with more than 99 pages. # So use 10+4 digits value = "%010d%04d" % (survey.survey_id, page) y = survey.defs.paper_height - defs.corner_mark_bottom x = survey.defs.paper_width - defs.corner_mark_right qr_code = qr.QrCodeWidget(value, barLevel='H') bounds = qr_code.getBounds() width = bounds[2] - bounds[0] height = bounds[3] - bounds[1] # Squeeze into the space between corner mark and content size = defs.bottom_page_margin - defs.corner_mark_bottom code_y = y code_x = x - size d = Drawing(size*mm, size*mm, transform=[float(size*mm)/width,0,0,-float(size*mm)/height,0,0]) d.add(qr_code) renderPDF.draw(d, canvas, code_x*mm, code_y*mm)
def __add_graph(self): drawing = Drawing(200, 100) data = list() labels = list() self.c.drawString(370, 730, 'Distribucion en pesos'.encode('utf-8')) for acc in self.accounts: balance = acc.balance if acc.currency == 'USD': balance = balance * self.dolar data.append(balance) labels.append(acc.name) pie = Pie() pie.x = 280 pie.y = 630 pie.height = 100 pie.width = 100 pie.data = data pie.labels = labels pie.simpleLabels = 1 pie.slices.strokeWidth = 1 pie.slices.strokeColor = black pie.slices.label_visible = 0 legend = Legend() legend.x = 400 legend.y = 680 legend.dx = 8 legend.dy = 8 legend.fontName = 'Helvetica' legend.fontSize = 7 legend.boxAnchor = 'w' legend.columnMaximum = 10 legend.strokeWidth = 1 legend.strokeColor = black legend.deltax = 75 legend.deltay = 10 legend.autoXPadding = 5 legend.yGap = 0 legend.dxTextSpace = 5 legend.alignment = 'right' legend.dividerLines = 1|2|4 legend.dividerOffsY = 4.5 legend.subCols.rpad = 30 n = len(pie.data) self.__setItems(n,pie.slices, 'fillColor',self.pdf_chart_colors) legend.colorNamePairs = [(pie.slices[i].fillColor, (pie.labels[i][0:20],'$%0.2f' % pie.data[i])) for i in xrange(n)] drawing.add(pie) drawing.add(legend) x, y = 0, 0 renderPDF.draw(drawing, self.c, x, y, showBoundary=False)
def sample2(): "A line plot with non-equidistant points in x-axis." drawing = Drawing(400, 200) data = [ ( ("25/11/1991", 1), ("30/11/1991", 1.000933333), ("31/12/1991", 1.0062), ("31/01/1992", 1.0112), ("29/02/1992", 1.0158), ("31/03/1992", 1.020733333), ("30/04/1992", 1.026133333), ("31/05/1992", 1.030266667), ("30/06/1992", 1.034466667), ("31/07/1992", 1.038733333), ("31/08/1992", 1.0422), ("30/09/1992", 1.045533333), ("31/10/1992", 1.049866667), ("30/11/1992", 1.054733333), ("31/12/1992", 1.061), ) ] data[0] = preprocessData(data[0]) lp = LinePlot() lp.x = 50 lp.y = 50 lp.height = 125 lp.width = 300 lp.data = data lp.joinedLines = 1 lp.lines.symbol = makeMarker("FilledDiamond") lp.strokeColor = colors.black start = mktime(mkTimeTuple("25/11/1991")) t0 = mktime(mkTimeTuple("30/11/1991")) t1 = mktime(mkTimeTuple("31/12/1991")) t2 = mktime(mkTimeTuple("31/03/1992")) t3 = mktime(mkTimeTuple("30/06/1992")) t4 = mktime(mkTimeTuple("30/09/1992")) end = mktime(mkTimeTuple("31/12/1992")) lp.xValueAxis.valueMin = start lp.xValueAxis.valueMax = end lp.xValueAxis.valueSteps = [start, t0, t1, t2, t3, t4, end] lp.xValueAxis.labelTextFormat = seconds2str lp.xValueAxis.labels[1].dy = -20 lp.xValueAxis.labels[2].dy = -35 lp.yValueAxis.labelTextFormat = "%4.2f" lp.yValueAxis.valueMin = 100 lp.yValueAxis.valueMax = 110 lp.yValueAxis.valueStep = 2 drawing.add(lp) return drawing
def demo(self,drawing=None): from reportlab.lib import colors if not drawing: tx,ty=self._getDrawingDimensions() drawing = Drawing(tx,ty) drawing.add(self.draw()) return drawing
def sample1a(): "A line plot with non-equidistant points in x-axis." drawing = Drawing(400, 200) data = [((1, 1), (2, 2), (2.5, 1), (3, 3), (4, 5)), ((1, 2), (2, 3), (2.5, 2), (3.5, 5), (4, 6))] lp = LinePlot() lp.x = 50 lp.y = 50 lp.height = 125 lp.width = 300 lp.data = data lp.joinedLines = 1 lp.strokeColor = colors.black lp.lines.symbol = makeMarker("UK_Flag") lp.lines[0].strokeWidth = 2 lp.lines[1].strokeWidth = 4 lp.xValueAxis.valueMin = 0 lp.xValueAxis.valueMax = 5 lp.xValueAxis.valueStep = 1 lp.yValueAxis.valueMin = 0 lp.yValueAxis.valueMax = 7 lp.yValueAxis.valueStep = 1 drawing.add(lp) return drawing
def demo(self): """Shows basic use of a line chart.""" drawing = Drawing(400, 200) data = [((1, 1), (2, 2), (2.5, 1), (3, 3), (4, 5)), ((1, 2), (2, 3), (2.5, 2), (3.5, 5), (4, 6))] lp = LinePlot() lp.x = 50 lp.y = 50 lp.height = 125 lp.width = 300 lp.data = data lp.joinedLines = 1 lp.lineLabelFormat = "%2.0f" lp.strokeColor = colors.black lp.lines[0].strokeColor = colors.red lp.lines[0].symbol = makeMarker("FilledCircle") lp.lines[1].strokeColor = colors.blue lp.lines[1].symbol = makeMarker("FilledDiamond") lp.xValueAxis.valueMin = 0 lp.xValueAxis.valueMax = 5 lp.xValueAxis.valueStep = 1 lp.yValueAxis.valueMin = 0 lp.yValueAxis.valueMax = 7 lp.yValueAxis.valueStep = 1 drawing.add(lp) return drawing
def draw_qr_global_id(canvas, survey): if survey.global_id is None: raise AssertionError # Only allow ascii value = survey.global_id.encode('ascii') y = survey.defs.paper_height - defs.corner_mark_bottom x = (survey.defs.paper_width - defs.corner_mark_right + defs.corner_mark_left) / 2 qr_code = qr.QrCodeWidget(value, barLevel='H') bounds = qr_code.getBounds() width = bounds[2] - bounds[0] height = bounds[3] - bounds[1] # Squeeze into the space between corner mark and content size = defs.bottom_page_margin - defs.corner_mark_bottom code_y = y code_x = x - size / 2.0 d = Drawing(size*mm, size*mm, transform=[float(size*mm)/width,0,0,-float(size*mm)/height,0,0]) d.add(qr_code) renderPDF.draw(d, canvas, code_x*mm, code_y*mm)
def getCaptcha(n=5,fontName='Courier',fontSize=14,text=None,fillColor=None): '''return n random chars in a string and in a byte string structured as a GIF image''' from reportlab.graphics.shapes import Drawing, Group, String, \ rotate, skewX, skewY, mmult, translate, Rect if not text: from random import randint, uniform text=''.join([_allowed[randint(0,_mx)] for i in range(n)]) else: uniform = lambda l,h: 0.5*(l+h) n = len(text) baseline = 0 x = 0 G0 = Group() for c in text: x += 1 A = translate(x,uniform(baseline-5,baseline+5)) A = mmult(A,rotate(uniform(-15,15))) A = mmult(A,skewX(uniform(-8,8))) A = mmult(A,skewY(uniform(-8,8))) G = Group(transform=A) G.add(String(0,0,c,fontname=fontName,fontSize=fontSize)) G0.add(G) x0,y0,x1,y1 = G0.getBounds() x = 1+x1 G0.transform=translate(2-x0,2-y0) W = 4+x1-x0 H = 4+y1-y0 D = Drawing(W,H) if fillColor: from reportlab.lib.colors import toColor D.add(Rect(0,0,W,H, fillColor = toColor(fillColor),strokeColor=None)) D.add(G0) return text, D.asString('gif')
def draw_time_repartition(mandate): drawing = Drawing(width=180*mm, height=120*mm) pdf_chart_colors = [HexColor("#fa9d00"), HexColor("#006884"), HexColor("#00909e"), HexColor("#ffd08d"), ] pie = Pie() pie.x = 60*mm pie.y = 35*mm pie.width = 60*mm pie.height = 60*mm pie.slices.strokeWidth = 0.5 pie.slices.fontName = 'Helvetica' pie.slices.fontSize = 8 pie.data = [] pie.labels = [] titles = [] add_data_and_titles_to_pie(pie, titles, mandate.research_percent, 'research_percent') add_data_and_titles_to_pie(pie, titles, mandate.tutoring_percent, 'tutoring_percent') add_data_and_titles_to_pie(pie, titles, mandate.service_activities_percent, 'service_activities_percent') add_data_and_titles_to_pie(pie, titles, mandate.formation_activities_percent, 'formation_activities_percent') if len(pie.data) > 0: drawing.add(pie) add_legend_to_pie(drawing) n = len(pie.data) set_items(n, pie.slices, 'fillColor', pdf_chart_colors) drawing.legend.colorNamePairs = \ [(pie.slices[i].fillColor, (titles[i], '%0.f' % pie.data[i] + '%')) for i in range(n)] return drawing
def makeDrawing0(self): "Generate a RLG drawing with some uncommented grid samples." D = Drawing(450, 650) d = 80 s = 50 for row in range(10): y = 530 - row * d if row == 0: for col in range(4): x = 20 + col * d g = Grid() g.x = x g.y = y g.width = s g.height = s g.useRects = 0 g.useLines = 1 if col == 0: pass elif col == 1: g.delta0 = 10 elif col == 2: g.orientation = 'horizontal' elif col == 3: g.deltaSteps = [5, 10, 20, 30] g.demo() D.add(g) elif row == 1: for col in range(4): x = 20 + col * d g = Grid() g.y = y g.x = x g.width = s g.height = s if col == 0: pass elif col == 1: g.delta0 = 10 elif col == 2: g.orientation = 'horizontal' elif col == 3: g.deltaSteps = [5, 10, 20, 30] g.useRects = 1 g.useLines = 0 g.demo() D.add(g) elif row == 2: for col in range(3): x = 20 + col * d g = Grid() g.x = x g.y = y g.width = s g.height = s g.useLines = 1 g.useRects = 1 if col == 0: pass elif col == 1: g.delta0 = 10 elif col == 2: g.orientation = 'horizontal' g.demo() D.add(g) elif row == 3: for col in range(3): x = 20 + col * d sr = ShadedRect() sr.x = x sr.y = y sr.width = s sr.height = s sr.fillColorStart = colors.Color(0, 0, 0) sr.fillColorEnd = colors.Color(1, 1, 1) if col == 0: sr.numShades = 5 elif col == 1: sr.numShades = 2 elif col == 2: sr.numShades = 1 sr.demo() D.add(sr) elif row == 4: for col in range(3): x = 20 + col * d sr = ShadedRect() sr.x = x sr.y = y sr.width = s sr.height = s sr.fillColorStart = colors.red sr.fillColorEnd = colors.blue sr.orientation = 'horizontal' if col == 0: sr.numShades = 10 elif col == 1: sr.numShades = 20 elif col == 2: sr.numShades = 50 sr.demo() D.add(sr) elif row == 5: for col in range(3): x = 20 + col * d sr = ShadedRect() sr.x = x sr.y = y sr.width = s sr.height = s sr.fillColorStart = colors.white sr.fillColorEnd = colors.green sr.orientation = 'horizontal' if col == 0: sr.numShades = 10 elif col == 1: sr.numShades = 20 sr.orientation = 'vertical' elif col == 2: sr.numShades = 50 sr.demo() D.add(sr) elif row == 6: for col in range(3): x = 20 + col * d sr = ShadedRect() sr.x = x sr.y = y + s sr.width = s sr.height = -s sr.fillColorStart = colors.white sr.fillColorEnd = colors.green sr.orientation = 'horizontal' if col == 0: sr.numShades = 10 elif col == 1: sr.numShades = 20 sr.orientation = 'vertical' elif col == 2: sr.numShades = 50 sr.demo() D.add(sr) return D
assert len(data) == pixels, len(data) assert shape == im.getbbox()[2:] data = np.array(data).reshape(shape, order="F") assert shape == data.shape pixels = np.product(shape) print("Have %i base pairs, and %i pixels" % (len(seq), pixels)) assert pixels <= len(seq) assert 0 <= data.min() <= data.max() <= 255 # Open PDF width, height = page_size = [x * scale for x in shape] c = canvas.Canvas(pdf_file, page_size) c.setTitle(main_caption) d = Drawing(*page_size) base = 0 for row in range(shape[1]): for col in range(shape[0]): color = colors.CMYKColor(black=(255 - data[col, row]) / 255.0) # From top left? s = String((col + 0.5) * scale, (shape[1] - row) * scale, seq[base], fillColor=color, fontSize=4, textAnchor="middle") d.add(s) base += 1 renderPDF.draw(d, c, 0, 0) c.showPage() c.save()
from fontTools.ttLib import TTFont from reportlab.lib import colors path = sys.argv[1] glyphName = sys.argv[2] if (len(sys.argv) > 3): imageFile = sys.argv[3] else: imageFile = "%s.png" % glyphName font = TTFont(path) # it would work just as well with fontTools.t1Lib.T1Font gs = font.getGlyphSet() pen = ReportLabPen(gs, Path(fillColor=colors.red, strokeWidth=5)) g = gs[glyphName] g.draw(pen) w, h = g.width, 1000 from reportlab.graphics import renderPM from reportlab.graphics.shapes import Group, Drawing # Everything is wrapped in a group to allow transformations. g = Group(pen.path) g.translate(0, 200) g.scale(0.3, 0.3) d = Drawing(w, h) d.add(g) renderPM.drawToFile(d, imageFile, fmt="PNG")
class Renderer: LINK = '{http://www.w3.org/1999/xlink}href' SVG_DEFS = '{http://www.w3.org/2000/svg}defs' SVG_ROOT = '{http://www.w3.org/2000/svg}svg' SVG_A = '{http://www.w3.org/2000/svg}a' SVG_G = '{http://www.w3.org/2000/svg}g' SVG_SYMBOL = '{http://www.w3.org/2000/svg}symbol' SVG_USE = '{http://www.w3.org/2000/svg}use' SVG_RECT = '{http://www.w3.org/2000/svg}rect' SVG_CIRCLE = '{http://www.w3.org/2000/svg}circle' SVG_ELLIPSE = '{http://www.w3.org/2000/svg}ellipse' SVG_LINE = '{http://www.w3.org/2000/svg}line' SVG_POLYLINE = '{http://www.w3.org/2000/svg}polyline' SVG_POLYGON = '{http://www.w3.org/2000/svg}polygon' SVG_PATH = '{http://www.w3.org/2000/svg}path' SVG_TEXT = '{http://www.w3.org/2000/svg}text' SVG_TSPAN = '{http://www.w3.org/2000/svg}tspan' SVG_IMAGE = '{http://www.w3.org/2000/svg}image' SVG_NODES = frozenset((SVG_ROOT, SVG_A, SVG_G, SVG_SYMBOL, SVG_USE, SVG_RECT, SVG_CIRCLE, SVG_ELLIPSE, SVG_LINE, SVG_POLYLINE, SVG_POLYGON, SVG_PATH, SVG_TEXT, SVG_IMAGE)) def __init__(self, filename): self.filename = filename self.level = 0 self.styles = {} self.mainGroup = Group() self.drawing = None self.root = None def render(self, node, parent = None): if parent == None: parent = self.mainGroup # ignore if display = none display = node.get('display') if display == "none": return if node.tag == self.SVG_ROOT: self.level += 1 if not self.drawing is None: raise SVGError('drawing already created!') self.root = node # default styles style = { 'color':'black', 'fill':'black', 'stroke':'none', 'font-family':'Helvetica', 'font-size':'12' } self.styles[self.level] = style # iterate children for child in node: self.render(child, self.mainGroup) # create drawing width = node.get('width', '100%') height = node.get('height', '100%') if node.get("viewBox"): try: minx, miny, width, height = node.get("viewBox").split() except ValueError: raise SVGError("viewBox values not valid") else: minx, miny = 0, 0 if width.endswith('%') and height.endswith('%'): # handle relative size wscale = parseLength(width) / 100. hscale = parseLength(height) / 100. xL,yL,xH,yH = self.mainGroup.getBounds() self.drawing = Drawing(xH*wscale + xL, yH*hscale + yL) else: self.drawing = Drawing(parseLength(width), parseLength(height)) height = self.drawing.height self.mainGroup.scale(1, -1) self.mainGroup.translate(-float(minx), -height-float(miny)) self.drawing.add(self.mainGroup) self.level -= 1 return self.drawing elif node.tag in (self.SVG_G, self.SVG_A, self.SVG_SYMBOL): self.level += 1 # set this levels style style = self.styles[self.level - 1].copy() style = self.nodeStyle(node, style) self.styles[self.level] = style group = Group() # iterate children for child in node: self.render(child, group) parent.add(group) transforms = node.get('transform') if transforms: for op in parseTransform.iterparse(transforms): self.applyTransformOnGroup(group, op) self.level -= 1 elif node.tag == self.SVG_USE: self.level += 1 # set this levels style style = self.styles[self.level - 1].copy() style = self.nodeStyle(node, style) self.styles[self.level] = style group = Group() # link id link_id = node.get(self.LINK).lstrip('#') # find linked node in defs section target = None for defs in self.root.getiterator(self.SVG_DEFS): for element in defs: if element.get('id') == link_id: target = element break if target is None: raise SVGError("Could not find use node '%s'" % link_id) self.render(target, group) parent.add(group) # apply transform transforms = node.get('transform') if transforms: for op in parseTransform.iterparse(transforms): self.applyTransformOnGroup(group, op) # apply 'x' and 'y' attribute as translation of defs object if node.get('x') or node.get('y'): dx = parseLength(node.get('x','0')) dy = parseLength(node.get('y','0')) self.applyTransformOnGroup(group, ('translate', (dx,dy))) self.level -= 1 elif node.tag == self.SVG_LINE: # get coordinates x1 = parseLength(node.get('x1', '0')) y1 = parseLength(node.get('y1', '0')) x2 = parseLength(node.get('x2', '0')) y2 = parseLength(node.get('y2', '0')) shape = Line(x1, y1, x2, y2) self.addShape(parent, node, shape) elif node.tag == self.SVG_RECT: # get coordinates x = parseLength(node.get('x', '0')) y = parseLength(node.get('y', '0')) width = parseLength(node.get('width')) height = parseLength(node.get('height')) rx = parseLength(node.get('rx', '0')) ry = parseLength(node.get('ry', '0')) shape = Rect(x, y, width, height, rx=rx, ry=ry) self.addShape(parent, node, shape) elif node.tag == self.SVG_CIRCLE: cx = parseLength(node.get('cx', '0')) cy = parseLength(node.get('cy', '0')) r = parseLength(node.get('r')) if r > 0.: shape = Circle(cx, cy, r) self.addShape(parent, node, shape) elif node.tag == self.SVG_ELLIPSE: cx = parseLength(node.get('cx', '0')) cy = parseLength(node.get('cy', '0')) rx = parseLength(node.get('rx')) ry = parseLength(node.get('ry')) if rx > 0. and ry > 0.: shape = Ellipse(cx, cy, rx, ry) self.addShape(parent, node, shape) elif node.tag == self.SVG_POLYLINE: # convert points points = node.get('points').strip() if len(points) == 0: return points = map(parseLength, re.split('[ ,]+', points)) # Need to use two shapes, because standard RLG polylines # do not support filling... group = Group() shape = Polygon(points) self.applyStyleToShape(shape, node) shape.strokeColor = None group.add(shape) shape = PolyLine(points) self.applyStyleToShape(shape, node) group.add(shape) self.addShape(parent, node, group) elif node.tag == self.SVG_POLYGON: # convert points points = node.get('points').strip() if len(points) == 0: return points = list(map(parseLength, re.split('[ ,]+', points))) shape = Polygon(points) self.addShape(parent, node, shape) elif node.tag == self.SVG_IMAGE: x = parseLength(node.get('x', '0')) y = parseLength(node.get('y', '0')) width = parseLength(node.get('width', '0')) height = parseLength(node.get('height', '0')) # link id link_id = node.get(self.LINK) filename = os.path.join(os.path.dirname(self.filename), link_id) shape = Image(x, y, width, height, filename) self.addShape(parent, node, shape) elif node.tag == self.SVG_TEXT: # Todo: # - rotation not handled # - baseshift not handled # - embedded span node not handled # def parsePos(node, subnode, name, default = '0'): values = subnode.get(name) if values is None: if not node is None: values = node.get(name, default) else: values = default return map(parseLength, values.split()) def getPos(values, i, default = None): if i >= len(values): if default is None: return values[-1] else: return default else: return values[i] def handleText(node, subnode, text): # get position variables xs = parsePos(node, subnode, 'x') dxs = parsePos(node, subnode, 'dx') ys = parsePos(node, subnode,'y') dys = parsePos(node, subnode,'dy') if sum(map(len, (xs,ys,dxs,dys))) == 4: # single value shape = String(xs[0] + dxs[0], -ys[0] - dys[0], text) self.applyStyleToShape(shape, subnode) group.add(shape) else: # multiple values for i,c in enumerate(text): x = getPos(xs, i) dx = getPos(dxs, i, 0) y = getPos(ys, i) dy = getPos(dys, i, 0) shape = String(x + dx, -y -dy, c) self.applyStyleToShape(shape, subnode) group.add(shape) if node.text and node.text.strip(): group = Group() handleText(None, node, node.text.strip()) group.scale(1, -1) self.addShape(parent, node, group) if len(node) > 0: group = Group() self.level += 1 # set this levels style style = self.styles[self.level - 1].copy() nodestylestyle = self.nodeStyle(node, style) self.styles[self.level] = nodestylestyle for subnode in node: if subnode.tag == self.SVG_TSPAN: handleText(node, subnode, subnode.text.strip()) self.level -= 1 group.scale(1, -1) self.addShape(parent, node, group) elif node.tag == self.SVG_PATH: def convertQuadratic(Q0, Q1, Q2): C1 = (Q0[0] + 2./3*(Q1[0] - Q0[0]), Q0[1] + 2./3*(Q1[1] - Q0[1])) C2 = (C1[0] + 1./3*(Q2[0] - Q0[0]), C1[1] + 1./3*(Q2[1] - Q0[1])) C3 = Q2 return C1[0], C1[1], C2[0], C2[1], C3[0], C3[1] def prevCtrl(lastOp, lastArgs, currentX, currentY): # fetch last controll point if lastOp in 'CScsQqTt': x, y = lastArgs[-2] # mirror about current point return currentX + (currentX-x), currentY + (currentY-y) else: # defaults to current point return currentX, currentY # store sub paths in 'paths' list shape = Path() # keep track of current point and path start point startX, startY = 0.,0. currentX, currentY = 0.,0. # keep track of last operation lastOp = None lastArgs = None # avoid empty path data data = node.get('d') if data is None or len(data) == 0: return for op, args in parsePath.iterparse(data): if op == 'z' or op == 'Z': # close path or subpath shape.closePath() # next sub path starts at begining of current path currentX, currentY = startX, startY elif op == 'M': # moveto absolute if not lastOp is None and lastOp not in ('z', 'Z'): # close sub path shape.closePath() x, y = args[0] shape.moveTo(x, y) startX, startY = x, y # multiple moveto arge result in line for x, y in args[1:]: shape.lineTo(x, y) currentX, currentY = x, y elif op == 'm': if not lastOp is None and lastOp not in ('z', 'Z'): # close sub path shape.closePath() # moveto relative rx, ry = args[0] x, y = currentX + rx, currentY + ry shape.moveTo(x, y) startX, startY = x, y currentX, currentY = x, y # multiple moveto arge result in line for rx, ry in args[1:]: x, y = currentX + rx, currentY + ry shape.lineTo(x, y) currentX, currentY = x, y elif op == 'L': # lineto absolute for x,y in args: shape.lineTo(x, y) currentX, currentY = x, y elif op == 'l': # lineto relative for rx,ry in args: x, y = currentX + rx, currentY + ry shape.lineTo(x, y) currentX, currentY = x, y elif op == 'V': # vertical line absolute for y in args: shape.lineTo(currentX, y) currentY = y elif op == 'v': # vertical line relative for ry in args: y = currentY + ry shape.lineTo(currentX, y) currentY = y elif op == 'H': # horisontal line absolute for x in args: shape.lineTo(x, currentY) currentX = x elif op == 'h': # horisontal line relative for rx in args: x = currentX + rx shape.lineTo(x, currentY) currentX = x elif op == 'C': # cubic bezier absolute for i in range(len(args)//3): x1, y1 = args[i*3 + 0] x2, y2 = args[i*3 + 1] x3, y3 = args[i*3 + 2] shape.curveTo(x1, y1, x2, y2, x3, y3) currentX, currentY = x3, y3 elif op == 'c': # cubic bezier relative for i in range(len(args)//3): x1, y1 = args[i*3 + 0] x1, y1 = x1 + currentX, y1 + currentY x2, y2 = args[i*3 + 1] x2, y2 = x2 + currentX, y2 + currentY x3, y3 = args[i*3 + 2] x3, y3 = x3 + currentX, y3 + currentY shape.curveTo(x1, y1, x2, y2, x3, y3) currentX, currentY = x3, y3 lastOp = op lastArgs = (x1, y1), (x2, y2), (x3, y3) continue elif op == 'S': # shorthand cubic bezier absolute for i in range(len(args)//2): x1, y1 = prevCtrl(lastOp, lastArgs, currentX, currentY) x2, y2 = args[i*2 + 0] x3, y3 = args[i*2 + 1] shape.curveTo(x1, y1, x2, y2, x3, y3) lastOp = op lastArgs = (x2, y2), (x3, y3) currentX, currentY = x3, y3 continue elif op == 's': # shorthand cubic bezier relative for i in range(len(args)//2): x1, y1 = prevCtrl(lastOp, lastArgs, currentX, currentY) x2, y2 = args[i*2 + 0] x2, y2 = x2 + currentX, y2 + currentY x3, y3 = args[i*2 + 1] x3, y3 = x3 + currentX, y3 + currentY shape.curveTo(x1, y1, x2, y2, x3, y3) currentX, currentY = x3, y3 lastOp = op lastArgs = (x1, y1), (x2, y2), (x3, y3) continue elif op == 'Q': # quadratic bezier absolute for i in range(len(args)//2): x1, y1 = currentX, currentY x2, y2 = args[i*2 + 0] x3, y3 = args[i*2 + 1] ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3)) shape.curveTo(*ctrls) currentX, currentY = x3, y3 lastOp = op lastArgs = (x2, y2), (x3, y3) continue elif op == 'q': # quadratic bezier relative for i in range(len(args)//2): x1, y1 = currentX, currentY x2, y2 = args[i*2 + 0] x2, y2 = x2 + currentX, y2 + currentY x3, y3 = args[i*2 + 1] x3, y3 = x3 + currentX, y3 + currentY ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3)) shape.curveTo(*ctrls) currentX, currentY = x3, y3 lastOp = op lastArgs = (x2, y2), (x3, y3) continue elif op == 'T': # shorthand quadratic bezier absolute for i in range(len(args)): x1, y1 = currentX, currentY x2, y2 = prevCtrl(lastOp, lastArgs, currentX, currentY) x3, y3 = args[i] ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3)) shape.curveTo(*ctrls) currentX, currentY = x3, y3 lastOp = op lastArgs = (x2, y2), (x3, y3) continue elif op == 't': # shorthand quadratic bezier relative for i in range(len(args)): x1, y1 = currentX, currentY x2, y2 = prevCtrl(lastOp, lastArgs, currentX, currentY) x3, y3 = args[i] x3, y3 = x3 + currentX, y3 + currentY ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3)) shape.curveTo(*ctrls) currentX, currentY = x3, y3 lastOp = op lastArgs = (x2, y2), (x3, y3) continue elif op == 'A' or op == 'a': # elliptic arc missing continue lastOp = op lastArgs = args # check if fill applies to path fill = None if node.get('fill'): # inline style fill = node.get('fill') else: # try local style if node.get('style'): style = parseStyle.parse(node.get('style')) if 'fill' in style: fill = style['fill'] # try global style if fill is None: style = self.styles[self.level] if 'fill' in style: fill = style['fill'] else: fill = 'none' # hack because RLG has no "semi-closed" paths... if lastOp == 'z' or lastOp == 'Z' or fill == 'none': self.addShape(parent, node, shape) else: group = Group() strokeshape = shape.copy() self.addShape(group, node, strokeshape, fill = 'none') shape.closePath() self.addShape(group, node, shape, stroke = 'none') self.addShape(parent, node, group) def addShape(self, parent, node, shape, **kwargs): self.applyStyleToShape(shape, node, **kwargs) transform = node.get('transform') if transform: # transform can only be applied to a group if isinstance(node, Group): group = node else: group = Group() for op in parseTransform.iterparse(transform): self.applyTransformOnGroup(group, op) if not isinstance(node, Group): group.add(shape) parent.add(group) else: parent.add(shape) return shape def nodeStyle(self, node, style = None): if style is None: style = {} # update with local style if node.get('style'): localstyle = parseStyle.parse(node.get('style')) for name, value in six.iteritems(localstyle): style[name] = value # update with inline style for name in STYLE_NAMES: value = node.get(name) if value: style[name] = value return style def applyStyleToShape(self, shape, node, **kwargs): # fetch global styles for this level globalstyle = self.styles[self.level] # update with node style localstyle = self.nodeStyle(node) for name in STYLES: # avoid text styles if not a String subclass if not isinstance(shape, String) and name in STYLES_FONT: continue value = None if name in kwargs: value = kwargs[name] elif name in localstyle: value = localstyle[name] elif name in globalstyle: value = globalstyle[name] else: continue # handle 'currentColor' if value == 'currentColor': if 'color' in localstyle: value = localstyle['color'] elif 'color' in globalstyle: value = globalstyle['color'] # fetch shape attribute name and converter attrname, converter = STYLES[name] # Sett attribute of shape if hasattr(shape, attrname): try: setattr(shape, attrname, converter(value)) except SVGError: pass # defaults if isinstance(shape, String): if shape.fillColor is None: shape.fillColor = colors.black elif isinstance(shape, (Line, PolyLine)): if shape.strokeColor is None: shape.strokeColor = colors.black elif isinstance(shape, (Rect, Circle, Ellipse, Polygon)): if shape.fillColor is None and shape.strokeColor is None: shape.strokeColor = colors.black def applyTransformOnGroup(self, group, transform): op, args = transform if op == 'scale': group.scale(*args) elif op == 'translate': group.translate(*args) elif op == 'rotate': if len(args) == 2: angle, center = args if center: cx, cy = center group.translate(cx, cy) group.rotate(angle) group.translate(-cx, -cy) else: group.rotate(angle) elif op == "skewX": angle = args[0] group.skew(angle, 0) elif op == "skewY": angle = args[0] group.skew(0, angle) elif op == "matrix": group.transform = mmult(group.transform, args)
# Add labels to chart chart.barLabelFormat = '$%.2f' # Text to display on label - 2 decimal float chart.barLabels.nudge = 8 # Nudge labels upwards by 8px # ------- Create legend ------- legend = Legend() # Create the legend legend.boxAnchor = 'sw' # Set anchor to bottom-left legend.x = 50 # Shift legend right to bring in line with chart legend.y = 50 # Shift legend up by 50px legend.alignment = 'right' # Put labels to the right of color icons # Set legend colors legend.colorNamePairs = [(colors[i], '{} '.format(labels[i])) for i in range(len(colors))] # Add chart and legend to drawing d.add(chart) d.add(legend) # Export as test_img.png d.save(fnRoot='test_img', formats=['png']) #--------------------------------# # Opening an image from disk # #--------------------------------# # Though we use webbrowser module, it opens in whatever default app for the file type from webbrowser import open open('test_img.png')
def demo(self): D = Drawing(self.width, self.height) D.add(self) return D
def create_bar(self, data_list, label_x_axis, contain, y_label=None, x_label=None, bar_width=520, bar_height=100, draw_width=520, draw_height=200, user_color=None, fontName="Times-Roman", fontSize=6, x_angle=0, bar_space=0): d = Drawing(width=draw_width, height=draw_height) bar = VerticalBarChart() bar.width = bar_width bar.height = bar_height bar.y = bar.height - (bar_height / 4) bar.strokeColor = colors.black bar.barLabelFormat = '%s' bar.barLabels.nudge = 7 bar.barLabels.fontSize = fontSize ################# X AXIS PROPERTIES ################# bar.categoryAxis.labels.dx = 0 bar.categoryAxis.labels.angle = x_angle bar.categoryAxis.labels.boxAnchor = 'autox' bar.categoryAxis.labels.fontSize = fontSize bar.categoryAxis.labels.fontName = self.master_font bar.categoryAxis.strokeWidth = 0.25 bar.categoryAxis.tickDown = -(bar.height) bar.categoryAxis.categoryNames = label_x_axis labX = Label() labX.boxAnchor = 'ne' labX.dx = bar.width * 2.15 labX.dy = bar.height labX.fontName = fontName labX.fontSize = fontSize labX.setText(x_label) d.add(labX) ##################################################### ################# Y AXIS PROPERTIES ################# bar.valueAxis.forceZero = 1 bar.valueAxis.labels.fontSize = fontSize bar.valueAxis.labels.fontName = fontName bar.valueAxis.rangeRound = 'both' bar.valueAxis.valueMin = 0 bar.valueAxis.visibleGrid = 1 bar.valueAxis.visibleAxis = 1 bar.valueAxis.labels.dx = -10 labY = Label() labY.boxAnchor = 'autox' labY.dy = bar.y + (bar.height / 1.5) labY.dx = bar.x - 30 labY.angle = 90 labY.fontName = fontName labY.fontSize = fontSize labY.setText(y_label) d.add(labY) ##################################################### bar.barSpacing = bar_space # bar.groupSpacing = 3 bar.data = data_list if user_color != None: usage_color = user_color else: random_range = [randint(0, 100) for i in range(len(contain))] usage_color = map( lambda item: PCMYKColor(randint(0, item), randint(0, item), randint(0, item), randint(0, item)), random_range) for i in range(len(data_list)): bar.bars[i].name = contain[i].upper() bar.bars[i].fillColor = usage_color[i] legend = Legend() legend.alignment = 'right' legend.boxAnchor = 'sw' legend.dxTextSpace = 10 legend.fontSize = fontSize legend.fontName = fontName legend.subCols.minWidth = 55 legend.variColumn = 1 legend.deltay = 15 legend.x = bar.x legend.colorNamePairs = Auto(obj=bar) d.add(bar) d.add(legend) self.flowables.append(d)
def gen_bar_drawing(data, data_note, width=letter[0] * 0.8, height=letter[1] * 0.25): """ 函数功能:生成Drawing之用 :return: """ data_value = list(map(lambda x: x[1], data)) data_finale = [tuple(data_value)] drawing = Drawing(width=width, height=height) bc = VerticalBarChart() # bc.x = 50 # bc.y = 50 # bc.height = 125 bc.width = width bc.data = data_finale # bc.valueAxis.valueMin = 0 bc.barSpacing = 0 # bc.valueAxis.valueMax = 50 # bc.valueAxis.valueStep = 10 # bc.categoryAxis.style = 'stacked' bc.categoryAxis.labels.boxAnchor = 'ne' bc.categoryAxis.labels.dx = 8 bc.categoryAxis.labels.dy = -2 bc.categoryAxis.labels.angle = 30 barFillColors = [ colors.red, colors.green, colors.white, colors.blue, colors.yellow, colors.pink, colors.purple, colors.lightgreen, colors.darkblue, colors.lightyellow, colors.fidred, colors.greenyellow, colors.gray, colors.blueviolet, colors.lightgoldenrodyellow ] for i in range(len(data_finale)): bc.bars[i].name = data_note[i] # 最多只支持15种颜色,多出的设置为红色 if i < 15: bc.bars[i].fillColor = barFillColors[i] else: bc.bars[i].fillColor = colors.red # x_min = data[0][0] # x_max = data[-1][0] # bc.xValueAxis.valueMin = x_min # lp.xValueAxis.valueMax = x_max # step = int(((x_max - x_min) / (60 * 60 * 24)) / 15) + 1 # bc.categoryAxis.categoryNames = [str(Sec2Datetime(x))[0:10] for x in range(int(x_min), int(x_max), 60 * 60 * 24 * step)] drawing.add(bc) # 增加legend # add_legend(drawing, bc, pos_x=10, pos_y=-10) return drawing
def demo(self,drawing=None): if not drawing: tx,ty=self._getDrawingDimensions() drawing = Drawing(tx,ty) drawing.add(self.draw()) return drawing
def makeDrawing1(self): "Generate a RLG drawing with some uncommented grid samples." D = Drawing(450, 650) d = 80 s = 50 for row in range(2): y = 530 - row * d if row == 0: for col in range(4): x = 20 + col * d g = DoubleGrid() g.x = x g.y = y g.width = s g.height = s # This should be done implicitely... g.grid0.x = x g.grid0.y = y g.grid1.x = x g.grid1.y = y g.grid0.width = s g.grid0.height = s g.grid1.width = s g.grid1.height = s if col == 0: pass elif col == 1: g.grid0.delta0 = 10 elif col == 2: g.grid0.delta0 = 5 elif col == 3: g.grid0.deltaSteps = [5, 10, 20, 30] g.demo() D.add(g) elif row == 1: for col in range(4): x = 20 + col * d g = DoubleGrid() g.x = x g.y = y g.width = s g.height = s # This should be done implicitely... g.grid0.x = x g.grid0.y = y g.grid1.x = x g.grid1.y = y g.grid0.width = s g.grid0.height = s g.grid1.width = s g.grid1.height = s if col == 0: g.grid0.useRects = 0 g.grid0.useLines = 1 g.grid1.useRects = 0 g.grid1.useLines = 1 elif col == 1: g.grid0.useRects = 1 g.grid0.useLines = 1 g.grid1.useRects = 0 g.grid1.useLines = 1 elif col == 2: g.grid0.useRects = 1 g.grid0.useLines = 0 g.grid1.useRects = 0 g.grid1.useLines = 1 elif col == 3: g.grid0.useRects = 1 g.grid0.useLines = 0 g.grid1.useRects = 1 g.grid1.useLines = 0 g.demo() D.add(g) return D
>>> d = shapes.Drawing(200, 100) >>> f = widgetbase.Face() >>> f.skinColor = colors.yellow >>> f.mood = "sad" >>> d.add(f) >>> renderPDF.drawToFile(d, 'face.pdf', 'A Face') """) from reportlab.graphics import widgetbase d = Drawing(200, 120) f = widgetbase.Face() f.x = 50 f.y = 10 f.skinColor = colors.yellow f.mood = "sad" d.add(f) draw(d, 'A sample widget') disc(""" Let's see what properties it has available, using the $setProperties()$ method we have seen earlier: """) eg(""" >>> f.dumpProperties() eyeColor = Color(0.00,0.00,1.00) mood = sad size = 80 skinColor = Color(1.00,1.00,0.00) x = 10 y = 10
def gen_lp_drawing(data, data_note, width=letter[0] * 0.8, height=letter[1] * 0.25, time_axis='day', y_min_zero=False, line_width=1.5, marker_size=5): """ 函数功能:生成Drawing之用 :return: """ drawing = Drawing(width=width, height=height) lp = LinePlot() lp.height = height lp.width = width lp.data = data lp.joinedLines = 1 # 定义颜色集 barFillColors = [ colors.red, colors.green, colors.blue, colors.darkgoldenrod, colors.pink, colors.purple, colors.lightgreen, colors.darkblue, colors.lightyellow, colors.fidred, colors.greenyellow, colors.gray, colors.white, colors.blueviolet, colors.lightgoldenrodyellow ] for i in range(0, len(data)): lp.lines[i].name = data_note[i] lp.lines[i].symbol = makeMarker('FilledCircle', size=marker_size) lp.lines[i].strokeWidth = line_width lp.lines[i].strokeColor = barFillColors[i] # lp.lineLabelFormat = '%2.0f' # lp.strokeColor = colors.black x_min = data[0][0][0] x_max = data[0][-1][0] lp.xValueAxis.valueMin = x_min lp.xValueAxis.valueMax = x_max if time_axis == 'day': step = int(((x_max - x_min) / (60 * 60 * 24)) / 30) + 1 lp.xValueAxis.valueSteps = [ n for n in range(int(x_min), int(x_max), 60 * 60 * 24 * step) ] lp.xValueAxis.labelTextFormat = lambda x: str(Sec2Datetime(x)[0:10]) lp.xValueAxis.labels.angle = 90 lp.xValueAxis.labels.fontSize = 6 lp.xValueAxis.labels.dy = -18 if y_min_zero: lp.yValueAxis.valueMin = 0 # lp.yValueAxis.valueMax = 50 # lp.yValueAxis.valueSteps = [1, 2, 3, 5, 6] elif time_axis == 'quarter': step = int(((x_max - x_min) / 0.25) / 30) + 1 lp.xValueAxis.valueSteps = [ n for n in range(int(x_min), int(x_max), int(math.ceil(0.25 * step))) ] lp.xValueAxis.labelTextFormat = lambda x: convertValue2Quarter(x) lp.xValueAxis.labels.angle = 90 lp.xValueAxis.labels.fontSize = 6 lp.xValueAxis.labels.dy = -18 if y_min_zero: lp.yValueAxis.valueMin = 0 elif time_axis == 'year': lp.xValueAxis.valueSteps = [ n for n in range(int(x_min), int(x_max), 1) ] lp.xValueAxis.labelTextFormat = lambda x: str(x) lp.xValueAxis.labels.angle = 90 lp.xValueAxis.labels.fontSize = 6 lp.xValueAxis.labels.dy = -18 if y_min_zero: lp.yValueAxis.valueMin = 0 elif time_axis == 'month': lp.xValueAxis.valueSteps = list(map(lambda x: x[0], data[0])) lp.xValueAxis.labelTextFormat = lambda x: str(Sec2Datetime(x))[0:7] lp.xValueAxis.labels.angle = 90 lp.xValueAxis.labels.fontSize = 6 lp.xValueAxis.labels.dy = -18 if y_min_zero: lp.yValueAxis.valueMin = 0 drawing.add(lp) add_legend(draw_obj=drawing, chart=lp, pos_x=10, pos_y=-20) return drawing
def test(): "Make a conference event for day 1 of UP Python 2003" d = Drawing(400, 200) cal = EventCalendar() cal.x = 50 cal.y = 25 cal.data = [ # these might be better as objects instead of tuples, since I # predict a large number of "optionsl" variables to affect # formatting in future. #title, speaker, track id, day, start time (hrs), duration (hrs) # track ID is 1-based not zero-based! ('Keynote: Why design another programming language?', 'Guido van Rossum', None, 1, 9.0, 1.0), ('Siena Web Service Architecture', 'Marc-Andre Lemburg', 1, 1, 10.5, 1.5), ('Extreme Programming in Python', 'Chris Withers', 2, 1, 10.5, 1.5), ('Pattern Experiences in C++', 'Mark Radford', 3, 1, 10.5, 1.5), ('What is the Type of std::toupper()', 'Gabriel Dos Reis', 4, 1, 10.5, 1.5), ('Linguistic Variables: Clear Thinking with Fuzzy Logic ', 'Walter Banks', 5, 1, 10.5, 1.5), ('lunch, short presentations, vendor presentations', '', None, 1, 12.0, 2.0), ("CORBA? Isn't that obsolete", 'Duncan Grisby', 1, 1, 14.0, 1.5), ("Python Design Patterns", 'Duncan Booth', 2, 1, 14.0, 1.5), ("Inside Security Checks and Safe Exceptions", 'Brandon Bray', 3, 1, 14.0, 1.5), ("Studying at a Distance", 'Panel Discussion, Panel to include Alan Lenton & Francis Glassborow', 4, 1, 14.0, 1.5), ("Coding Standards - Given the ANSI C Standard why do I still need a coding Standard", 'Randy Marques', 5, 1, 14.0, 1.5), ("RESTful Python", 'Hamish Lawson', 1, 1, 16.0, 1.5), ("Parsing made easier - a radical old idea", 'Andrew Koenig', 2, 1, 16.0, 1.5), ("C++ & Multimethods", 'Julian Smith', 3, 1, 16.0, 1.5), ("C++ Threading", 'Kevlin Henney', 4, 1, 16.0, 1.5), ("The Organisation Strikes Back", 'Alan Griffiths & Sarah Lees', 5, 1, 16.0, 1.5), ('Birds of a Feather meeting', '', None, 1, 17.5, 2.0), ('Keynote: In the Spirit of C', 'Greg Colvin', None, 2, 9.0, 1.0), ('The Infinite Filing Cabinet - object storage in Python', 'Jacob Hallen', 1, 2, 10.5, 1.5), ('Introduction to Python and Jython for C++ and Java Programmers', 'Alex Martelli', 2, 2, 10.5, 1.5), ('Template metaprogramming in Haskell', 'Simon Peyton Jones', 3, 2, 10.5, 1.5), ('Plenty People Programming: C++ Programming in a Group, Workshop with a difference', 'Nico Josuttis', 4, 2, 10.5, 1.5), ('Design and Implementation of the Boost Graph Library', 'Jeremy Siek', 5, 2, 10.5, 1.5), ('lunch, short presentations, vendor presentations', '', None, 2, 12.0, 2.0), ("Building GUI Applications with PythonCard and PyCrust", 'Andy Todd', 1, 2, 14.0, 1.5), ("Integrating Python, C and C++", 'Duncan Booth', 2, 2, 14.0, 1.5), ("Secrets and Pitfalls of Templates", 'Nicolai Josuttis & David Vandevoorde', 3, 2, 14.0, 1.5), ("Being a Mentor", 'Panel Discussion, Panel to include Alan Lenton & Francis Glassborow', 4, 2, 14.0, 1.5), ("The Embedded C Extensions to C", 'Willem Wakker', 5, 2, 14.0, 1.5), ("Lightning Talks", 'Paul Brian', 1, 2, 16.0, 1.5), ("Scripting Java Applications with Jython", 'Anthony Eden', 2, 2, 16.0, 1.5), ("Metaprogramming and the Boost Metaprogramming Library", 'David Abrahams', 3, 2, 16.0, 1.5), ("A Common Vendor ABI for C++ -- GCC's why, what and not", 'Nathan Sidwell & Gabriel Dos Reis', 4, 2, 16.0, 1.5), ("The Timing and Cost of Choices", 'Hubert Matthews', 5, 2, 16.0, 1.5), ('Birds of a Feather meeting', '', None, 2, 17.5, 2.0), ('Keynote: The Cost of C & C++ Compatibility', 'Andy Koenig', None, 3, 9.0, 1.0), ('Prying Eyes: Generic Observer Implementations in C++', 'Andrei Alexandrescu', 1, 2, 10.5, 1.5), ('The Roadmap to Generative Programming With C++', 'Ulrich Eisenecker', 2, 2, 10.5, 1.5), ('Design Patterns in C++ and C# for the Common Language Runtime', 'Brandon Bray', 3, 2, 10.5, 1.5), ('Extreme Hour (XH): (workshop) - Jutta Eckstein and Nico Josuttis', 'Jutta Ecstein', 4, 2, 10.5, 1.5), ('The Lambda Library : Unnamed Functions for C++', 'Jaako Jarvi', 5, 2, 10.5, 1.5), ('lunch, short presentations, vendor presentations', '', None, 3, 12.0, 2.0), ('Reflective Metaprogramming', 'Daveed Vandevoorde', 1, 3, 14.0, 1.5), ('Advanced Template Issues and Solutions (double session)', 'Herb Sutter', 2, 3, 14.0, 3), ('Concurrent Programming in Java (double session)', 'Angelika Langer', 3, 3, 14.0, 3), ('What can MISRA-C (2nd Edition) do for us?', 'Chris Hills', 4, 3, 14.0, 1.5), ('C++ Metaprogramming Concepts and Results', 'Walter E Brown', 5, 3, 14.0, 1.5), ('Binding C++ to Python with the Boost Python Library', 'David Abrahams', 1, 3, 16.0, 1.5), ('Using Aspect Oriented Programming for Enterprise Application Integration', 'Arno Schmidmeier', 4, 3, 16.0, 1.5), ('Defective C++', 'Marc Paterno', 5, 3, 16.0, 1.5), ("Speakers' Banquet & Birds of a Feather meeting", '', None, 3, 17.5, 2.0), ('Keynote: The Internet, Software and Computers - A Report Card', 'Alan Lenton', None, 4, 9.0, 1.0), ('Multi-Platform Software Development; Lessons from the Boost libraries', 'Beman Dawes', 1, 5, 10.5, 1.5), ('The Stability of the C++ ABI', 'Steve Clamage', 2, 5, 10.5, 1.5), ('Generic Build Support - A Pragmatic Approach to the Software Build Process', 'Randy Marques', 3, 5, 10.5, 1.5), ('How to Handle Project Managers: a survival guide', 'Barb Byro', 4, 5, 10.5, 1.5), ('lunch, ACCU AGM', '', None, 5, 12.0, 2.0), ('Sauce: An OO recursive descent parser; its design and implementation.', 'Jon Jagger', 1, 5, 14.0, 1.5), ('GNIRTS ESAC REWOL - Bringing the UNIX filters to the C++ iostream library.', 'JC van Winkel', 2, 5, 14.0, 1.5), ('Pattern Writing: Live and Direct', 'Frank Buschmann & Kevlin Henney', 3, 5, 14.0, 3.0), ('The Future of Programming Languages - A Goldfish Bowl', 'Francis Glassborow and friends', 3, 5, 14.0, 1.5), ('Honey, I Shrunk the Threads: Compile-time checked multithreaded transactions in C++', 'Andrei Alexandrescu', 1, 5, 16.0, 1.5), ('Fun and Functionality with Functors', 'Lois Goldthwaite', 2, 5, 16.0, 1.5), ('Agile Enough?', 'Alan Griffiths', 4, 5, 16.0, 1.5), ("Conference Closure: A brief plenary session", '', None, 5, 17.5, 0.5), ] #return cal cal.day = 1 d.add(cal) for format in ['pdf']: #,'gif','png']: out = d.asString(format) open('eventcal.%s' % format, 'wb').write(out) print('saved eventcal.%s' % format)
def exec_command(self, spreadsheet_data, args): if len(args) < 2: print("You must insert output file name") return print("Generating PDF...") # creating doc template and setting up output sheet style doc = SimpleDocTemplate(args[1], pagesize=letter) pdfmetrics.registerFont(TTFont('Standard', 'src/font.ttf')) pdfmetrics.registerFont(TTFont('Bold', 'src/font-bold.ttf')) doc.leftMargin = 40 styles = getSampleStyleSheet() style_h1 = ParagraphStyle(name='Heading1', fontName='Bold', fontSize=14, leading=22, spaceAfter=2) style_h2 = ParagraphStyle(name='Heading2', fontName='Standard', fontSize=12, leading=22, spaceAfter=1) space = Spacer(1, 0.20 * inch) table_style = TableStyle([ ('FONT', (0, 0), (-1, -1), 'Standard'), ('ALIGN', (0, 0), (-2, 0), 'CENTER'), ('ALIGN', (0, 0), (0, -5), 'LEFT'), ('INNERGRID', (0, 0), (-1, -1), 0.50, colors.black), ('BOX', (0, 0), (-1, -1), 0.25, colors.black), ]) # collect information about room occupancy elements = [] # iterate over any room for room_key, room in spreadsheet_data.room_data.data.items(): print("Sala:", str(room.building_id) + ' - ' + str(room.name) + "\n") line = Drawing(520, 10) line.add(Line(0, 7, 520, 7)) elements.append(Paragraph( "Sala: " + str(room.building_id) + ' - ' + str(room.name), style_h1)) elements.append(line) # for any room check occupancy for any day for day in self.tools.days_of_week[0:5]: print(self.tools.days_of_week_label[day]) elements.append( Paragraph(self.tools.days_of_week_label[day], style_h2)) data_id = id( spreadsheet_data.full_time_first_semester_event_data) semester_data = spreadsheet_data.full_time_first_semester_event_data.data event_data = [self.table_header] # for any day check occupancy in any time block if data_id in room.referenced_by: for time_block in self.tools.time_blocks: result = self.get_room_event_by_day(day, time_block, room, data_id, semester_data) if len(result) == 0: result = [self.tools.time_blocks[time_block], '', '', '', ''] else: for item in result: event_data.append(item) if len(event_data) <= 1: event_data = self.get_empty_tab() # add new table do sheet table = Table(event_data, hAlign='LEFT') table.setStyle(table_style) elements.append(table) elements.append(KeepTogether(Spacer(10, 20))) print("------------------------------------------") try: doc.build(elements) print("END, pdf is generated") except: print("Error while generating pdf, check correct of sheet")
# 绘制折线 其实就是使用对象PolyLine 这个类来绘制折线 from reportlab.graphics.shapes import Drawing, PolyLine from reportlab.graphics import renderPDF d = Drawing(400, 400) # 通过点生成需要绘制的线。 里面的都是点 坐标的方向是 竖直y 向上越大 水平x 向右越大 lines = PolyLine([(100, 100), (200, 0), (200, 200)]) d.add(lines) renderPDF.drawToFile(d, "line4.pdf", " line file")
def demo(self): d = Drawing(200, 200) d.add(SpiderChart()) return d
def users_passwords_to_pdf(pdf): """ Create access data sheets for all users as PDF. """ users_pdf_wlan_ssid = config["users_pdf_wlan_ssid"] or "-" users_pdf_wlan_password = config["users_pdf_wlan_password"] or "-" users_pdf_wlan_encryption = config["users_pdf_wlan_encryption"] or "-" users_pdf_url = config["users_pdf_url"] or "-" users_pdf_welcometitle = config["users_pdf_welcometitle"] users_pdf_welcometext = config["users_pdf_welcometext"] if config['users_sort_users_by_first_name']: sort = 'first_name' else: sort = 'last_name' qrcode_size = 2 * cm # qrcode for system url qrcode_url = QrCodeWidget(users_pdf_url) qrcode_url.barHeight = qrcode_size qrcode_url.barWidth = qrcode_size qrcode_url.barBorder = 0 qrcode_url_draw = Drawing(45, 45) qrcode_url_draw.add(qrcode_url) # qrcode for wlan text = "WIFI:S:%s;T:%s;P:%s;;" % (users_pdf_wlan_ssid, users_pdf_wlan_encryption, users_pdf_wlan_password) qrcode_wlan = QrCodeWidget(text) qrcode_wlan.barHeight = qrcode_size qrcode_wlan.barWidth = qrcode_size qrcode_wlan.barBorder = 0 qrcode_wlan_draw = Drawing(45, 45) qrcode_wlan_draw.add(qrcode_wlan) for user in User.objects.all().order_by(sort): pdf.append(Paragraph(escape(user.get_full_name()), stylesheet['h1'])) pdf.append(Spacer(0, 1 * cm)) data = [] # WLAN access data cell = [] cell.append(Paragraph(_("WLAN access data"), stylesheet['h2'])) cell.append( Paragraph("%s:" % _("WLAN name (SSID)"), stylesheet['formfield'])) cell.append( Paragraph(escape(users_pdf_wlan_ssid), stylesheet['formfield_value'])) cell.append( Paragraph("%s:" % _("WLAN password"), stylesheet['formfield'])) cell.append( Paragraph(escape(users_pdf_wlan_password), stylesheet['formfield_value'])) cell.append( Paragraph("%s:" % _("WLAN encryption"), stylesheet['formfield'])) cell.append( Paragraph(escape(users_pdf_wlan_encryption), stylesheet['formfield_value'])) cell.append(Spacer(0, 0.5 * cm)) # OpenSlides access data cell2 = [] cell2.append(Paragraph(_("OpenSlides access data"), stylesheet['h2'])) cell2.append(Paragraph("%s:" % _("Username"), stylesheet['formfield'])) cell2.append( Paragraph(escape(user.username), stylesheet['formfield_value'])) cell2.append(Paragraph("%s:" % _("Password"), stylesheet['formfield'])) cell2.append( Paragraph(escape(user.default_password), stylesheet['formfield_value'])) cell2.append(Paragraph("URL:", stylesheet['formfield'])) cell2.append( Paragraph(escape(users_pdf_url), stylesheet['formfield_value'])) data.append([cell, cell2]) # QRCodes cell = [] if users_pdf_wlan_ssid != "-" and users_pdf_wlan_encryption != "-": cell.append(qrcode_wlan_draw) cell.append( Paragraph(_("Scan this QRCode to connect WLAN."), stylesheet['qrcode_comment'])) cell2 = [] if users_pdf_url != "-": cell2.append(qrcode_url_draw) cell2.append( Paragraph(_("Scan this QRCode to open URL."), stylesheet['qrcode_comment'])) data.append([cell, cell2]) # build table table = Table(data) table._argW[0] = 8 * cm table._argW[1] = 8 * cm table.setStyle(TableStyle([('VALIGN', (0, 0), (-1, -1), 'TOP')])) pdf.append(table) pdf.append(Spacer(0, 2 * cm)) # welcome title and text pdf.append(Paragraph(escape(users_pdf_welcometitle), stylesheet['h2'])) pdf.append( Paragraph( escape(users_pdf_welcometext).replace('\r\n', '<br/>'), stylesheet['Paragraph12'])) pdf.append(PageBreak()) return pdf
c.drawString(-10,L.sizeY*-1-40, "This text is on every page. Attention, this position is relativ to the first label." + " "*27 + "Page " + str(int(i["id"]/8+1))) c.setFillColorRGB(*i["rgb"]) c.setFont("Helvetica-Bold", size=8) c.drawCentredString(L.sizeX / 2 , 27, i["color"]) c.setFillColorRGB(0, 0, 0) c.setFont("Courier", size=7) c.drawCentredString(L.sizeX/2, 7, "ID: " + str(i["id"])) # draw barcodes #bc = code39.Extended39("ID%.6i" % i["id"], barWidth=0.30, barHeight=10) #bc = code128.Code128("ID%.6i" % i["id"], barWidth=0.45, barHeight=10 bc = code93.Standard93("ID%.6i" % i["id"], barWidth=0.33, barHeight=8) bc.drawOn(c, -10, 14 ) # draw QR-code qr_code = qr.QrCodeWidget("WEB:www.example.com\nACCESS:%s\nID%.6i\nTS:%s" % (i["color"],i["id"],datetime.now().strftime("%m/%d/%Y, %H:%M:%S"))) bounds = qr_code.getBounds() width = bounds[2] - bounds[0] height = bounds[3] - bounds[1] dr = Drawing(0, 0, transform=[25. / width, 0, 0, 25. / height, 0, 0]) dr.add(qr_code) renderPDF.draw(dr, c, L.sizeX/2-12, 35) # draw hole c.circle(7, L.sizeY-7, 2.5) # draw image c.drawImage("star.jpg",5.0,27.0,width=6,height=6, preserveAspectRatio=True, anchor='c') L.save() L.show()
def pdf_drawPolyline(self, table_data, table_lable=[], title="", title_size=70, title_font=FONTBLOD, x=350, y=1800, width=2000, height=1000, line_width=8, lable_color=HexColor(0x000000), lable_angle=45, lable_fontsize=30, legend_y=450): ''' @example: chart_data_1 = { 'name': 'Occupancy ', 'data': [1,2,3,5,6,8], 'color': HexColor(0x2ebf70) } chart_data = [] chart_data.append(chart_data_1) self.pdf_drawPolyline(chart_data) ''' y = self.pdf_config_object.pdf_height - y chart_values = [] size = len(table_data) if size == 0: return width_single = width / size / 4 / 3 step = width / size x_position_tmp = x + step / 3 y_position = y + 70 * 3 + height title_position = self.get_title_position(width, title, title_size) self.pdf_page_object.setFillColor(HexColor(0x000000)) self.pdf_page_object.setFont(title_font, title_size) self.pdf_page_object.drawString(x + title_position - 120, y + height + title_size * 5 - 200, title) self.pdf_page_object.setLineWidth(line_width) i = 0 for single in table_data: chart_values.append(single['data']) self.pdf_page_object.setStrokeColor(single['color']) x_position = x_position_tmp + (i) * step self.pdf_page_object.line(x_position, y_position - legend_y - height, x_position + width_single * 0.8, y_position - legend_y - height) self.pdf_page_object.setFont(FONTBLOD, 40) self.pdf_page_object.setFillColor(HexColor(0x000000)) self.pdf_page_object.drawString(x_position + width_single, y_position - legend_y - height, single['name']) i = i + 1 drawing = Drawing(x, y) lc = HorizontalLineChart() lc.valueAxis.visible = 0 lc.categoryAxis.gridStrokeColor = colors.gray lc.valueAxis.gridStrokeColor = colors.gray lc.valueAxis.visibleGrid = 1 lc.valueAxis.labels.visible = 0 lc.height = height lc.width = width lc.data = chart_values lc.categoryAxis.categoryNames = table_lable lc.categoryAxis.labels.fontName = FONTBLOD lc.strokeColor = HexColor(0xffffff) lc.categoryAxis.labels.angle = 0 lc.categoryAxis.labels.strokeColor = lable_color lc.categoryAxis.labels.angle = lable_angle lc.categoryAxis.labels.dy = -60 lc.categoryAxis.labels.fontSize = lable_fontsize lc.valueAxis.valueMin = 0 y_value_max = self.get_biggest_value(chart_values) + 20 lc.valueAxis.valueMax = (y_value_max / 10) * 13 lc.valueAxis.valueStep = (y_value_max / 10) * 13 / 5 lc.lines.strokeWidth = line_width for i in range(size): lc.lines[i].strokeColor = table_data[i]['color'] if len(chart_values[0]) == 0: return drawing.add(lc) drawing.drawOn(self.pdf_page_object, x, y) labelArr = [] step = (y_value_max / 10) * 13 / 5 valueMax = (y_value_max / 10) * 13 for i in range(5): labelArr.append(i * step) self.pdf_page_object.drawString(x - 100, y + height * i * step / valueMax, format(i * step, ',')) self.pdf_page_object.drawString(x - 100, y + height, format(5 * step, ',')) lenthOfLabelLine = 100 arrLabeled = [] for item in table_data: self.pdf_page_object.setStrokeColor(item['color'], 1) self.pdf_page_object.setLineWidth(3) self.pdf_page_object.setFillColor(item['color']) peakData = self.get_max_data(item['data']) for peakInLoop in peakData: peakDataOne = peakInLoop['value'] posInarry = peakInLoop['index'] posYOfPeak = y + height * peakDataOne / valueMax + 10 posXOfPeak = x + width / len(item['data']) * ( posInarry + 1) - width / len(item['data']) / 2 + 20 if posInarry in arrLabeled: lenthOfLabelLine = lenthOfLabelLine + 80 deltaX, deltaY = self.get_randomdelta(lenthOfLabelLine) self.pdf_page_object.line(posXOfPeak, posYOfPeak, posXOfPeak + deltaX, posYOfPeak + deltaY) self.pdf_page_object.drawCentredString( posXOfPeak + deltaX, posYOfPeak + deltaY + 10, format(peakDataOne, ',')) arrLabeled.append(posInarry) lenthOfLabelLine = 100
def qr_code_result(request): response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'inline; filename="mypdf.pdf"' buffer = BytesIO() p = canvas.Canvas(buffer) # # Start writing the PDF here # p.setFont("Helvetica", 10) # p.drawString(110, 790, 'Range') # p.drawString(150, 790, 'Row') # p.drawString(110, 780, 'RowID') # p.drawString(110, 770, 'Entry') # p.drawString(110, 760, 'Source') # # End writing # qr_code = qr.QrCodeWidget('Range_Row_RowID_Enrty_Source') # bounds = qr_code.getBounds() # width = bounds[2] - bounds[0] # height = bounds[3] - bounds[1] # d = Drawing(50, 50, transform=[50./width,0,0,50./height,0,0]) # d.add(qr_code) # renderPDF.draw(d, p, 50, 755) # ################################## # p.setFont("Helvetica", 10) # p.drawString(110, 740, 'Range') # p.drawString(150, 740, 'Row') # p.drawString(110, 730, 'RowID') # p.drawString(110, 720, 'Entry') # p.drawString(110, 710, 'Source') C = 110 for j in range(3): H = 790 for i in range(15): p.setFont("Helvetica", 10) p.drawString(C, H, 'Range') p.drawString((C + 40), H, 'Row') p.drawString(C, (H - 10), 'RowID') p.drawString(C, (H - 20), 'Entry') p.drawString(C, (H - 30), 'Source') # End writing qr_code = qr.QrCodeWidget('Range_Row_RowID_Enrty_Source') bounds = qr_code.getBounds() width = bounds[2] - bounds[0] height = bounds[3] - bounds[1] d = Drawing(50, 50, transform=[50. / width, 0, 0, 50. / height, 0, 0]) d.add(qr_code) renderPDF.draw(d, p, (C - 60), (H - 35)) H -= 50 C += 175 p.showPage() p.save() pdf = buffer.getvalue() buffer.close() response.write(pdf) return response
def demo(self): D = Drawing(100, 100) g = DoubleGrid() D.add(g) return D
def pdf_drawBar(self, chart_data, categoryNames=[], bar_color=[], title="", title_size=70, title_font=FONTBLOD, x=300, y=1600, chart_width=2000, chart_height=655, lable_fontSize=50, background_color=HexColor(0x000000), lable_angle=0, lable_y=0): ''' @example: chart_data = [25,65,330] chart_lable=['Rank','Total Entries'] data = [] data.append(chart_data) self.pdf_drawBar(data,categoryNames = chart_lable) ''' y = self.pdf_config_object.pdf_height - y title_position = self.get_title_position(chart_width, title, title_size) self.pdf_page_object.setFillColor(HexColor(0x000000)) self.pdf_page_object.setFont(title_font, title_size) self.pdf_page_object.drawString(x + title_position - 150, y + chart_height + title_size * 3 - 80, title) max_list = [] for index in range(len(chart_data)): if chart_data[index]: max_list.append(max(chart_data[index])) else: max_list.append(0) barchart_max = max(max_list) + 100 drawing = Drawing(800, 2230) bc = VerticalBarChart() bc.x = 0 bc.y = 0 bc.height = chart_height bc.width = chart_width bc.data = chart_data bc.groupSpacing = 15 bc.barSpacing = 10 bc.strokeColor = HexColor(0xDFDFDF) bc.valueAxis.valueMin = 0 bc.valueAxis.valueMax = barchart_max + barchart_max / 20 bc.valueAxis.valueStep = (barchart_max + barchart_max / 20) / 5 bc.valueAxis.visible = 0 bc.valueAxis.gridStrokeColor = colors.gray bc.valueAxis.visibleGrid = 1 bc.categoryAxis.labels.dx = 8 bc.categoryAxis.labels.dy = lable_y bc.categoryAxis.labels.fontSize = lable_fontSize bc.categoryAxis.labels.angle = lable_angle bc.categoryAxis.categoryNames = categoryNames if len(bar_color) == 0: for i in range(len(chart_data)): bar_color.append(HexColor(self.randomcolor())) for i in range(len(chart_data)): setattr(bc.bars[i], 'fillColor', bar_color[i]) setattr(bc.bars[i], 'strokeColor', colors.white) bc.fillColor = HexColor(0xffffff) drawing.add(bc) drawing.drawOn(self.pdf_page_object, x, y) barchart_max = barchart_max + barchart_max / 20 try: colWidths = chart_width / (len(chart_data[0])) except ZeroDivisionError as e: raise e return yheight = chart_height yStart = y self.pdf_page_object.setFillColor(background_color) self.pdf_page_object.setFont(FONTBLOD, 50) for i in range(len(chart_data)): width = 0 if not chart_data[i] == 0: for j in range(len(chart_data[i])): width = x + j * colWidths try: if len(chart_data) == 1: self.pdf_page_object.drawCentredString( width + colWidths / 2, yStart + yheight * chart_data[i][j] / barchart_max + 20, format(int(chart_data[i][j]), ',')) else: self.pdf_page_object.drawCentredString( width + colWidths / (2 * len(chart_data) + 1) * ((i + 1) * 2) - colWidths / (2 * len(chart_data) + 1) / 2, yStart + yheight * chart_data[i][j] / barchart_max + 20, format(int(chart_data[i][j]), ',')) except Exception as e: raise e
report_title = Paragraph("A Complete Inventory of My Fruit", styles["h1"]) report.build([report_title]) #content table_data = [] for k, v in fruit.items(): table_data.append([k, v]) print(table_data) report_table = Table(data=table_data) report.build([report_title, report_table]) table_style = [('GRID', (0, 0), (-1, -1), 1, colors.black)] report_table = Table(data=table_data, style=table_style, hAlign="LEFT") report.build([report_title, report_table]) #graph report_pie = Pie(width=3, height=3) report_pie.data = [] report_pie.labels = [] for fruit_name in sorted(fruit): report_pie.data.append(fruit[fruit_name]) report_pie.labels.append(fruit_name) print(report_pie.data) print(report_pie.labels) report_chart = Drawing() report_chart.add(report_pie) report.build([report_title, report_table, report_chart])
def demo(self): D = Drawing(100, 100) g = ShadedRect() D.add(g) return D
data = [] for line in open("Predict.txt", "r").readlines(): # line = line.decode() if not line.isspace() and line[0] not in COMMENT_CHARS: data.append([float(n) for n in line.split()]) pred = [row[2] for row in data] high = [row[3] for row in data] low = [row[4] for row in data] times = [row[0] + row[1] / 12.0 for row in data] lp = LinePlot() lp.x = 50 lp.y = 50 lp.height = 125 lp.width = 300 lp.data = [ list(zip(times, pred)), list(zip(times, high)), list(zip(times, low)) ] lp.lines[0].strokeColor = colors.blue lp.lines[1].strokeColor = colors.red lp.lines[2].strokeColor = colors.green drawing.add(lp) drawing.add(String(250, 150, "Sunspots", fontSize=14, fillColor=colors.red)) renderPDF.drawToFile(drawing, "report2.pdf", "Sunspots")
orientation = 'horizontal' angle = 0 rect = ShadedRect(strokeWidth=0, strokeColor=None, orientation=orientation) for k in 'fillColorStart', 'fillColorEnd', 'numShades', 'cylinderMode': setattr(rect, k, getattr(self, k)) g.add(rotatedEnclosingRect(P, angle, rect)) g.add(EmptyClipPath) path = path.copy() path.isClipPath = 0 path.strokeColor = self.strokeColor path.strokeWidth = self.strokeWidth g.add(path) return g if __name__ == '__main__': #noruntests from reportlab.lib.colors import blue from reportlab.graphics.shapes import Drawing angle = 45 D = Drawing(120, 120) D.add( ShadedPolygon(points=(10, 10, 60, 60, 110, 10), strokeColor=None, strokeWidth=1, angle=90, numShades=50, cylinderMode=0)) D.save(formats=['gif'], fnRoot='shobj', outDir='/tmp')
def graph(): ciudad1 = str(cities[len(cities) - 1]) ciudad2 = 'm' if len(cities) > 2: counter = 1 i = 2 while i < len(cities) + 1: if ciudad1 == str(cities[len(cities) - i]) or ciudad2 == str( cities[len(cities) - i]): i += 1 elif ciudad2 == 'm': ciudad2 = str(cities[len(cities) - i]) counter += 1 if counter < 4: i += 1 else: i = len(cities) + 2 elif ciudad2 != 'm': if ciudad1 == str(cities[len(cities) - i]) or ciudad2 == str( cities[len(cities) - i]): i += 1 else: ciudad3 = str(cities[len(cities) - i]) i = len(cities) + 2 indices1 = [] indices2 = [] indices3 = [] for i in range(0, len(cities)): if ciudad1 == cities[i]: indices1.append(i) elif ciudad2 == cities[i]: indices2.append(i) elif ciudad3 == cities[i]: indices3.append(i) temp1 = 0 temp2 = 0 temp3 = 0 for m in indices1: temp1 = temp1 + datac[m] for m in indices2: temp2 = temp2 + datac[m] for m in indices3: temp3 = temp3 + datac[m] temp1 = temp1 / len(indices1) temp2 = temp2 / len(indices2) temp3 = temp3 / len(indices3) d = Drawing(220, 180) bar = VerticalBarChart() bar.x = 25 bar.y = 55 data = [[temp1, 0, temp2, 0, temp3]] bar.data = data try: bar.categoryAxis.categoryNames = [ ciudad1, '', ciudad2, '', ciudad3, '' ] bar.bars[0].fillColor = PCMYKColor(100, 0, 90, 50, alpha=85) d.add(bar, '') d.save(formats=['gif'], outDir='.', fnRoot='grafica') except: bar.categoryAxis.categoryNames = [str(cities[len(cities) - 1])] bar.bars[0].fillColor = PCMYKColor(100, 0, 90, 50, alpha=85) d.add(bar, '') d.save(formats=['gif'], outDir='.', fnRoot='grafica') photo1 = PhotoImage(file="grafica.gif") label = Label(tab4, image=photo1).grid(row=5, column=0) label2 = Label(tab4, text='grafica', fg="grafica").grid(row=5, column=3)
class Sheet(object): """Create one or more sheets of labels. """ def __init__(self, specification, drawing_callable, pages_to_draw=None, border=False, shade_missing=False): """ Parameters ---------- specification: labels.Specification instance The sizes etc of the label sheets. drawing_callable: callable A function (or other callable object) to call to draw an individual label. It will be given four parameters specifying the label. In order, these are a `reportlab.graphics.shapes.Drawing` instance to draw the label on, the width of the label, the height of the label, and the object to draw. The dimensions will be in points, the unit of choice for ReportLab. pages_to_draw: list of positive integers, default None The list pages to actually draw labels on. This is intended to be used with the preview methods to avoid drawing labels that will never be displayed. A value of None means draw all pages. border: Boolean, default False Whether or not to draw a border around each label. shade_missing: Boolean or ReportLab colour, default False Whether or not to shade missing labels (those specified through the partial_pages method). False means leave the labels unshaded. If a ReportLab colour is given, the labels will be shaded in that colour. A value of True will result in the missing labels being shaded in the hex colour 0xBBBBBB (a medium-light grey). Notes ----- If you specify a pages_to_draw list, pages not in that list will be blank since the drawing function will not be called on that page. This could have a side-affect if you rely on the drawing function modifying some global values. For example, in the nametags.py and preview.py demo scripts, the colours for each label are picked by a pseduo-random number generator. However, in the preview script, this generator is not advanced and so the colours on the last page differ between the preview and the actual output. """ # Save our arguments. specification._calculate() self.specs = deepcopy(specification) self.drawing_callable = drawing_callable self.pages_to_draw = pages_to_draw self.border = border if shade_missing == True: self.shade_missing = colors.HexColor(0xBBBBBB) else: self.shade_missing = shade_missing # Set up some internal variables. self._lw = self.specs.label_width * mm self._lh = self.specs.label_height * mm self._cr = self.specs.corner_radius * mm self._dw = (self.specs.label_width - self.specs.left_padding - self.specs.right_padding) * mm self._dh = (self.specs.label_height - self.specs.top_padding - self.specs.bottom_padding) * mm self._lp = self.specs.left_padding * mm self._bp = self.specs.bottom_padding * mm self._pr = self.specs.padding_radius * mm self._used = {} self._pages = [] self._current_page = None # Page information. self._pagesize = (float(self.specs.sheet_width*mm), float(self.specs.sheet_height*mm)) self._numlabels = [self.specs.rows, self.specs.columns] self._position = [1, 0] self.label_count = 0 self.page_count = 0 # Background image. if self.specs.background_image: self._bgimage = deepcopy(self.specs.background_image) # Different classes are scaled in different ways... if isinstance(self._bgimage, Image): self._bgimage.x = 0 self._bgimage.y = 0 self._bgimage.width = self._pagesize[0] self._bgimage.height = self._pagesize[1] elif isinstance(self._bgimage, Drawing): self._bgimage.shift(0, 0) self._bgimage.scale(self._pagesize[0]/self._bgimage.width, self._pagesize[1]/self._bgimage.height) else: raise ValueError("Unhandled background type.") # Background from a filename. elif self.specs.background_filename: self._bgimage = Image(0, 0, self._pagesize[0], self._pagesize[1], self.specs.background_filename) # No background. else: self._bgimage = None # Borders and clipping paths. We need two clipping paths; one for the # label as a whole (which is identical to the border), and one for the # available drawing area (i.e., after taking the padding into account). # This is necessary because sometimes the drawing area can extend # outside the border at the corners, e.g., if there is left padding # only and no padding radius, then the 'available' area corners will be # square and go outside the label corners if they are rounded. # Copy some properties to a local scope. h, w, r = float(self._lh), float(self._lw), float(self._cr) # Create the border from a path. If the corners are not rounded, skip # adding the arcs. border = ArcPath() if r: border.moveTo(w - r, 0) border.addArc(w - r, r, r, -90, 0) border.lineTo(w, h - r) border.addArc(w - r, h - r, r, 0, 90) border.lineTo(r, h) border.addArc(r, h - r, r, 90, 180) border.lineTo(0, r) border.addArc(r, r, r, 180, 270) border.closePath() else: border.moveTo(0, 0) border.lineTo(w, 0) border.lineTo(w, h) border.lineTo(0, h) border.closePath() # Set the properties and store. border.isClipPath = 0 border.strokeWidth = 1 border.strokeColor = colors.black border.fillColor = None self._border = border # Clip path for the label is the same as the border. self._clip_label = deepcopy(border) self._clip_label.isClipPath = 1 self._clip_label.strokeColor = None self._clip_label.fillColor = None # If there is no padding (i.e., the drawable area is the same as the # label area) then we can just use the label clip path for the drawing # clip path. if (self._dw == self._lw) and (self._dh == self._lh): self._clip_drawing = self._clip_label # Otherwise we have to generate a separate path. else: h, w, r = float(self._dh), float(self._dw), float(self._pr) clip = ArcPath() if r: clip.moveTo(w - r, 0) clip.addArc(w - r, r, r, -90, 0) clip.lineTo(w, h - r) clip.addArc(w - r, h - r, r, 0, 90) clip.lineTo(r, h) clip.addArc(r, h - r, r, 90, 180) clip.lineTo(0, r) clip.addArc(r, r, r, 180, 270) clip.closePath() else: clip.moveTo(0, 0) clip.lineTo(w, 0) clip.lineTo(w, h) clip.lineTo(0, h) clip.closePath() # Set the clipping properties. clip.isClipPath = 1 clip.strokeColor = None clip.fillColor = None self._clip_drawing = clip def partial_page(self, page, used_labels): """Allows a page to be marked as already partially used so you can generate a PDF to print on the remaining labels. Parameters ---------- page: positive integer The page number to mark as partially used. The page must not have already been started, i.e., for page 1 this must be called before any labels have been started, for page 2 this must be called before the first page is full and so on. used_labels: iterable An iterable of (row, column) pairs marking which labels have been used already. The rows and columns must be within the bounds of the sheet. """ # Check the page number is valid. if page <= self.page_count: raise ValueError("Page {0:d} has already started, cannot mark used labels now.".format(page)) # Add these to any existing labels marked as used. used = self._used.get(page, set()) for row, column in used_labels: # Check the index is valid. if row < 1 or row > self.specs.rows: raise IndexError("Invalid row number: {0:d}.".format(row)) if column < 1 or column > self.specs.columns: raise IndexError("Invalid column number: {0:d}.".format(column)) # Add it. used.add((int(row), int(column))) # Save the details. self._used[page] = used def _new_page(self): """Helper function to start a new page. Not intended for external use. """ self._current_page = Drawing(*self._pagesize) if self._bgimage: self._current_page.add(self._bgimage) self._pages.append(self._current_page) self.page_count += 1 self._position = [1, 0] def _next_label(self): """Helper method to move to the next label. Not intended for external use. This does not increment the label_count attribute as the next label may not be usable (it may have been marked as missing through partial_pages). See _next_unused_label for generally more useful method. """ # Special case for the very first label. if self.page_count == 0: self._new_page() # Filled up a page. elif self._position == self._numlabels: self._new_page() # Filled up a row. elif self._position[1] == self.specs.columns: self._position[0] += 1 self._position[1] = 0 # Move to the next column. self._position[1] += 1 def _next_unused_label(self): """Helper method to move to the next unused label. Not intended for external use. This method will shade in any missing labels if desired, and will increment the label_count attribute once a suitable label position has been found. """ self._next_label() # This label may be missing. if self.page_count in self._used: # Keep try while the label is missing. missing = self._used.get(self.page_count, set()) while tuple(self._position) in missing: # Throw the missing information away now we have used it. This # allows the _shade_remaining_missing method to work. missing.discard(tuple(self._position)) # Shade the missing label if desired. if self.shade_missing: self._shade_missing_label() # Try our luck with the next label. self._next_label() missing = self._used.get(self.page_count, set()) # Increment the count now we have found a suitable position. self.label_count += 1 def _calculate_edges(self): """Calculate edges of the current label. Not intended for external use. """ # Calculate the left edge of the label. left = self.specs.left_margin left += (self.specs.label_width * (self._position[1] - 1)) if self.specs.column_gap: left += (self.specs.column_gap * (self._position[1] - 1)) left *= mm # And the bottom. bottom = self.specs.sheet_height - self.specs.top_margin bottom -= (self.specs.label_height * self._position[0]) if self.specs.row_gap: bottom -= (self.specs.row_gap * (self._position[0] - 1)) bottom *= mm # Done. return float(left), float(bottom) def _shade_missing_label(self): """Helper method to shade a missing label. Not intended for external use. """ # Start a drawing for the whole label. label = Drawing(float(self._lw), float(self._lh)) label.add(self._clip_label) # Fill with a rectangle; the clipping path will take care of the borders. r = shapes.Rect(0, 0, float(self._lw), float(self._lh)) r.fillColor = self.shade_missing r.strokeColor = None label.add(r) # Add the label to the page. label.shift(*self._calculate_edges()) self._current_page.add(label) def _shade_remaining_missing(self): """Helper method to shade any missing labels remaining on the current page. Not intended for external use. Note that this will modify the internal _position attribute and should therefore only be used once all the 'real' labels have been drawn. """ # Sanity check. if not self.shade_missing: return # Run through each missing label left in the current page and shade it. missing = self._used.get(self.page_count, set()) for position in missing: self._position = position self._shade_missing_label() def _draw_label(self, obj, count): """Helper method to draw on the current label. Not intended for external use. """ # Start a drawing for the whole label. label = Drawing(float(self._lw), float(self._lh)) label.add(self._clip_label) # And one for the available area (i.e., after padding). available = Drawing(float(self._dw), float(self._dh)) available.add(self._clip_drawing) # Call the drawing function. self.drawing_callable(available, float(self._dw), float(self._dh), obj) # Render the contents on the label. available.shift(float(self._lp), float(self._bp)) label.add(available) # Draw the border if requested. if self.border: label.add(self._border) # Add however many copies we need to. for i in range(count): # Find the next available label. self._next_unused_label() # Have we been told to skip this page? if self.pages_to_draw and self.page_count not in self.pages_to_draw: continue # Add the label to the page. ReportLab stores the added drawing by # reference so we have to copy it N times. thislabel = copy(label) thislabel.shift(*self._calculate_edges()) self._current_page.add(thislabel) def add_label(self, obj, count=1): """Add a label to the sheet. Parameters ---------- obj: The object to draw on the label. This is passed without modification or copying to the drawing function. count: positive integer, default 1 How many copies of the label to add to the sheet. Note that the drawing function will only be called once and the results copied for each label. If the drawing function maintains any state internally then using this parameter may break it. """ self._draw_label(obj, count) def add_labels(self, objects, count=1): """Add multiple labels to the sheet. Parameters ---------- objects: iterable An iterable of the objects to add. Each of these will be passed to the add_label method. Note that if this is a generator it will be consumed. count: positive integer or iterable of positive integers, default 1 The number of copies of each label to add. If a single integer, that many copies of every label are added. If an iterable, then each value specifies how many copies of the corresponding label to add. The iterables are advanced in parallel until one is exhausted; extra values in the other one are ignored. This means that if there are fewer count entries than objects, the objects corresponding to the missing counts will not be added to the sheet. Note that if this is a generator it will be consumed. Also note that the drawing function will only be called once for each label and the results copied for the repeats. If the drawing function maintains any state internally then using this parameter may break it. """ # If we can convert it to an int, do so and use the itertools.repeat() # method to create an infinite iterator from it. Otherwise, assume it # is an iterable or sequence. try: count = int(count) except TypeError: pass else: count = repeat(count) # If it is not an iterable (e.g., a list or range object), # create an iterator over it. if not hasattr(count, 'next') and not hasattr(count, '__next__'): count = iter(count) # Go through the objects. for obj in objects: # Check we have a count for this one. try: thiscount = next(count) except StopIteration: break # Draw it. self._draw_label(obj, thiscount) def save(self, filelike): """Save the file as a PDF. Parameters ---------- filelike: path or file-like object The filename or file-like object to save the labels under. Any existing contents will be overwritten. """ # Shade any remaining missing labels if desired. self._shade_remaining_missing() # Create a canvas. canvas = Canvas(filelike, pagesize=self._pagesize) canvas.setViewerPreference("PrintScaling", "None") # Render each created page onto the canvas. for page in self._pages: renderPDF.draw(page, canvas, 0, 0) canvas.showPage() # Done. canvas.save() def preview(self, page, filelike, format='png', dpi=72, background_colour=0xFFFFFF): """Render a preview image of a page. Parameters ---------- page: positive integer Which page to render. Must be in the range [1, page_count] filelike: path or file-like object Can be a filename as a string, a Python file object, or something which behaves like a Python file object. For example, if you were using the Django web framework, an HttpResponse object could be passed to render the preview to the browser (as long as you remember to set the mimetype of the response). If you pass a filename, the existing contents will be overwritten. format: string The image format to use for the preview. ReportLab uses the Python Imaging Library (PIL) internally, so any PIL format should be supported. dpi: positive real The dots-per-inch to use when rendering. background_colour: Hex colour specification What color background to use. Notes ----- If you are creating this sheet for a preview only, you can pass the pages_to_draw parameter to the constructor to avoid the drawing function being called for all the labels on pages you'll never look at. If you preview a page you did not tell the sheet to draw, you will get a blank image. Raises ------ ValueError: If the page number is not valid. """ # Check the page number. if page < 1 or page > self.page_count: raise ValueError("Invalid page number; should be between 1 and {0:d}.".format(self.page_count)) # Shade any remaining missing labels if desired. self._shade_remaining_missing() # Rendering to an image (as opposed to a PDF) requires any background # to have an integer width and height if it is a ReportLab Image # object. Drawing objects are exempt from this. oldw, oldh = None, None if isinstance(self._bgimage, Image): oldw, oldh = self._bgimage.width, self._bgimage.height self._bgimage.width = int(oldw) + 1 self._bgimage.height = int(oldh) + 1 # Let ReportLab do the heavy lifting. renderPM.drawToFile(self._pages[page-1], filelike, format, dpi, background_colour) # Restore the size of the background image if we changed it. if oldw: self._bgimage.width = oldw self._bgimage.height = oldh def preview_string(self, page, format='png', dpi=72, background_colour=0xFFFFFF): """Render a preview image of a page as a string. Parameters ---------- page: positive integer Which page to render. Must be in the range [1, page_count] format: string The image format to use for the preview. ReportLab uses the Python Imaging Library (PIL) internally, so any PIL format should be supported. dpi: positive real The dots-per-inch to use when rendering. background_colour: Hex colour specification What color background to use. Notes ----- If you are creating this sheet for a preview only, you can pass the pages_to_draw parameter to the constructor to avoid the drawing function being called for all the labels on pages you'll never look at. If you preview a page you did not tell the sheet to draw, you will get a blank image. Raises ------ ValueError: If the page number is not valid. """ # Check the page number. if page < 1 or page > self.page_count: raise ValueError("Invalid page number; should be between 1 and {0:d}.".format(self.page_count)) # Shade any remaining missing labels if desired. self._shade_remaining_missing() # Rendering to an image (as opposed to a PDF) requires any background # to have an integer width and height if it is a ReportLab Image # object. Drawing objects are exempt from this. oldw, oldh = None, None if isinstance(self._bgimage, Image): oldw, oldh = self._bgimage.width, self._bgimage.height self._bgimage.width = int(oldw) + 1 self._bgimage.height = int(oldh) + 1 # Let ReportLab do the heavy lifting. s = renderPM.drawToString(self._pages[page-1], format, dpi, background_colour) # Restore the size of the background image if we changed it. if oldw: self._bgimage.width = oldw self._bgimage.height = oldh # Done. return s
def draw_qr_code(self, string): qr_code = qr.QrCodeWidget(string) drawing = Drawing(23 * mm, 23 * mm) drawing.add(qr_code) renderPDF.draw(drawing, self.canvas, 20 * mm, self.current_height - 85) self.current_height -= 85
car_sales_lst.append(car_sales) car_price = float(i[2].strip( "$")) #by default all the prices are in '', for example '18731.76 car_price_lst.append(car_price) d = Drawing(400, 400) pc = Pie() pc.x = 100 pc.y = 240 pc.width = 130 pc.height = 130 pc.sideLabels = True pc.sideLabelsOffset = 0.05 pc.data = car_sales_lst[:10] pc.labels = list(set(car_name_lst[:10])) d.add(pc, '') revenue_calculation_1 = car_sales_lst[:10] revenue_calculation_2 = car_price_lst[:10] car_revenue_list = [] for i in range(len(car_price_lst[:10])): reven = revenue_calculation_1[i] * revenue_calculation_2[i] car_revenue_list.append( int(reven)) #using int because its many digits after "," #print(car_revenue_list) bc = VerticalBarChart() data = [tuple(car_revenue_list)] bc.x = 50 bc.y = 75