def _path(self, node): self.path = self.canvas.beginPath() self.path.moveTo(**utils.attr_get(node, ['x', 'y'])) for n in utils._child_get(node, self): if not n.text: if n.tag == 'moveto': vals = utils.text_get(n).split() self.path.moveTo( utils.unit_get( vals[0]), utils.unit_get( vals[1])) elif n.tag == 'curvesto': vals = utils.text_get(n).split() while len(vals) > 5: pos = [] while len(pos) < 6: pos.append(utils.unit_get(vals.pop(0))) self.path.curveTo(*pos) elif n.text: data = n.text.split() while len(data) > 1: x = utils.unit_get(data.pop(0)) y = utils.unit_get(data.pop(0)) self.path.lineTo(x, y) if (not node.get('close')) or utils.bool_get(node.get('close')): self.path.close() self.canvas.drawPath( self.path, **utils.attr_get(node, [], { 'fill': 'bool', 'stroke': 'bool'}))
def _rect(self, node): if node.get('round'): self.canvas.roundRect(radius=utils.unit_get(node.get('round')), **utils.attr_get(node, ['x', 'y', 'width', 'height'], {'fill': 'bool', 'stroke': 'bool'})) else: self.canvas.rect(**utils.attr_get(node, ['x', 'y', 'width', 'height'], {'fill': 'bool', 'stroke': 'bool'}))
def _path(self, node): self.path = self.canvas.beginPath() self.path.moveTo(**utils.attr_get(node, ['x', 'y'])) for n in utils._child_get(node, self): if not n.text: if n.tag == 'moveto': vals = utils.text_get(n).split() self.path.moveTo(utils.unit_get(vals[0]), utils.unit_get(vals[1])) elif n.tag == 'curvesto': vals = utils.text_get(n).split() while len(vals) > 5: pos = [] while len(pos) < 6: pos.append(utils.unit_get(vals.pop(0))) self.path.curveTo(*pos) elif n.text: data = n.text.split( ) # Not sure if I must merge all TEXT_NODE ? while len(data) > 1: x = utils.unit_get(data.pop(0)) y = utils.unit_get(data.pop(0)) self.path.lineTo(x, y) if (not node.get('close')) or utils.bool_get(node.get('close')): self.path.close() self.canvas.drawPath( self.path, **utils.attr_get(node, [], { 'fill': 'bool', 'stroke': 'bool' }))
def _rect(self, node): if node.get("round"): self.canvas.roundRect( radius=utils.unit_get(node.get("round")), **utils.attr_get(node, ["x", "y", "width", "height"], {"fill": "bool", "stroke": "bool"}) ) else: self.canvas.rect(**utils.attr_get(node, ["x", "y", "width", "height"], {"fill": "bool", "stroke": "bool"}))
def __init__(self, localcontext, out, node, doc, images=None, path='.', title=None): if images is None: images = {} if not localcontext: localcontext = {'internal_header': True} self.localcontext = localcontext self.images = images self.path = path self.title = title pagesize_map = {'a4': A4, 'us_letter': letter } pageSize = (841.8897637795275, 595.275590551181) self.doc_tmpl = TinyDocTemplate(out, pagesize=pageSize, **utils.attr_get(node, ['leftMargin', 'rightMargin', 'topMargin', 'bottomMargin'], {'allowSplitting': 'int', 'showBoundary': 'bool', 'rotation': 'int', 'title': 'str', 'author': 'str'})) self.page_templates = [] self.styles = doc.styles self.doc = doc self.image = [] pts = node.findall('pageTemplate') for pt in pts: frames = [] for frame_el in pt.findall('frame'): frame = platypus.Frame(**(utils.attr_get(frame_el, ['x1', 'y1', 'width', 'height', 'leftPadding', 'rightPadding', 'bottomPadding', 'topPadding'], {'id': 'str', 'showBoundary': 'bool'}))) if utils.attr_get(frame_el, ['last']): frame.lastFrame = True frames.append(frame) try: gr = pt.findall('pageGraphics') \ or pt[1].findall('pageGraphics') except Exception: # FIXME: be even more specific, perhaps? gr = '' if len(gr): # self.image=[ n for n in utils._child_get(gr[0], self) if n.tag=='image' or not self.localcontext] drw = _rml_draw(self.localcontext, gr[0], self.doc, images=images, path=self.path, title=self.title) self.page_templates.append( platypus.PageTemplate(frames=frames, onPage=drw.render, **utils.attr_get(pt, [], {'id': 'str'}))) else: drw = _rml_draw(self.localcontext, node, self.doc, title=self.title) self.page_templates.append( platypus.PageTemplate(frames=frames, onPage=drw.render, **utils.attr_get(pt, [], {'id': 'str'}))) self.doc_tmpl.addPageTemplates(self.page_templates)
def _rect(self, node): if node.get('round'): self.canvas.roundRect(radius=utils.unit_get(node.get('round')), **utils.attr_get( node, ['x', 'y', 'width', 'height'], { 'fill': 'bool', 'stroke': 'bool' })) else: self.canvas.rect( **utils.attr_get(node, ['x', 'y', 'width', 'height'], { 'fill': 'bool', 'stroke': 'bool' }))
def _circle(self, node): self.canvas.circle( x_cen=utils.unit_get(node.get("x")), y_cen=utils.unit_get(node.get("y")), r=utils.unit_get(node.get("radius")), **utils.attr_get(node, [], {"fill": "bool", "stroke": "bool"}) )
def _ellipse(self, node): x1 = utils.unit_get(node.get("x")) x2 = utils.unit_get(node.get("width")) y1 = utils.unit_get(node.get("y")) y2 = utils.unit_get(node.get("height")) self.canvas.ellipse(x1, y1, x2, y2, **utils.attr_get(node, [], {"fill": "bool", "stroke": "bool"}))
def _ellipse(self, node): x1 = utils.unit_get(node.get('x')) x2 = utils.unit_get(node.get('width')) y1 = utils.unit_get(node.get('y')) y2 = utils.unit_get(node.get('height')) self.canvas.ellipse(x1,y1,x2,y2, **utils.attr_get(node, [], {'fill':'bool','stroke':'bool'}))
def _circle(self, node): self.canvas.circle(x_cen=utils.unit_get(node.get('x')), y_cen=utils.unit_get(node.get('y')), r=utils.unit_get(node.get('radius')), **utils.attr_get(node, [], { 'fill': 'bool', 'stroke': 'bool' }))
def _circle(self, node): self.canvas.circle( x_cen=utils.unit_get( node.get('x')), y_cen=utils.unit_get( node.get('y')), r=utils.unit_get( node.get('radius')), **utils.attr_get( node, [], { 'fill': 'bool', 'stroke': 'bool'}))
def __init__(self, localcontext, out, node, doc, images=None, path='.', title=None): if images is None: images = {} if not localcontext: localcontext={'internal_header':True} self.localcontext = localcontext self.images= images self.path = path self.title = title pagesize_map = {'a4': A4, 'us_letter': letter } pageSize = (841.8897637795275, 595.275590551181) self.doc_tmpl = TinyDocTemplate(out, pagesize=pageSize, **utils.attr_get(node, ['leftMargin','rightMargin','topMargin','bottomMargin'], {'allowSplitting':'int','showBoundary':'bool','rotation':'int','title':'str','author':'str'})) self.page_templates = [] self.styles = doc.styles self.doc = doc self.image=[] pts = node.findall('pageTemplate') for pt in pts: frames = [] for frame_el in pt.findall('frame'): frame = platypus.Frame( **(utils.attr_get(frame_el, ['x1','y1', 'width','height', 'leftPadding', 'rightPadding', 'bottomPadding', 'topPadding'], {'id':'str', 'showBoundary':'bool'})) ) if utils.attr_get(frame_el, ['last']): frame.lastFrame = True frames.append( frame ) try : gr = pt.findall('pageGraphics')\ or pt[1].findall('pageGraphics') except Exception: # FIXME: be even more specific, perhaps? gr='' if len(gr): # self.image=[ n for n in utils._child_get(gr[0], self) if n.tag=='image' or not self.localcontext] drw = _rml_draw(self.localcontext,gr[0], self.doc, images=images, path=self.path, title=self.title) self.page_templates.append( platypus.PageTemplate(frames=frames, onPage=drw.render, **utils.attr_get(pt, [], {'id':'str'}) )) else: drw = _rml_draw(self.localcontext,node,self.doc,title=self.title) self.page_templates.append( platypus.PageTemplate(frames=frames,onPage=drw.render, **utils.attr_get(pt, [], {'id':'str'}) )) self.doc_tmpl.addPageTemplates(self.page_templates)
def _place(self, node): flows = _rml_flowable(self.doc, self.localcontext, images=self.images, path=self.path, title=self.title).render(node) infos = utils.attr_get(node, ['x','y','width','height']) infos['y']+=infos['height'] for flow in flows: w,h = flow.wrap(infos['width'], infos['height']) if w<=infos['width'] and h<=infos['height']: infos['y']-=h flow.drawOn(self.canvas,infos['x'],infos['y']) infos['height']-=h else: raise ValueError("Not enough space")
def _place(self, node): flows = _rml_flowable(self.doc, self.localcontext, images=self.images, path=self.path, title=self.title).render( node ) infos = utils.attr_get(node, ["x", "y", "width", "height"]) infos["y"] += infos["height"] for flow in flows: w, h = flow.wrap(infos["width"], infos["height"]) if w <= infos["width"] and h <= infos["height"]: infos["y"] -= h flow.drawOn(self.canvas, infos["x"], infos["y"]) infos["height"] -= h else: raise ValueError("Not enough space")
def _path(self, node): self.path = self.canvas.beginPath() self.path.moveTo(**utils.attr_get(node, ["x", "y"])) for n in utils._child_get(node, self): if not n.text: if n.tag == "moveto": vals = utils.text_get(n).split() self.path.moveTo(utils.unit_get(vals[0]), utils.unit_get(vals[1])) elif n.tag == "curvesto": vals = utils.text_get(n).split() while len(vals) > 5: pos = [] while len(pos) < 6: pos.append(utils.unit_get(vals.pop(0))) self.path.curveTo(*pos) elif n.text: data = n.text.split() # Not sure if I must merge all TEXT_NODE ? while len(data) > 1: x = utils.unit_get(data.pop(0)) y = utils.unit_get(data.pop(0)) self.path.lineTo(x, y) if (not node.get("close")) or utils.bool_get(node.get("close")): self.path.close() self.canvas.drawPath(self.path, **utils.attr_get(node, [], {"fill": "bool", "stroke": "bool"}))
def _table(self, node): children = utils._child_get(node,self,'tr') if not children: return None length = 0 colwidths = None rowheights = None data = [] styles = [] posy = 0 for tr in children: paraStyle = None if tr.get('style'): st = copy.deepcopy(self.styles.table_styles[tr.get('style')]) for si in range(len(st._cmds)): s = list(st._cmds[si]) s[1] = (s[1][0],posy) s[2] = (s[2][0],posy) st._cmds[si] = tuple(s) styles.append(st) if tr.get('paraStyle'): paraStyle = self.styles.styles[tr.get('paraStyle')] data2 = [] posx = 0 for td in utils._child_get(tr, self,'td'): if td.get('style'): st = copy.deepcopy(self.styles.table_styles[td.get('style')]) for s in st._cmds: s[1][1] = posy s[2][1] = posy s[1][0] = posx s[2][0] = posx styles.append(st) if td.get('paraStyle'): # TODO: merge styles paraStyle = self.styles.styles[td.get('paraStyle')] posx += 1 flow = [] for n in utils._child_get(td, self): if n.tag == etree.Comment: n.text = '' continue fl = self._flowable(n, extra_style=paraStyle) if isinstance(fl,list): flow += fl else: flow.append( fl ) if not len(flow): flow = self._textual(td) data2.append( flow ) if len(data2)>length: length=len(data2) for ab in data: while len(ab)<length: ab.append('') while len(data2)<length: data2.append('') data.append( data2 ) posy += 1 if node.get('colWidths'): assert length == len(node.get('colWidths').split(',')) colwidths = [utils.unit_get(f.strip()) for f in node.get('colWidths').split(',')] if node.get('rowHeights'): rowheights = [utils.unit_get(f.strip()) for f in node.get('rowHeights').split(',')] if len(rowheights) == 1: rowheights = rowheights[0] table = platypus.LongTable(data = data, colWidths=colwidths, rowHeights=rowheights, **(utils.attr_get(node, ['splitByRow'] ,{'repeatRows':'int','repeatCols':'int'}))) if node.get('style'): table.setStyle(self.styles.table_styles[node.get('style')]) for s in styles: table.setStyle(s) return table
def _flowable(self, node, extra_style=None): if node.tag=='pto': return self._pto(node) if node.tag=='para': style = self.styles.para_style_get(node) if extra_style: style.__dict__.update(extra_style) result = [] for i in self._textual(node).split('\n'): result.append(platypus.Paragraph(i, style, **(utils.attr_get(node, [], {'bulletText':'str'})))) return result elif node.tag=='barCode': try: from reportlab.graphics.barcode import code128 from reportlab.graphics.barcode import code39 from reportlab.graphics.barcode import code93 from reportlab.graphics.barcode import common from reportlab.graphics.barcode import fourstate from reportlab.graphics.barcode import usps from reportlab.graphics.barcode import createBarcodeDrawing except ImportError: _logger.warning("Cannot use barcode renderers:", exc_info=True) return None args = utils.attr_get(node, [], {'ratio':'float','xdim':'unit','height':'unit','checksum':'int','quiet':'int','width':'unit','stop':'bool','bearers':'int','barWidth':'float','barHeight':'float'}) codes = { 'codabar': lambda x: common.Codabar(x, **args), 'code11': lambda x: common.Code11(x, **args), 'code128': lambda x: code128.Code128(str(x), **args), 'standard39': lambda x: code39.Standard39(str(x), **args), 'standard93': lambda x: code93.Standard93(str(x), **args), 'i2of5': lambda x: common.I2of5(x, **args), 'extended39': lambda x: code39.Extended39(str(x), **args), 'extended93': lambda x: code93.Extended93(str(x), **args), 'msi': lambda x: common.MSI(x, **args), 'fim': lambda x: usps.FIM(x, **args), 'postnet': lambda x: usps.POSTNET(x, **args), 'ean13': lambda x: createBarcodeDrawing('EAN13', value=str(x), **args), 'qrcode': lambda x: createBarcodeDrawing('QR', value=x, **args), } code = 'code128' if node.get('code'): code = node.get('code').lower() return codes[code](self._textual(node)) elif node.tag=='name': self.styles.names[ node.get('id')] = node.get('value') return None elif node.tag=='xpre': style = self.styles.para_style_get(node) return platypus.XPreformatted(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str','dedent':'int','frags':'int'}))) elif node.tag=='pre': style = self.styles.para_style_get(node) return platypus.Preformatted(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str','dedent':'int'}))) elif node.tag=='illustration': return self._illustration(node) elif node.tag=='blockTable': return self._table(node) elif node.tag=='title': styles = reportlab.lib.styles.getSampleStyleSheet() style = styles['Title'] return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str'}))) elif re.match('^h([1-9]+[0-9]*)$', (node.tag or '')): styles = reportlab.lib.styles.getSampleStyleSheet() style = styles['Heading'+str(node.tag[1:])] return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str'}))) elif node.tag=='image': image_data = False if not node.get('file'): if node.get('name'): if node.get('name') in self.doc.images: _logger.debug("Image %s read ", node.get('name')) image_data = self.doc.images[node.get('name')].read() else: _logger.warning("Image %s not defined", node.get('name')) return False else: import base64 newtext = node.text if self.localcontext: newtext = utils._process_text(self, node.text or '') image_data = base64.decodestring(newtext) if not image_data: _logger.debug("No inline image data") return False image = StringIO(image_data) else: _logger.debug("Image get from file %s", node.get('file')) image = _open_image(node.get('file'), path=self.doc.path) return platypus.Image(image, mask=(250,255,250,255,250,255), **(utils.attr_get(node, ['width','height']))) elif node.tag=='spacer': if node.get('width'): width = utils.unit_get(node.get('width')) else: width = utils.unit_get('1cm') length = utils.unit_get(node.get('length')) return platypus.Spacer(width=width, height=length) elif node.tag=='section': return self.render(node) elif node.tag == 'pageNumberReset': return PageReset() elif node.tag in ('pageBreak', 'nextPage'): return platypus.PageBreak() elif node.tag=='condPageBreak': return platypus.CondPageBreak(**(utils.attr_get(node, ['height']))) elif node.tag=='setNextTemplate': return platypus.NextPageTemplate(str(node.get('name'))) elif node.tag=='nextFrame': return platypus.CondPageBreak(1000) # TODO: change the 1000 ! elif node.tag == 'setNextFrame': from reportlab.platypus.doctemplate import NextFrameFlowable return NextFrameFlowable(str(node.get('name'))) elif node.tag == 'currentFrame': from reportlab.platypus.doctemplate import CurrentFrameFlowable return CurrentFrameFlowable(str(node.get('name'))) elif node.tag == 'frameEnd': return EndFrameFlowable() elif node.tag == 'hr': width_hr=node.get('width') or '100%' color_hr=node.get('color') or 'black' thickness_hr=node.get('thickness') or 1 lineCap_hr=node.get('lineCap') or 'round' return platypus.flowables.HRFlowable(width=width_hr,color=color.get(color_hr),thickness=float(thickness_hr),lineCap=str(lineCap_hr)) else: sys.stderr.write('Warning: flowable not yet implemented: %s !\n' % (node.tag,)) return None
def _drawCenteredString(self, node): v = utils.attr_get(node, ["x", "y"]) text = self._textual(node, **v) text = utils.xml2str(text) self.canvas.drawCentredString(text=text, **v)
def __init__(self, localcontext, out, node, doc, images=None, path=".", title=None): if images is None: images = {} if not localcontext: localcontext = {"internal_header": True} self.localcontext = localcontext self.images = images self.path = path self.title = title pagesize_map = {"a4": A4, "us_letter": letter} pageSize = (841.8897637795275, 595.275590551181) self.doc_tmpl = TinyDocTemplate( out, pagesize=pageSize, **utils.attr_get( node, ["leftMargin", "rightMargin", "topMargin", "bottomMargin"], {"allowSplitting": "int", "showBoundary": "bool", "rotation": "int", "title": "str", "author": "str"}, ) ) self.page_templates = [] self.styles = doc.styles self.doc = doc self.image = [] pts = node.findall("pageTemplate") for pt in pts: frames = [] for frame_el in pt.findall("frame"): frame = platypus.Frame( **( utils.attr_get( frame_el, [ "x1", "y1", "width", "height", "leftPadding", "rightPadding", "bottomPadding", "topPadding", ], {"id": "str", "showBoundary": "bool"}, ) ) ) if utils.attr_get(frame_el, ["last"]): frame.lastFrame = True frames.append(frame) try: gr = pt.findall("pageGraphics") or pt[1].findall("pageGraphics") except Exception: # FIXME: be even more specific, perhaps? gr = "" if len(gr): # self.image=[ n for n in utils._child_get(gr[0], self) if n.tag=='image' or not self.localcontext] drw = _rml_draw(self.localcontext, gr[0], self.doc, images=images, path=self.path, title=self.title) self.page_templates.append( platypus.PageTemplate(frames=frames, onPage=drw.render, **utils.attr_get(pt, [], {"id": "str"})) ) else: drw = _rml_draw(self.localcontext, node, self.doc, title=self.title) self.page_templates.append( platypus.PageTemplate(frames=frames, onPage=drw.render, **utils.attr_get(pt, [], {"id": "str"})) ) self.doc_tmpl.addPageTemplates(self.page_templates)
def _drawRightString(self, node): v = utils.attr_get(node, ['x','y']) text=self._textual(node, **v) text = utils.xml2str(text) self.canvas.drawRightString(text=text, **v)
def _flowable(self, node, extra_style=None): if node.tag == "pto": return self._pto(node) if node.tag == "para": style = self.styles.para_style_get(node) if extra_style: style.__dict__.update(extra_style) result = [] for i in self._textual(node).split("\n"): result.append(platypus.Paragraph(i, style, **(utils.attr_get(node, [], {"bulletText": "str"})))) return result elif node.tag == "barCode": try: from openerp.reportlab.graphics.barcode import code128 from openerp.reportlab.graphics.barcode import code39 from openerp.reportlab.graphics.barcode import code93 from openerp.reportlab.graphics.barcode import common from openerp.reportlab.graphics.barcode import fourstate from openerp.reportlab.graphics.barcode import usps from openerp.reportlab.graphics.barcode import createBarcodeDrawing except ImportError: _logger.warning("Cannot use barcode renderers:", exc_info=True) return None args = utils.attr_get( node, [], { "ratio": "float", "xdim": "unit", "height": "unit", "checksum": "int", "quiet": "int", "width": "unit", "stop": "bool", "bearers": "int", "barWidth": "float", "barHeight": "float", }, ) codes = { "codabar": lambda x: common.Codabar(x, **args), "code11": lambda x: common.Code11(x, **args), "code128": lambda x: code128.Code128(str(x), **args), "standard39": lambda x: code39.Standard39(str(x), **args), "standard93": lambda x: code93.Standard93(str(x), **args), "i2of5": lambda x: common.I2of5(x, **args), "extended39": lambda x: code39.Extended39(str(x), **args), "extended93": lambda x: code93.Extended93(str(x), **args), "msi": lambda x: common.MSI(x, **args), "fim": lambda x: usps.FIM(x, **args), "postnet": lambda x: usps.POSTNET(x, **args), "ean13": lambda x: createBarcodeDrawing("EAN13", value=str(x), **args), "qrcode": lambda x: createBarcodeDrawing("QR", value=x, **args), } code = "code128" if node.get("code"): code = node.get("code").lower() return codes[code](self._textual(node)) elif node.tag == "name": self.styles.names[node.get("id")] = node.get("value") return None elif node.tag == "xpre": style = self.styles.para_style_get(node) return platypus.XPreformatted( self._textual(node), style, **(utils.attr_get(node, [], {"bulletText": "str", "dedent": "int", "frags": "int"})) ) elif node.tag == "pre": style = self.styles.para_style_get(node) return platypus.Preformatted( self._textual(node), style, **(utils.attr_get(node, [], {"bulletText": "str", "dedent": "int"})) ) elif node.tag == "illustration": return self._illustration(node) elif node.tag == "blockTable": return self._table(node) elif node.tag == "title": styles = reportlab.lib.styles.getSampleStyleSheet() style = styles["Title"] return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {"bulletText": "str"}))) elif re.match("^h([1-9]+[0-9]*)$", (node.tag or "")): styles = reportlab.lib.styles.getSampleStyleSheet() style = styles["Heading" + str(node.tag[1:])] return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {"bulletText": "str"}))) elif node.tag == "image": image_data = False if not node.get("file"): if node.get("name"): if node.get("name") in self.doc.images: _logger.debug("Image %s read ", node.get("name")) image_data = self.doc.images[node.get("name")].read() else: _logger.warning("Image %s not defined", node.get("name")) return False else: import base64 newtext = node.text if self.localcontext: newtext = utils._process_text(self, node.text or "") image_data = base64.decodestring(newtext) if not image_data: _logger.debug("No inline image data") return False image = StringIO(image_data) else: _logger.debug("Image get from file %s", node.get("file")) image = _open_image(node.get("file"), path=self.doc.path) return platypus.Image( image, mask=(250, 255, 250, 255, 250, 255), **(utils.attr_get(node, ["width", "height"])) ) elif node.tag == "spacer": if node.get("width"): width = utils.unit_get(node.get("width")) else: width = utils.unit_get("1cm") length = utils.unit_get(node.get("length")) return platypus.Spacer(width=width, height=length) elif node.tag == "section": return self.render(node) elif node.tag == "pageNumberReset": return PageReset() elif node.tag in ("pageBreak", "nextPage"): return platypus.PageBreak() elif node.tag == "condPageBreak": return platypus.CondPageBreak(**(utils.attr_get(node, ["height"]))) elif node.tag == "setNextTemplate": return platypus.NextPageTemplate(str(node.get("name"))) elif node.tag == "nextFrame": return platypus.CondPageBreak(1000) # TODO: change the 1000 ! elif node.tag == "setNextFrame": from openerp.reportlab.platypus.doctemplate import NextFrameFlowable return NextFrameFlowable(str(node.get("name"))) elif node.tag == "currentFrame": from openerp.reportlab.platypus.doctemplate import CurrentFrameFlowable return CurrentFrameFlowable(str(node.get("name"))) elif node.tag == "frameEnd": return EndFrameFlowable() elif node.tag == "hr": width_hr = node.get("width") or "100%" color_hr = node.get("color") or "black" thickness_hr = node.get("thickness") or 1 lineCap_hr = node.get("lineCap") or "round" return platypus.flowables.HRFlowable( width=width_hr, color=color.get(color_hr), thickness=float(thickness_hr), lineCap=str(lineCap_hr) ) else: sys.stderr.write("Warning: flowable not yet implemented: %s !\n" % (node.tag,)) return None