def __init__(self, out, node, doc): if not node.hasAttribute('pageSize'): page_size = (utils.unit_get('21cm'), utils.unit_get('29.7cm')) else: ps = map(lambda x: x.strip(), node.getAttribute('pageSize') \ .replace(')', '') \ .replace('(', '') \ .split(', ')) page_size = (utils.unit_get(ps[0]), utils.unit_get(ps[1])) self.doc_tmpl = platypus.BaseDocTemplate(out, pagesize=page_size, **utils.attr_get(node, ['leftMargin', 'rightMargin', 'topMargin', 'bottomMargin'], {'allowSplitting': 'int', 'showBoundary': 'bool', 'title': 'str', 'author': 'str'})) self.page_templates = [] self.styles = doc.styles self.doc = doc pts = node.getElementsByTagName('pageTemplate') for pt in pts: frames = [] for frame_el in pt.getElementsByTagName('frame'): frame = platypus.Frame(**(utils.attr_get(frame_el, ['x1', 'y1', 'width', 'height', 'leftPadding', 'rightPadding', 'bottomPadding', 'topPadding'], {'id': 'text', 'showBoundary': 'bool'}))) frames.append(frame) gr = pt.getElementsByTagName('pageGraphics') if len(gr): drw = Draw(gr[0], self.doc) self.page_templates.append(platypus.PageTemplate(frames=frames, onPage=drw.render, **utils.attr_get(pt, [], {'id': 'str'}))) else: self.page_templates.append(platypus.PageTemplate(frames=frames, **utils.attr_get(pt, [], {'id': 'str'}))) self.doc_tmpl.addPageTemplates(self.page_templates)
def _line_mode(self, node): ljoin = {'round': 1, 'mitered': 0, 'bevelled': 2} lcap = {'default': 0, 'round': 1, 'square': 2} if node.hasAttribute('width'): width = utils.unit_get(node.getAttribute('width')) self.canvas.setLineWidth(width) if node.hasAttribute('join'): self.canvas.setLineJoin(ljoin[node.getAttribute('join')]) if node.hasAttribute('cap'): self.canvas.setLineCap(lcap[node.getAttribute('cap')]) if node.hasAttribute('miterLimit'): dash = utils.unit_get(node.getAttribute('miterLimit')) self.canvas.setDash(dash) if node.hasAttribute('dash'): dashes = node.getAttribute('dash').split(', ') for x in range(len(dashes)): dashes[x] = utils.unit_get(dashes[x]) self.canvas.setDash(node.getAttribute('dash').split(', '))
def _path(self, node): self.path = self.canvas.beginPath() self.path.moveTo(**utils.attr_get(node, ['x', 'y'])) for child_node in node.childNodes: if child_node.nodeType == node.ELEMENT_NODE: if child_node.localName == 'moveto': vals = utils.text_get(child_node).split() self.path.moveTo(utils.unit_get(vals[0]), utils.unit_get(vals[1])) elif child_node.localName == 'curvesto': vals = utils.text_get(child_node).split() while len(vals) > 5: pos = [] while len(pos) < 6: pos.append(utils.unit_get(vals.pop(0))) self.path.curveTo(*pos) elif (child_node.nodeType == node.TEXT_NODE): # Not sure if I must merge all TEXT_NODE ? data = child_node.data.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.hasAttribute('close')) or \ utils.bool_get(node.getAttribute('close')): self.path.close() self.canvas.drawPath(self.path, **utils.attr_get(node, [], {'fill': 'bool', 'stroke': 'bool'}))
def _translate(self, node): dx = 0 dy = 0 if node.hasAttribute('dx'): dx = utils.unit_get(node.getAttribute('dx')) if node.hasAttribute('dy'): dy = utils.unit_get(node.getAttribute('dy')) self.canvas.translate(dx, dy)
def _ellipse(self, node): x1 = utils.unit_get(node.getAttribute('x')) x2 = utils.unit_get(node.getAttribute('width')) y1 = utils.unit_get(node.getAttribute('y')) y2 = utils.unit_get(node.getAttribute('height')) self.canvas.ellipse(x1, y1, x2, y2, **utils.attr_get(node, [], {'fill': 'bool', 'stroke': 'bool'}))
def _table(self, node): length = 0 colwidths = None rowheights = None horizonal_align = None vertical_align = None data = [] for tr in _child_get(node, 'tr'): data2 = [] for td in _child_get(tr, 'td'): flow = [] for n in td.childNodes: if n.nodeType == node.ELEMENT_NODE: flow.append(self._flowable(n)) 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) if not data: raise ParserError("Empty Table") if node.hasAttribute('colWidths'): colwidths = [utils.unit_get(f.strip()) for f in node.getAttribute('colWidths').split(', ')] if len(colwidths) == 1 and length > 1: colwidth = colwidths[0] colwidths = [colwidth for x in xrange(1, length + 1)] if node.hasAttribute('rowHeights'): rowheights = [utils.unit_get(f.strip()) for f in node.getAttribute('rowHeights').split(', ')] if len(rowheights) == 1 and len(data) > 1: rowheight = rowheights[0] rowheights = [rowheight for x in xrange(1, len(data) + 1)] if node.hasAttribute("hAlign"): horizonal_align = node.getAttribute('hAlign') if node.hasAttribute("vAlign"): vertical_align = node.getAttribute('vAlign') table = platypus.Table(data=data, colWidths=colwidths, rowHeights=rowheights, hAlign=horizonal_align, vAlign=vertical_align, **(utils.attr_get(node, ['splitByRow'], {'repeatRows': 'int', 'repeatCols': 'int'}))) if node.hasAttribute('style'): table.setStyle(self.styles.table_styles[node.getAttribute('style')]) return table
def render(self, node): tags = { 'drawCentredString': self._draw_centred_string, 'drawCenteredString': self._draw_centred_string, 'drawRightString': self._draw_right_string, 'drawString': self._draw_string, 'rect': self._rect, 'ellipse': self._ellipse, 'lines': self._lines, 'grid': self._grid, 'curves': self._curves, 'fill': lambda node: self.canvas.setFillColor(color.get(node.getAttribute('color'))), 'stroke': lambda node: self.canvas.setStrokeColor(color.get(node.getAttribute('color'))), 'setFont': lambda node: self.canvas.setFont(node.getAttribute('name'), utils.unit_get(node.getAttribute('size'))), 'place': self._place, 'circle': self._circle, 'lineMode': self._line_mode, 'path': self._path, 'rotate': lambda node: self.canvas.rotate(float(node.getAttribute('degrees'))), 'translate': self._translate, 'image': self._image} for nd in node.childNodes: if nd.nodeType == nd.ELEMENT_NODE: for tag in tags: if nd.localName == tag: tags[tag](nd) break
def _lines(self, node): line_str = utils.text_get(node).split() lines = [] while len(line_str) > 3: lines.append([utils.unit_get(l) for l in line_str[0:4]]) line_str = line_str[4:] self.canvas.lines(lines)
def __init__(self, node, styles, value, encoding): Flowable.__init__(self) self.node = node self.styles = styles self.value = value self.encoding = encoding self.xpos = utils.unit_get(node.getAttribute('x')) self.ypos = utils.unit_get(node.getAttribute('y')) self.width = utils.unit_get(node.getAttribute('width')) self.height = utils.unit_get(node.getAttribute('height')) self.code_name = node.getAttribute('code') self.codes = getCodes() from trml2pdf.parser import ParserError try: self.codes[self.code_name] except KeyError, msg: raise ParserError("Unknown barcode name '%s'." % self.code_name)
def _rect(self, node): if node.hasAttribute('round'): kwargs = utils.attr_get(node, ['x', 'y', 'width', 'height'], {'fill': 'bool', 'stroke': 'bool'}) radius = utils.unit_get(node.getAttribute('round')) self.canvas.roundRect(radius=radius, **kwargs) else: self.canvas.rect(**utils.attr_get(node, ['x', 'y', 'width', 'height'], {'fill': 'bool', 'stroke': 'bool'}))
def _image(self, node): from trml2pdf import utils img = ImageReader(str(node.getAttribute('file')), self.doc.context) (sx, sy) = img.getSize() args = {} for tag in ('width', 'height', 'x', 'y'): if node.hasAttribute(tag): args[tag] = utils.unit_get(node.getAttribute(tag)) if ('width' in args) and (not 'height' in args): args['height'] = sy * args['width'] / sx elif ('height' in args) and (not 'width' in args): args['width'] = sx * args['height'] / sy elif ('width' in args) and ('height' in args): if (float(args['width']) / args['height']) > (float(sx) > sy): args['width'] = sx * args['height'] / sy else: args['height'] = sy * args['width'] / sx self.canvas.drawImage(img, **args)
def _table_style_get(self, style_node): styles = [] for node in style_node.childNodes: if node.nodeType == node.ELEMENT_NODE: start = utils.tuple_int_get(node, 'start', (0, 0)) stop = utils.tuple_int_get(node, 'stop', (-1, -1)) if node.localName == 'blockValign': styles.append(('VALIGN', start, stop, str(node.getAttribute('value')))) elif node.localName == 'blockFont': styles.append(('FONT', start, stop, str(node.getAttribute('name')))) elif node.localName == 'blockTextColor': styles.append(('TEXTCOLOR', start, stop, color.get(str(node.getAttribute('colorName'))))) elif node.localName == 'blockLeading': styles.append(('LEADING', start, stop, utils.unit_get(node.getAttribute('length')))) elif node.localName == 'blockAlignment': styles.append(('ALIGNMENT', start, stop, str(node.getAttribute('value')))) elif node.localName == 'blockLeftPadding': styles.append(('LEFTPADDING', start, stop, utils.unit_get(node.getAttribute('length')))) elif node.localName == 'blockRightPadding': styles.append(('RIGHTPADDING', start, stop, utils.unit_get(node.getAttribute('length')))) elif node.localName == 'blockTopPadding': styles.append(('TOPPADDING', start, stop, utils.unit_get(node.getAttribute('length')))) elif node.localName == 'blockBottomPadding': styles.append(('BOTTOMPADDING', start, stop, utils.unit_get(node.getAttribute('length')))) elif node.localName == 'blockBackground': styles.append(('BACKGROUND', start, stop, color.get(node.getAttribute('colorName')))) if node.hasAttribute('size'): styles.append(('FONTSIZE', start, stop, utils.unit_get(node.getAttribute('size')))) elif node.localName == 'lineStyle': kind = node.getAttribute('kind') kind_list = ['GRID', 'BOX', 'OUTLINE', 'INNERGRID', 'LINEBELOW', 'LINEABOVE', 'LINEBEFORE', 'LINEAFTER'] assert kind in kind_list thick = 1 if node.hasAttribute('thickness'): thick = float(node.getAttribute('thickness')) styles.append((kind, start, stop, thick, color.get(node.getAttribute('colorName')))) return platypus.tables.TableStyle(styles)
def _para_style_update(self, style, node): for attr in ['textColor', 'backColor', 'bulletColor']: if node.hasAttribute(attr): style.__dict__[attr] = color.get(node.getAttribute(attr)) for attr in ['fontName', 'bulletFontName', 'bulletText']: if node.hasAttribute(attr): style.__dict__[attr] = node.getAttribute(attr) for attr in ['fontSize', 'leftIndent', 'rightIndent', 'spaceBefore', 'spaceAfter', 'firstLineIndent', 'bulletIndent', 'bulletFontSize', 'leading']: if node.hasAttribute(attr): style.__dict__[attr] = utils.unit_get(node.getAttribute(attr)) if node.hasAttribute('alignment'): align = { 'right': reportlab.lib.enums.TA_RIGHT, 'center': reportlab.lib.enums.TA_CENTER, 'justify': reportlab.lib.enums.TA_JUSTIFY} style.alignment = align.get(node.getAttribute('alignment').lower(), reportlab.lib.enums.TA_LEFT) return style
def _image(self, node): import urllib from reportlab.lib.utils import ImageReader u = urllib.urlopen(str(node.getAttribute('file'))) s = StringIO.StringIO() s.write(u.read()) s.seek(0) img = ImageReader(s) (sx, sy) = img.getSize() args = {} for tag in ('width', 'height', 'x', 'y'): if node.hasAttribute(tag): args[tag] = utils.unit_get(node.getAttribute(tag)) if ('width' in args) and (not 'height' in args): args['height'] = sy * args['width'] / sx elif ('height' in args) and (not 'width' in args): args['width'] = sx * args['height'] / sy elif ('width' in args) and ('height' in args): if (float(args['width']) / args['height']) > (float(sx) > sy): args['width'] = sx * args['height'] / sy else: args['height'] = sy * args['width'] / sx self.canvas.drawImage(img, **args)
def _curves(self, node): line_str = utils.text_get(node).split() while len(line_str) > 7: self.canvas.bezier(*[utils.unit_get(l) for l in line_str[0:8]]) line_str = line_str[8:]
def _flowable(self, node): if node.localName == 'para': style = self.styles.para_style_get(node) return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'}))) elif node.localName == "p": # support html <p> for paragraph tags style = self.styles.para_style_get(node) return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'}))) elif node.localName == 'name': self.styles.names[node.getAttribute('id')] = node.getAttribute('value') return None elif node.localName == '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.localName == '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.localName == 'illustration': return self._illustration(node) elif node.localName == 'blockTable': return self._table(node) elif node.localName == 'title': styles = reportlab.lib.styles.getSampleStyleSheet() # FIXME: better interface for accessing styles see TODO style = self.styles.styles.get('style.Title', styles['Title']) return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'}))) elif node.localName == 'h1': styles = reportlab.lib.styles.getSampleStyleSheet() # although not defined in spec, we assume same as "title" see RML spec style = self.styles.styles.get('style.h1', styles['Heading1']) return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'}))) elif node.localName == 'h2': styles = reportlab.lib.styles.getSampleStyleSheet() # although not defined in spec, we assume same as "title" see RML spec style = self.styles.styles.get('style.h2', styles['Heading2']) return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'}))) elif node.localName == 'h3': styles = reportlab.lib.styles.getSampleStyleSheet() # although not defined in spec, we assume same as "title" see RML spec style = self.styles.styles.get('style.h2', styles['Heading3']) return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText': 'str'}))) elif node.localName == 'image': return platypus.Image(node.getAttribute('file'), mask=(250, 255, 250, 255, 250, 255), **(utils.attr_get(node, ['width', 'height']))) elif node.localName == 'spacer': if node.hasAttribute('width'): width = utils.unit_get(node.getAttribute('width')) else: width = utils.unit_get('1cm') length = utils.unit_get(node.getAttribute('length')) return platypus.Spacer(width=width, height=length) elif node.localName == 'pageBreak': return platypus.PageBreak() elif node.localName == 'condPageBreak': return platypus.CondPageBreak(**(utils.attr_get(node, ['height']))) elif node.localName == 'setNextTemplate': return platypus.NextPageTemplate(str(node.getAttribute('name'))) elif node.localName == 'nextFrame': return platypus.CondPageBreak(1000) # TODO: change the 1000 ! elif node.localName=='keepInFrame': substory = [] subnode = node.firstChild while subnode: if node.nodeType == node.ELEMENT_NODE: subflow = self._flowable(subnode) if subflow: substory.append(subflow) subnode = subnode.nextSibling return platypus.KeepInFrame(content=substory, **(utils.attr_get(node, ['maxWidth','maxHeight'], {'name':'str','mode':'str'}))) elif node.localName is None: return None else: raise ParserError('%s Flowable Not Implemented' % node.localName) return None
def __init__(self, node, styles): self.node = node self.styles = styles self.width = utils.unit_get(node.getAttribute('width')) self.height = utils.unit_get(node.getAttribute('height'))
def _grid(self, node): xs = node.getAttribute('xs').split(', ') ys = node.getAttribute('ys').split(', ') xlist = [utils.unit_get(s) for s in xs] ylist = [utils.unit_get(s) for s in ys] self.canvas.grid(xlist, ylist)
def _circle(self, node): self.canvas.circle(x_cen=utils.unit_get(node.getAttribute('x')), y_cen=utils.unit_get(node.getAttribute('y')), r=utils.unit_get(node.getAttribute('radius')), **utils.attr_get(node, [], {'fill': 'bool', 'stroke': 'bool'}))