Package zephir :: Package utils :: Package trml2pdf :: Module trml2pdf
[hide private]
[frames] | no frames]

Source Code for Module zephir.utils.trml2pdf.trml2pdf

  1  #!/usr/bin/python 
  2  # -*- coding: UTF-8 -*- 
  3   
  4  # trml2pdf - An RML to PDF converter 
  5  # Copyright (C) 2003, Fabien Pinckaers, UCL, FSA 
  6  # Contributors 
  7  #     Richard Waid <richard@iopen.net> 
  8  # 
  9  # This library is free software; you can redistribute it and/or 
 10  # modify it under the terms of the GNU Lesser General Public 
 11  # License as published by the Free Software Foundation; either 
 12  # version 2.1 of the License, or (at your option) any later version. 
 13  # 
 14  # This library is distributed in the hope that it will be useful, 
 15  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 17  # Lesser General Public License for more details. 
 18  # 
 19  # You should have received a copy of the GNU Lesser General Public 
 20  # License along with this library; if not, write to the Free Software 
 21  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 22   
 23  import sys 
 24  # Eole: utilisation de cStringIO 
 25  import cStringIO as StringIO 
 26  import xml.dom.minidom 
 27  import copy 
 28  import locale 
 29   
 30  import reportlab 
 31  from reportlab.pdfgen import canvas 
 32  from reportlab import platypus 
 33   
 34  import utils 
 35  import color 
 36   
 37  # 
 38  # Change this to UTF-8 if you plan tu use Reportlab's UTF-8 support 
 39  # 
 40  try: 
 41      from zephir.config import charset 
 42      encoding = charset 
 43  except: 
 44      encoding = locale.getpreferredencoding() 
 45   
 46   
