Ejemplo n.º 1
0
    def render(self, node):
        tags = {
            'drawCentredString': self._drawCenteredString,
            'drawRightString': self._drawRightString,
            'drawString': self._drawString,
            'rect': self._rect,
            'ellipse': self._ellipse,
            'lines': self._lines,
            'grid': self._grid,
            'curves': self._curves,
            'fill': lambda node: self.canvas.setFillColor(
                color.get(
                    node.get('color'))),
            'stroke': lambda node: self.canvas.setStrokeColor(
                color.get(
                    node.get('color'))),
            'setFont': self.setFont,
            'place': self._place,
            'circle': self._circle,
            'lineMode': self._line_mode,
            'path': self._path,
            'rotate': lambda node: self.canvas.rotate(
                float(
                    node.get('degrees'))),
            'translate': self._translate,
            'image': self._image,
        }

        for n in utils._child_get(node, self):
            if n.tag in tags:
                tags[n.tag](n)
Ejemplo n.º 2
0
 def _table_style_get(self, style_node):
     styles = []
     for node in style_node:
         start = utils.tuple_int_get(node, 'start', (0, 0))
         stop = utils.tuple_int_get(node, 'stop', (-1, -1))
         if node.tag == 'blockValign':
             styles.append(('VALIGN', start, stop, str(node.get('value'))))
         elif node.tag == 'blockFont':
             styles.append(('FONT', start, stop, str(node.get('name'))))
         elif node.tag == 'blockTextColor':
             styles.append(('TEXTCOLOR', start, stop, color.get(
                 str(node.get('colorName')))))
         elif node.tag == 'blockLeading':
             styles.append(('LEADING', start, stop, utils.unit_get(
                 node.get('length'))))
         elif node.tag == 'blockAlignment':
             styles.append(
                 ('ALIGNMENT', start, stop, str(node.get('value'))))
         elif node.tag == 'blockSpan':
             styles.append(('SPAN', start, stop))
         elif node.tag == 'blockLeftPadding':
             styles.append(
                 ('LEFTPADDING', start, stop,
                     utils.unit_get(node.get('length'))))
         elif node.tag == 'blockRightPadding':
             styles.append(
                 ('RIGHTPADDING', start, stop,
                     utils.unit_get(node.get('length'))))
         elif node.tag == 'blockTopPadding':
             styles.append(
                 ('TOPPADDING', start, stop,
                     utils.unit_get(node.get('length'))))
         elif node.tag == 'blockBottomPadding':
             styles.append(
                 ('BOTTOMPADDING', start, stop,
                     utils.unit_get(node.get('length'))))
         elif node.tag == 'blockBackground':
             styles.append(
                 ('BACKGROUND', start, stop,
                     color.get(node.get('colorName'))))
         if node.get('size'):
             styles.append(
                 ('FONTSIZE', start, stop,
                     utils.unit_get(node.get('size'))))
         elif node.tag == 'lineStyle':
             kind = node.get('kind')
             kind_list = [
                 'GRID', 'BOX', 'OUTLINE', 'INNERGRID',
                 'LINEBELOW', 'LINEABOVE', 'LINEBEFORE', 'LINEAFTER'
             ]
             assert kind in kind_list
             thick = 1
             if node.get('thickness'):
                 thick = float(node.get('thickness'))
             styles.append(
                 (kind, start, stop, thick, color.get(
                     node.get('colorName'))))
     return platypus.tables.TableStyle(styles)
Ejemplo n.º 3
0
 def _para_style_update(self, node):
     data = {}
     for attr in ["textColor", "backColor", "bulletColor", "borderColor"]:
         if node.get(attr):
             data[attr] = color.get(node.get(attr))
     for attr in ["fontName", "bulletFontName", "bulletText"]:
         if node.get(attr):
             data[attr] = node.get(attr)
     for attr in [
         "fontSize",
         "leftIndent",
         "rightIndent",
         "spaceBefore",
         "spaceAfter",
         "firstLineIndent",
         "bulletIndent",
         "bulletFontSize",
         "leading",
         "borderWidth",
         "borderPadding",
         "borderRadius",
     ]:
         if node.get(attr):
             data[attr] = utils.unit_get(node.get(attr))
     if node.get("alignment"):
         align = {
             "right": reportlab.lib.enums.TA_RIGHT,
             "center": reportlab.lib.enums.TA_CENTER,
             "justify": reportlab.lib.enums.TA_JUSTIFY,
         }
         data["alignment"] = align.get(node.get("alignment").lower(), reportlab.lib.enums.TA_LEFT)
     return data
