def end(self, tag): curctx = super(PDFParseTarget, self).end(tag) parent = self.parent ss = self.req.pdf_styles if (isinstance(curctx, npdml.NPDMLPageContext) and isinstance(parent, npdml.NPDMLPageTemplateContext)): self._page_tpls[curctx['id']] = curctx elif (isinstance(curctx, npdml.NPDMLFrameContext) and isinstance(parent, npdml.NPDMLPageContext)): parent['frames'].append(curctx) elif isinstance(curctx, npdml.NPDMLParagraphContext): btext = None if curctx.is_numbered: btext = self.get_bullet(curctx) para = Paragraph(curctx.get_data(), ss[curctx.get('style', 'body')], bulletText=btext) if isinstance(parent, npdml.NPDMLCanvasContext): parent.canvas.add((curctx, para)) else: self.story.append(para) elif isinstance(curctx, npdml.NPDMLTableCellContext): para_style = 'body' if isinstance(parent, npdml.NPDMLTableHeaderContext): para_style = 'table_header' if 'width' in curctx: parent.widths.append(eval_length(curctx['width'])) else: parent.widths.append(None) para = Paragraph(curctx.get_data(), ss[curctx.get('style', para_style)]) colspan = 1 rowspan = 1 if 'colspan' in curctx: try: colspan = int(curctx['colspan']) except (TypeError, ValueError): pass if 'rowspan' in curctx: try: rowspan = int(curctx['rowspan']) except (TypeError, ValueError): pass para.colspan = colspan para.rowspan = rowspan parent.cells.append(para) if colspan > 1: parent.cells.extend([''] * (colspan - 1)) elif isinstance(curctx, npdml.NPDMLTableRowContext): parent.rows.append(curctx.cells) if isinstance(curctx, npdml.NPDMLTableHeaderContext): parent.has_header = True if len(parent.widths) < len(curctx.widths): parent.widths = curctx.widths elif isinstance(curctx, npdml.NPDMLTableContext): # FIXME: unhardcode spacing kwargs = { 'colWidths': curctx.widths, 'spaceBefore': 8 } if 'repeatRows' in curctx: try: kwargs['repeatRows'] = int(curctx['repeatRows']) except (TypeError, ValueError): pass if 'align' in curctx: value = curctx['align'].upper() if value in ('LEFT', 'RIGHT', 'CENTER'): kwargs['hAlign'] = value extra_style = [] rowspans = {} for rowidx, row in enumerate(curctx.rows): for colidx in list(rowspans): rowspans[colidx] -= 1 if rowspans[colidx] == 0: del rowspans[colidx] row.insert(colidx, '') for colidx, col in enumerate(row): if not isinstance(col, Paragraph): continue if col.colspan > 1 or col.rowspan > 1: extra_style.append(('SPAN', (colidx, rowidx), (colidx + col.colspan - 1, rowidx + col.rowspan - 1))) if col.rowspan > 1: # FIXME: proper backgrounds of spanned cells extra_style.append(('ROWBACKGROUNDS', (colidx, rowidx), (colidx + col.colspan - 1, rowidx + col.rowspan - 1), (colors.white,))) for idx in range(colidx, colidx + col.colspan): rowspans[idx] = col.rowspan - 1 table = Table(curctx.rows, **kwargs) table.setStyle(DefaultTableStyle(extra_style, has_header=curctx.has_header)) self.story.append(table) elif isinstance(curctx, npdml.NPDMLAnchorContext): curctx.setdefault('color', 'blue') markup = '<a %s>%s</a>' % (_attr_str(curctx), curctx.get_data()) parent.data.append(markup) elif isinstance(curctx, npdml.NPDMLBoldContext): markup = '<b>%s</b>' % (curctx.get_data(),) parent.data.append(markup) elif isinstance(curctx, npdml.NPDMLItalicContext): markup = '<i>%s</i>' % (curctx.get_data(),) parent.data.append(markup) elif isinstance(curctx, npdml.NPDMLUnderlineContext): markup = '<u>%s</u>' % (curctx.get_data(),) parent.data.append(markup) elif isinstance(curctx, npdml.NPDMLStrikethroughContext): markup = '<strike>%s</strike>' % (curctx.get_data(),) parent.data.append(markup) elif isinstance(curctx, npdml.NPDMLSuperscriptContext): markup = '<super>%s</super>' % (curctx.get_data(),) parent.data.append(markup) elif isinstance(curctx, npdml.NPDMLSubscriptContext): markup = '<sub>%s</sub>' % (curctx.get_data(),) parent.data.append(markup) elif isinstance(curctx, npdml.NPDMLFontContext): kwargs = {} for attr in ('name', 'size', 'color'): if attr in curctx: kwargs[attr] = curctx[attr] if len(kwargs): markup = '<font %s>%s</font>' % (_attr_str(kwargs), curctx.get_data()) parent.data.append(markup) else: parent.data.append(curctx.get_data()) elif isinstance(curctx, npdml.NPDMLImageContext): kwargs = {} src = urlparse.urlparse(curctx['src']) # TODO: Support http, https, and vfs URLs if src.scheme != 'file': raise NotImplementedError('Only "file://" URLs ' 'are implemented.') image = src.path if image.endswith('.svg') or image.endswith('.svgz'): image = svglib.svg2rlg(image) if isinstance(parent, npdml.NPDMLCanvasContext): if isinstance(image, shapes.Drawing): parent.canvas.add((curctx, image)) else: x = eval_length(curctx.get('x', 0)) y = eval_length(curctx.get('y', 0)) # FIXME: we fail to position image properly when # width/height are not given. width = eval_length(curctx.get('width', 0)) height = eval_length(curctx.get('height', 0)) image = shapes.Image(x, - y - height, width, height, image) parent.canvas.add(image) else: # TODO: support different scaling modes (kind=) if 'width' in curctx: kwargs['width'] = eval_length(curctx['width']) if 'height' in curctx: kwargs['height'] = eval_length(curctx['height']) if 'align' in curctx: value = curctx['align'].upper() if value in ('LEFT', 'RIGHT', 'CENTER'): kwargs['hAlign'] = value # TODO: vAlign if isinstance(image, shapes.Drawing): for k, v in kwargs.items(): setattr(image, k, v) self.story.append(image) else: self.story.append(Image(image, **kwargs)) elif isinstance(curctx, npdml.NPDMLTitleContext): if isinstance(parent, npdml.NPDMLPageContext): para = Paragraph(curctx.get_data(), ss[curctx.get('style', 'title')]) self.story.append(para) elif isinstance(parent, npdml.NPDMLMetadataContext): self._title = curctx.get_data() elif isinstance(parent, npdml.NPDMLSectionContext): text = curctx.get_data() para_text = text sect_id = self.get_section_id() dlevel = parent.depth btext = None if parent.is_numbered: btext = self.get_bullet(curctx) if parent.in_toc and dlevel > 0: para_text = '<a name="%s"/>%s' % (sect_id, text) outline = '%s%s' % ( '' if btext is None else btext + ' ', text) self.story.append(OutlineEntryFlowable(outline, sect_id, dlevel - 1)) para = Paragraph(para_text, ss[curctx.get('style', 'heading' + str(dlevel))], bulletText=btext) self.story.append(para) elif isinstance(curctx, npdml.NPDMLCanvasContext): self.story.append(curctx.canvas) # Process canvas-only elements if isinstance(parent, npdml.NPDMLCanvasContext): canvas = parent.canvas if isinstance(curctx, npdml.NPDMLLineContext): x1 = eval_length(curctx.pop('x1', 0)) y1 = eval_length(curctx.pop('y1', 0)) x2 = eval_length(curctx.pop('x2')) y2 = eval_length(curctx.pop('y2')) canvas.add(shapes.Line(x1, -y1, x2, -y2, **curctx)) elif isinstance(curctx, npdml.NPDMLRectangleContext): x = eval_length(curctx.pop('x', 0)) y = eval_length(curctx.pop('y', 0)) width = eval_length(curctx.pop('width')) height = eval_length(curctx.pop('height', width)) rx = eval_length(curctx.pop('rx', 0)) ry = eval_length(curctx.pop('ry', 0)) curctx.setdefault('fillColor', None) canvas.add(shapes.Rect(x, - y - height, width, height, rx, ry, **curctx)) elif isinstance(curctx, npdml.NPDMLLabelContext): x = eval_length(curctx.pop('x', 0)) y = eval_length(curctx.pop('y', 0)) curctx.setdefault('fontName', DEFAULT_FONT) canvas.add(shapes.String(x, -y, curctx.get_data(), **curctx)) elif isinstance(curctx, npdml.NPDMLCircleContext): cx = eval_length(curctx.pop('cx')) cy = eval_length(curctx.pop('cy')) radius = eval_length(curctx.pop('radius')) curctx.setdefault('fillColor', None) canvas.add(shapes.Circle(cx, -cy, radius, **curctx)) elif isinstance(curctx, npdml.NPDMLEllipseContext): cx = eval_length(curctx.pop('cx')) cy = eval_length(curctx.pop('cy')) rx = eval_length(curctx.pop('rx')) ry = eval_length(curctx.pop('ry')) curctx.setdefault('fillColor', None) canvas.add(shapes.Ellipse(cx, -cy, rx, ry, **curctx)) if isinstance(curctx, npdml.NPDMLBlock) and curctx._indenter: self.story.append(Indenter(-curctx._indenter.left, -curctx._indenter.right))