47 -def _child_get(node, childs):
48 clds = [] 49 for n in node.childNodes: 50 if (n.nodeType==n.ELEMENT_NODE) and (n.localName==childs): 51 clds.append(n) 52 return clds
53
54 -class _rml_styles(object):
55 - def __init__(self, nodes):
56 self.styles = {} 57 self.names = {} 58 self.table_styles = {} 59 for node in nodes: 60 for style in node.getElementsByTagName('blockTableStyle'): 61 self.table_styles[style.getAttribute('id')] = self._table_style_get(style) 62 for style in node.getElementsByTagName('paraStyle'): 63 self.styles[style.getAttribute('name')] = self._para_style_get(style) 64 for variable in node.getElementsByTagName('initialize'): 65 for name in variable.getElementsByTagName('name'): 66 self.names[ name.getAttribute('id')] = name.getAttribute('value')
67
68 - def _para_style_update(self, style, node):
69 for attr in ['textColor', 'backColor', 'bulletColor']: 70 if node.hasAttribute(attr): 71 style.__dict__[attr] = color.get(node.getAttribute(attr)) 72 for attr in ['fontName', 'bulletFontName', 'bulletText']: 73 if node.hasAttribute(attr): 74 style.__dict__[attr] = node.getAttribute(attr) 75 for attr in ['fontSize', 'leftIndent', 'rightIndent', 'spaceBefore', 'spaceAfter', 'firstLineIndent', 'bulletIndent', 'bulletFontSize', 'leading']: 76 if node.hasAttribute(attr): 77 style.__dict__[attr] = utils.unit_get(node.getAttribute(attr)) 78 if node.hasAttribute('alignment'): 79 align = { 80 'right':reportlab.lib.enums.TA_RIGHT, 81 'center':reportlab.lib.enums.TA_CENTER, 82 'justify':reportlab.lib.enums.TA_JUSTIFY 83 } 84 style.alignment = align.get(node.getAttribute('alignment').lower(), reportlab.lib.enums.TA_LEFT) 85 return style
86
87 - def _table_style_get(self, style_node):
88 styles = [] 89 for node in style_node.childNodes: 90 if node.nodeType==node.ELEMENT_NODE: 91 start = utils.tuple_int_get(node, 'start', (0,0) ) 92 stop = utils.tuple_int_get(node, 'stop', (-1,-1) ) 93 if node.localName=='blockValign': 94 styles.append(('VALIGN', start, stop, str(node.getAttribute('value')))) 95 elif node.localName=='blockFont': 96 styles.append(('FONT', start, stop, str(node.getAttribute('name')))) 97 elif node.localName=='blockTextColor': 98 styles.append(('TEXTCOLOR', start, stop, color.get(str(node.getAttribute('colorName'))))) 99 elif node.localName=='blockLeading': 100 styles.append(('LEADING', start, stop, utils.unit_get(node.getAttribute('length')))) 101 elif node.localName=='blockAlignment': 102 styles.append(('ALIGNMENT', start, stop, str(node.getAttribute('value')))) 103 elif node.localName=='blockLeftPadding': 104 styles.append(('LEFTPADDING', start, stop, utils.unit_get(node.getAttribute('length')))) 105 elif node.localName=='blockRightPadding': 106 styles.append(('RIGHTPADDING', start, stop, utils.unit_get(node.getAttribute('length')))) 107 elif node.localName=='blockTopPadding': 108 styles.append(('TOPPADDING', start, stop, utils.unit_get(node.getAttribute('length')))) 109 elif node.localName=='blockBottomPadding': 110 styles.append(('BOTTOMPADDING', start, stop, utils.unit_get(node.getAttribute('length')))) 111 elif node.localName=='blockBackground': 112 styles.append(('BACKGROUND', start, stop, color.get(node.getAttribute('colorName')))) 113 if node.hasAttribute('size'): 114 styles.append(('FONTSIZE', start, stop, utils.unit_get(node.getAttribute('size')))) 115 elif node.localName=='lineStyle': 116 kind = node.getAttribute('kind') 117 kind_list = [ 'GRID', 'BOX', 'OUTLINE', 'INNERGRID', 'LINEBELOW', 'LINEABOVE','LINEBEFORE', 'LINEAFTER' ] 118 assert kind in kind_list 119 thick = 1 120 if node.hasAttribute('thickness'): 121 thick = float(node.getAttribute('thickness')) 122 styles.append((kind, start, stop, thick, color.get(node.getAttribute('colorName')))) 123 return platypus.tables.TableStyle(styles)
124
125 - def _para_style_get(self, node):
126 styles = reportlab.lib.styles.getSampleStyleSheet() 127 style = copy.deepcopy(styles["Normal"]) 128 self._para_style_update(style, node) 129 return style
130
131 - def para_style_get(self, node):
132 style = False 133 if node.hasAttribute('style'): 134 if node.getAttribute('style') in self.styles: 135 style = copy.deepcopy(self.styles[node.getAttribute('style')]) 136 else: 137 sys.stderr.write('Warning: style not found, %s - setting default!\n' % (node.getAttribute('style'),) ) 138 if not style: 139 styles = reportlab.lib.styles.getSampleStyleSheet() 140 style = copy.deepcopy(styles['Normal']) 141 return self._para_style_update(style, node)
142
143 -class _rml_doc(object):
144 - def __init__(self, data):
145 self.dom = xml.dom.minidom.parseString(data) 146 self.filename = self.dom.documentElement.getAttribute('filename')
147
148 - def docinit(self, els):
149 from reportlab.lib.fonts import addMapping 150 from reportlab.pdfbase import pdfmetrics 151 from reportlab.pdfbase.ttfonts import TTFont 152 153 for node in els: 154 for font in node.getElementsByTagName('registerFont'): 155 name = font.getAttribute('fontName').encode('ascii') 156 fname = font.getAttribute('fontFile').encode('ascii') 157 pdfmetrics.registerFont(TTFont(name, fname )) 158 addMapping(name, 0, 0, name) #normal 159 addMapping(name, 0, 1, name) #italic 160 addMapping(name, 1, 0, name) #bold 161 addMapping(name, 1, 1, name) #italic and bold
162
163 - def render(self, out):
164 el = self.dom.documentElement.getElementsByTagName('docinit') 165 if el: 166 self.docinit(el) 167 168 el = self.dom.documentElement.getElementsByTagName('stylesheet') 169 self.styles = _rml_styles(el) 170 171 el = self.dom.documentElement.getElementsByTagName('template') 172 if len(el): 173 pt_obj = _rml_template(out, el[0], self) 174 pt_obj.render(self.dom.documentElement.getElementsByTagName('story')[0]) 175 else: 176 self.canvas = canvas.Canvas(out) 177 pd = self.dom.documentElement.getElementsByTagName('pageDrawing')[0] 178 pd_obj = _rml_canvas(self.canvas, None, self) 179 pd_obj.render(pd) 180 self.canvas.showPage() 181 self.canvas.save()
182
183 -class _rml_canvas(object):
184 - def __init__(self, canvas, doc_tmpl=None, doc=None):
185 self.canvas = canvas 186 self.styles = doc.styles 187 self.doc_tmpl = doc_tmpl 188 self.doc = doc
189
190 - def _textual(self, node):
191 rc = '' 192 for n in node.childNodes: 193 if n.nodeType == n.ELEMENT_NODE: 194 if n.localName=='pageNumber': 195 rc += str(self.canvas.getPageNumber()) 196 elif (n.nodeType == node.CDATA_SECTION_NODE): 197 rc += n.data 198 elif (n.nodeType == node.TEXT_NODE): 199 rc += n.data 200 return rc.encode(encoding)
201
202 - def _drawString(self, node):
203 self.canvas.drawString(text=self._textual(node), **utils.attr_get(node, ['x','y']))
204 - def _drawCenteredString(self, node):
205 self.canvas.drawCentredString(text=self._textual(node), **utils.attr_get(node, ['x','y']))
206 - def _drawRightString(self, node):
207 self.canvas.drawRightString(text=self._textual(node), **utils.attr_get(node, ['x','y']))
208 - def _rect(self, node):
209 if node.hasAttribute('round'): 210 self.canvas.roundRect(radius=utils.unit_get(node.getAttribute('round')), **utils.attr_get(node, ['x','y','width','height'], {'fill':'bool','stroke':'bool'})) 211 else: 212 self.canvas.rect(**utils.attr_get(node, ['x','y','width','height'], {'fill':'bool','stroke':'bool'}))
213 - def _ellipse(self, node):
214 x1 = utils.unit_get(node.getAttribute('x')) 215 x2 = utils.unit_get(node.getAttribute('width')) 216 y1 = utils.unit_get(node.getAttribute('y')) 217 y2 = utils.unit_get(node.getAttribute('height')) 218 self.canvas.ellipse(x1,y1,x2,y2, **utils.attr_get(node, [], {'fill':'bool','stroke':'bool'}))
219 - def _curves(self, node):
220 line_str = utils.text_get(node).split() 221 lines = [] 222 while len(line_str)>7: 223 self.canvas.bezier(*[utils.unit_get(l) for l in line_str[0:8]]) 224 line_str = line_str[8:]
225 - def _lines(self, node):
226 line_str = utils.text_get(node).split() 227 lines = [] 228 while len(line_str)>3: 229 lines.append([utils.unit_get(l) for l in line_str[0:4]]) 230 line_str = line_str[4:] 231 self.canvas.lines(lines)
232 - def _grid(self, node):
233 xlist = [utils.unit_get(s) for s in node.getAttribute('xs').split(',')] 234 ylist = [utils.unit_get(s) for s in node.getAttribute('ys').split(',')] 235 self.canvas.grid(xlist, ylist)
236 - def _translate(self, node):
237 dx = 0 238 dy = 0 239 if node.hasAttribute('dx'): 240 dx = utils.unit_get(node.getAttribute('dx')) 241 if node.hasAttribute('dy'): 242 dy = utils.unit_get(node.getAttribute('dy')) 243 self.canvas.translate(dx,dy)
244
245 - def _circle(self, node):
246 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'}))
247
248 - def _place(self, node):
249 flows = _rml_flowable(self.doc).render(node) 250 infos = utils.attr_get(node, ['x','y','width','height']) 251 252 infos['y']+=infos['height'] 253 for flow in flows: 254 w,h = flow.wrap(infos['width'], infos['height']) 255 if w<=infos['width'] and h<=infos['height']: 256 infos['y']-=h 257 flow.drawOn(self.canvas,infos['x'],infos['y']) 258 infos['height']-=h 259 else: 260 raise ValueError, "Not enough space"
261
262 - def _line_mode(self, node):
263 ljoin = {'round':1, 'mitered':0, 'bevelled':2} 264 lcap = {'default':0, 'round':1, 'square':2} 265 if node.hasAttribute('width'): 266 self.canvas.setLineWidth(utils.unit_get(node.getAttribute('width'))) 267 if node.hasAttribute('join'): 268 self.canvas.setLineJoin(ljoin[node.getAttribute('join')]) 269 if node.hasAttribute('cap'): 270 self.canvas.setLineCap(lcap[node.getAttribute('cap')]) 271 if node.hasAttribute('miterLimit'): 272 self.canvas.setDash(utils.unit_get(node.getAttribute('miterLimit'))) 273 if node.hasAttribute('dash'): 274 dashes = node.getAttribute('dash').split(',') 275 for x in range(len(dashes)): 276 dashes[x]=utils.unit_get(dashes[x]) 277 self.canvas.setDash(node.getAttribute('dash').split(','))
278
279 - def _image(self, node):
280 import urllib 281 from reportlab.lib.utils import ImageReader 282 u = urllib.urlopen(str(node.getAttribute('file'))) 283 s = StringIO.StringIO() 284 s.write(u.read()) 285 s.seek(0) 286 img = ImageReader(s) 287 (sx,sy) = img.getSize() 288 289 args = {} 290 for tag in ('width','height','x','y'): 291 if node.hasAttribute(tag): 292 args[tag] = utils.unit_get(node.getAttribute(tag)) 293 if ('width' in args) and (not 'height' in args): 294 args['height'] = sy * args['width'] / sx 295 elif ('height' in args) and (not 'width' in args): 296 args['width'] = sx * args['height'] / sy 297 elif ('width' in args) and ('height' in args): 298 if (float(args['width'])/args['height'])>(float(sx)>sy): 299 args['width'] = sx * args['height'] / sy 300 else: 301 args['height'] = sy * args['width'] / sx 302 self.canvas.drawImage(img, **args)
303
304 - def _path(self, node):
305 self.path = self.canvas.beginPath() 306 self.path.moveTo(**utils.attr_get(node, ['x','y'])) 307 for n in node.childNodes: 308 if n.nodeType == node.ELEMENT_NODE: 309 if n.localName=='moveto': 310 vals = utils.text_get(n).split() 311 self.path.moveTo(utils.unit_get(vals[0]), utils.unit_get(vals[1])) 312 elif n.localName=='curvesto': 313 vals = utils.text_get(n).split() 314 while len(vals)>5: 315 pos=[] 316 while len(pos)<6: 317 pos.append(utils.unit_get(vals.pop(0))) 318 self.path.curveTo(*pos) 319 elif (n.nodeType == node.TEXT_NODE): 320 data = n.data.split() # Not sure if I must merge all TEXT_NODE ? 321 while len(data)>1: 322 x = utils.unit_get(data.pop(0)) 323 y = utils.unit_get(data.pop(0)) 324 self.path.lineTo(x,y) 325 if (not node.hasAttribute('close')) or utils.bool_get(node.getAttribute('close')): 326 self.path.close() 327 self.canvas.drawPath(self.path, **utils.attr_get(node, [], {'fill':'bool','stroke':'bool'}))
328
329 - def render(self, node):
330 tags = { 331 'drawCentredString': self._drawCenteredString, 332 'drawRightString': self._drawRightString, 333 'drawString': self._drawString, 334 'rect': self._rect, 335 'ellipse': self._ellipse, 336 'lines': self._lines, 337 'grid': self._grid, 338 'curves': self._curves, 339 'fill': lambda node: self.canvas.setFillColor(color.get(node.getAttribute('color'))), 340 'stroke': lambda node: self.canvas.setStrokeColor(color.get(node.getAttribute('color'))), 341 'setFont': lambda node: self.canvas.setFont(node.getAttribute('name'), utils.unit_get(node.getAttribute('size'))), 342 'place': self._place, 343 'circle': self._circle, 344 'lineMode': self._line_mode, 345 'path': self._path, 346 'rotate': lambda node: self.canvas.rotate(float(node.getAttribute('degrees'))), 347 'translate': self._translate, 348 'image': self._image 349 } 350 for nd in node.childNodes: 351 if nd.nodeType==nd.ELEMENT_NODE: 352 for tag in tags: 353 if nd.localName==tag: 354 tags[tag](nd) 355 break
356
357 -class _rml_draw(object):
358 - def __init__(self, node, styles):
359 self.node = node 360 self.styles = styles 361 self.canvas = None
362
363 - def render(self, canvas, doc):
364 canvas.saveState() 365 cnv = _rml_canvas(canvas, doc, self.styles) 366 cnv.render(self.node) 367 canvas.restoreState()
368
369 -class _rml_flowable(object):
370 - def __init__(self, doc):
371 self.doc = doc 372 self.styles = doc.styles
373
374 - def _textual(self, node):
375 rc = '' 376 for n in node.childNodes: 377 if n.nodeType == node.ELEMENT_NODE: 378 if n.localName=='getName': 379 newNode = self.doc.dom.createTextNode(self.styles.names.get(n.getAttribute('id'),'Unknown name')) 380 node.insertBefore(newNode, n) 381 node.removeChild(n) 382 if n.localName=='pageNumber': 383 rc+='<pageNumber/>' # TODO: change this ! 384 else: 385 self._textual(n) 386 rc += n.toxml() 387 elif (n.nodeType == node.CDATA_SECTION_NODE): 388 rc += n.data 389 elif (n.nodeType == node.TEXT_NODE): 390 rc += n.data 391 return rc.encode(encoding)
392
393 - def _table(self, node):
394 length = 0 395 colwidths = None 396 rowheights = None 397 data = [] 398 for tr in _child_get(node,'tr'): 399 data2 = [] 400 for td in _child_get(tr, 'td'): 401 flow = [] 402 for n in td.childNodes: 403 if n.nodeType==node.ELEMENT_NODE: 404 flow.append( self._flowable(n) ) 405 if not len(flow): 406 flow = self._textual(td) 407 data2.append( flow ) 408 if len(data2)>length: 409 length=len(data2) 410 for ab in data: 411 while len(ab)<length: 412 ab.append('') 413 while len(data2)<length: 414 data2.append('') 415 data.append( data2 ) 416 if node.hasAttribute('colWidths'): 417 assert length == len(node.getAttribute('colWidths').split(',')) 418 colwidths = [utils.unit_get(f.strip()) for f in node.getAttribute('colWidths').split(',')] 419 if node.hasAttribute('rowHeights'): 420 rowheights = [utils.unit_get(f.strip()) for f in node.getAttribute('rowHeights').split(',')] 421 table = platypus.Table(data = data, colWidths=colwidths, rowHeights=rowheights, **(utils.attr_get(node, ['splitByRow'] ,{'repeatRows':'int','repeatCols':'int'}))) 422 if node.hasAttribute('style'): 423 table.setStyle(self.styles.table_styles[node.getAttribute('style')]) 424 return table
425
426 - def _illustration(self, node):
427 class Illustration(platypus.flowables.Flowable): 428 def __init__(self, node, styles): 429 self.node = node 430 self.styles = styles 431 self.width = utils.unit_get(node.getAttribute('width')) 432 self.height = utils.unit_get(node.getAttribute('height'))
433 def wrap(self, *args): 434 return (self.width, self.height)
435 def draw(self): 436 canvas = self.canv 437 drw = _rml_draw(self.node, self.styles) 438 drw.render(self.canv, None) 439 return Illustration(node, self.styles) 440
441 - def _flowable(self, node):
442 if node.localName=='para': 443 style = self.styles.para_style_get(node) 444 return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str'}))) 445 elif node.localName=='name': 446 self.styles.names[ node.getAttribute('id')] = node.getAttribute('value') 447 return None 448 elif node.localName=='xpre': 449 style = self.styles.para_style_get(node) 450 return platypus.XPreformatted(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str','dedent':'int','frags':'int'}))) 451 elif node.localName=='pre': 452 style = self.styles.para_style_get(node) 453 return platypus.Preformatted(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str','dedent':'int'}))) 454 elif node.localName=='illustration': 455 return self._illustration(node) 456 elif node.localName=='blockTable': 457 return self._table(node) 458 elif node.localName=='title': 459 styles = reportlab.lib.styles.getSampleStyleSheet() 460 style = styles['Title'] 461 return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str'}))) 462 elif node.localName=='h1': 463 styles = reportlab.lib.styles.getSampleStyleSheet() 464 style = styles['Heading1'] 465 return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str'}))) 466 elif node.localName=='h2': 467 styles = reportlab.lib.styles.getSampleStyleSheet() 468 style = styles['Heading2'] 469 return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str'}))) 470 elif node.localName=='h3': 471 styles = reportlab.lib.styles.getSampleStyleSheet() 472 style = styles['Heading3'] 473 return platypus.Paragraph(self._textual(node), style, **(utils.attr_get(node, [], {'bulletText':'str'}))) 474 elif node.localName=='image': 475 return platypus.Image(node.getAttribute('file'), mask=(250,255,250,255,250,255), **(utils.attr_get(node, ['width','height']))) 476 elif node.localName=='spacer': 477 if node.hasAttribute('width'): 478 width = utils.unit_get(node.getAttribute('width')) 479 else: 480 width = utils.unit_get('1cm') 481 length = utils.unit_get(node.getAttribute('length')) 482 return platypus.Spacer(width=width, height=length) 483 elif node.localName=='pageBreak': 484 return platypus.PageBreak() 485 elif node.localName=='condPageBreak': 486 return platypus.CondPageBreak(**(utils.attr_get(node, ['height']))) 487 elif node.localName=='setNextTemplate': 488 return platypus.NextPageTemplate(str(node.getAttribute('name'))) 489 elif node.localName=='nextFrame': 490 return platypus.CondPageBreak(1000) # TODO: change the 1000 ! 491 else: 492 sys.stderr.write('Warning: flowable not yet implemented: %s !\n' % (node.localName,)) 493 return None
494
495 - def render(self, node_story):
496 story = [] 497 node = node_story.firstChild 498 while node: 499 if node.nodeType == node.ELEMENT_NODE: 500 flow = self._flowable(node) 501 if flow: 502 story.append(flow) 503 node = node.nextSibling 504 return story
505
506 -class _rml_template(object):
507 - def __init__(self, out, node, doc):
508 if not node.hasAttribute('pageSize'): 509 pageSize = (utils.unit_get('21cm'), utils.unit_get('29.7cm')) 510 else: 511 ps = map(lambda x:x.strip(), node.getAttribute('pageSize').replace(')', '').replace('(', '').split(',')) 512 pageSize = ( utils.unit_get(ps[0]),utils.unit_get(ps[1]) ) 513 cm = reportlab.lib.units.cm 514 self.doc_tmpl = platypus.BaseDocTemplate(out, pagesize=pageSize, **utils.attr_get(node, ['leftMargin','rightMargin','topMargin','bottomMargin'], {'allowSplitting':'int','showBoundary':'bool','title':'str','author':'str'})) 515 self.page_templates = [] 516 self.styles = doc.styles 517 self.doc = doc 518 pts = node.getElementsByTagName('pageTemplate') 519 for pt in pts: 520 frames = [] 521 for frame_el in pt.getElementsByTagName('frame'): 522 frame = platypus.Frame( **(utils.attr_get(frame_el, ['x1','y1', 'width','height', 'leftPadding', 'rightPadding', 'bottomPadding', 'topPadding'], {'id':'text', 'showBoundary':'bool'})) ) 523 frames.append( frame ) 524 gr = pt.getElementsByTagName('pageGraphics') 525 if len(gr): 526 drw = _rml_draw(gr[0], self.doc) 527 self.page_templates.append( platypus.PageTemplate(frames=frames, onPage=drw.render, **utils.attr_get(pt, [], {'id':'str'}) )) 528 else: 529 self.page_templates.append( platypus.PageTemplate(frames=frames, **utils.attr_get(pt, [], {'id':'str'}) )) 530 self.doc_tmpl.addPageTemplates(self.page_templates)
531
532 - def render(self, node_story):
533 r = _rml_flowable(self.doc) 534 fis = r.render(node_story) 535 self.doc_tmpl.build(fis)
536
537 -def parseString(data, fout=None):
538 r = _rml_doc(data) 539 if fout: 540 fp = file(fout,'wb') 541 r.render(fp) 542 fp.close() 543 return fout 544 else: 545 fp = StringIO.StringIO() 546 r.render(fp) 547 return fp.getvalue()
548
549 -def trml2pdf_help():
550 print 'Usage: trml2pdf input.rml >output.pdf' 551 print 'Render the standard input (RML) and output a PDF file' 552 sys.exit(0)
553 554 if __name__=="__main__": 555 if len(sys.argv)>1: 556 if sys.argv[1]=='--help': 557 trml2pdf_help() 558 print parseString(file(sys.argv[1], 'r').read()), 559 else: 560 print 'Usage: trml2pdf input.rml >output.pdf' 561 print 'Try \'trml2pdf --help\' for more information.' 562