Ejemplo n.º 4
0
 def _para_style_update(self, node):
     data = {}
     for attr in ['textColor', 'backColor', 'bulletColor', 'borderColor']:
         if node.get(attr):
             data[attr] = color.get(node.get(attr))
     for attr in ['fontName', 'bulletFontName', 'bulletText']:
         if node.get(attr):
             data[attr] = node.get(attr)
     for attr in [
             'fontSize', 'leftIndent', 'rightIndent', 'spaceBefore',
             'spaceAfter', 'firstLineIndent', 'bulletIndent',
             'bulletFontSize', 'leading', 'borderWidth', 'borderPadding',
             'borderRadius'
     ]:
         if node.get(attr):
             data[attr] = utils.unit_get(node.get(attr))
     if node.get('alignment'):
         align = {
             'right': reportlab.lib.enums.TA_RIGHT,
             'center': reportlab.lib.enums.TA_CENTER,
             'justify': reportlab.lib.enums.TA_JUSTIFY
         }
         data['alignment'] = align.get(
             node.get('alignment').lower(), reportlab.lib.enums.TA_LEFT)
     return data
Ejemplo n.º 5
0
 def _para_style_update(self, node):
     data = {}
     for attr in ['textColor', 'backColor', 'bulletColor', 'borderColor']:
         if node.get(attr):
             data[attr] = color.get(node.get(attr))
     for attr in ['fontName', 'bulletFontName', 'bulletText']:
         if node.get(attr):
             data[attr] = node.get(attr)
     for attr in [
         'fontSize', 'leftIndent', 'rightIndent',
         'spaceBefore', 'spaceAfter',
         'firstLineIndent', 'bulletIndent', 'bulletFontSize', 'leading',
         'borderWidth', 'borderPadding', 'borderRadius'
     ]:
         if node.get(attr):
             data[attr] = utils.unit_get(node.get(attr))
     if node.get('alignment'):
         align = {
             'right': reportlab.lib.enums.TA_RIGHT,
             'center': reportlab.lib.enums.TA_CENTER,
             'justify': reportlab.lib.enums.TA_JUSTIFY
         }
         data['alignment'] = align.get(
             node.get('alignment').lower(), reportlab.lib.enums.TA_LEFT)
     return data
Ejemplo n.º 6
0
 def _table_style_get(self, style_node):
     styles = []
     for node in style_node:
         start = utils.tuple_int_get(node, "start", (0, 0))
         stop = utils.tuple_int_get(node, "stop", (-1, -1))
         if node.tag == "blockValign":
             styles.append(("VALIGN", start, stop, str(node.get("value"))))
         elif node.tag == "blockFont":
             styles.append(("FONT", start, stop, str(node.get("name"))))
         elif node.tag == "blockTextColor":
             styles.append(("TEXTCOLOR", start, stop, color.get(str(node.get("colorName")))))
         elif node.tag == "blockLeading":
             styles.append(("LEADING", start, stop, utils.unit_get(node.get("length"))))
         elif node.tag == "blockAlignment":
             styles.append(("ALIGNMENT", start, stop, str(node.get("value"))))
         elif node.tag == "blockSpan":
             styles.append(("SPAN", start, stop))
         elif node.tag == "blockLeftPadding":
             styles.append(("LEFTPADDING", start, stop, utils.unit_get(node.get("length"))))
         elif node.tag == "blockRightPadding":
             styles.append(("RIGHTPADDING", start, stop, utils.unit_get(node.get("length"))))
         elif node.tag == "blockTopPadding":
             styles.append(("TOPPADDING", start, stop, utils.unit_get(node.get("length"))))
         elif node.tag == "blockBottomPadding":
             styles.append(("BOTTOMPADDING", start, stop, utils.unit_get(node.get("length"))))
         elif node.tag == "blockBackground":
             styles.append(("BACKGROUND", start, stop, color.get(node.get("colorName"))))
         if node.get("size"):
             styles.append(("FONTSIZE", start, stop, utils.unit_get(node.get("size"))))
         elif node.tag == "lineStyle":
             kind = node.get("kind")
             kind_list = ["GRID", "BOX", "OUTLINE", "INNERGRID", "LINEBELOW", "LINEABOVE", "LINEBEFORE", "LINEAFTER"]
             assert kind in kind_list
             thick = 1
             if node.get("thickness"):
                 thick = float(node.get("thickness"))
             styles.append((kind, start, stop, thick, color.get(node.get("colorName"))))
     return platypus.tables.TableStyle(styles)
Ejemplo n.º 7
0
 def render(self, node):
     tags = {
         "drawCentredString": self._drawCenteredString,
         "drawRightString": self._drawRightString,
         "drawString": self._drawString,
         "rect": self._rect,
         "ellipse": self._ellipse,
         "lines": self._lines,
         "grid": self._grid,
         "curves": self._curves,
         "fill": lambda node: self.canvas.setFillColor(color.get(node.get("color"))),
         "stroke": lambda node: self.canvas.setStrokeColor(color.get(node.get("color"))),
         "setFont": self.setFont,
         "place": self._place,
         "circle": self._circle,
         "lineMode": self._line_mode,
         "path": self._path,
         "rotate": lambda node: self.canvas.rotate(float(node.get("degrees"))),
         "translate": self._translate,
         "image": self._image,
     }
     for n in utils._child_get(node, self):
         if n.tag in tags:
             tags[n.tag](n)
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
    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