SlideShare ist ein Scribd-Unternehmen logo
1 von 43
Downloaden Sie, um offline zu lesen
ReportLab Paragraphs
     Reloaded

      Dinu C. Gherman
      gherman@python.net

     EuroPython Conference
       2008-07-07, Vilnius
Agenda
• ReportLab Overview
• Paragraphs
• Paragraphs Reloaded & Examples
• Summary
ReportLab Overview
General Features
• Generating PDF with Python (+ some C)
• Content: fonts, graphics, images, tables
• PDF features: page transitions, hyperlinks,
  outline, …
• Graphics import as bitmaps and SVG (ext.)
• Graphics export as bitmaps, PDF, EPS, SVG
Technologies
• PDF
• Type1 and TrueType fonts
• PIL
• libart
• Unicode (UTF-8)
Meta Info
• Developped since ca. 1996
• By Andy Robinson, Robin Becker, et al.
• Current: SVN (v. 2.1 + 12 months)
• Open Source
• Closed Source: RML, PDF encryption,
  PDF import
1st Layer: Canvas
• Corresponds to a single page with
• Text,
• Graphics,
• PDF features (hyperlinks, page transitions...)
• Can also be saved as a bitmap, EPS, SVG
Example 1
#!/usr/bin/env python
# _*_ coding: UTF-8 _*_

from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import A4

canv = Canvas("helloworld.pdf", pagesize=A4)

### ...

canv.showPage()

canv.save()
                                         …
###

from reportlab.lib import colors
from reportlab.lib.units import cm

# circle
canv.setStrokeColor(colors.green)
canv.setFillColor(colors.red)
canv.setLineWidth(0.5*cm)
x, y = 10*cm, 10*cm
canv.circle(x, y, 5*cm,
    stroke=True, fill=True)
                                     Hello world!
# text
canv.setFillColor(colors.yellow)
canv.setFont("Helvetica", 36)
canv.drawCentredString(x, y,
    u"Hello world!")
2nd Layer: Platypus
• ”Page LAyout TYPography Using Scripts“
• Frames
• PageTemplate
• DocumentTemplate
• Content: Flowables & Styles (”Story“)
• Rendered as PDF document
Structure
   Flow.          Flow.    Flow.
   Frame
                  Flow.    Flow.
Flow.    Flow.
                  Flow.    Flow.
Flow.    Flow.
                  Flow. Flow.
Frame Frame       Frame Frame
PageTemplate      PageTemplate
        DocumentTemplate
Flowables
• Content related:
  Paragraph, Preformatted, Image, Table,
  XBox, Spacer, …
• Logic related:
  FrameBreak, PageBreak, CondPageBreak, …
• Layout related:
  KeepWithNext, KeepInFrame, …
Example 2
from reportlab.lib.units import cm
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen.canvas import Canvas
from reportlab.platypus import 
    BaseDocTemplate, PageTemplate, 
    Frame, Paragraph
from reportlab.lib.styles import 
    getSampleStyleSheet

from django.contrib.webdesign import 
    lorem_ipsum as li

PAGESIZE = A4
                                         …
class TwoColumnDocTemplate(BaseDocTemplate):
    "A simple two-column document template."

   def __init__(self, filename, **kw):
       m = margin = 2*cm
       tm = topMargin = 2*cm
       bm = bottomMargin = 2*cm
       cw, ch = (PAGESIZE[0]-2*m)/2., (PAGESIZE[1]-tm)
       leftCol = Frame(m, bm, cw-0.75*cm, ch-tm,
           leftPadding=0, topPadding=0,
           rightPadding=0, bottomPadding=0,
           id="left", showBoundary=True
       )
       rightCol = Frame(cw+2.7*cm, bm, cw-0.75*cm, ch-tm,
           leftPadding=0, topPadding=0,
           rightPadding=0, bottomPadding=0,
           id="right", showBoundary=True
       )
       apply(BaseDocTemplate.__init__, (self, filename), kw)
       allPages = PageTemplate("all", [leftCol, rightCol])
       self.addPageTemplates([allPages])
                                                         …
explicabo distinctio animi ad ipsam veniam enim,
                                                Maiores cupiditate placeat                                  fugit quis recusandae amet eveniet praesentium


def generateTwoColDocument(outPath):
                                                                                                            veniam obcaecati consectetur maxime delectus?
                                                Dolorem perferendis accusantium                             Harum molestias iure at nemo labore quod repellat
                                                veniam optio                                                quas ducimus eum similique, incidunt facilis itaque


    "Create a 2-col doc with rand. text."
                                                                                                            obcaecati iusto fugiat, enim unde voluptas illo? Enim
                                                Quidem explicabo officiis quasi soluta exercitationem       eaque repudiandae cupiditate ad accusantium, alias
                                                blanditiis ullam nobis suscipit praesentium? Nostrum        error tempore ducimus a dicta aut voluptates vitae,
                                                quaerat ullam recusandae esse nulla maiores eos             error cupiditate assumenda quia culpa id illum rerum
                                                eligendi adipisci consequatur dolores, sequi cum            ipsam ipsum, quisquam blanditiis corporis fugiat
                                                veniam dolor voluptates ipsa tempora, quibusdam             excepturi facilis quaerat exercitationem cum tempore
                                                nostrum quasi labore nobis perspiciatis illo eaque vero     voluptas repudiandae? Eos hic reiciendis excepturi
                                                pariatur quos? Ipsum odio ipsa quidem amet impedit          recusandae ad esse.


    stylesheet = getSampleStyleSheet()
                                                recusandae quis, corporis cupiditate laboriosam alias
                                                ratione tempore? Exercitationem voluptates alias
                                                aspernatur odio laboriosam dolores unde vero.
                                                                                                            Excepturi sed repellendus facere
                                                Blanditiis quo at consectetur impedit, iure fugiat sed
                                                                                                            ullam

    h1 = stylesheet['Heading1']                 voluptate nesciunt temporibus facilis, dignissimos
                                                aspernatur maiores assumenda nostrum, error nisi
                                                accusamus officiis quo deleniti facere recusandae
                                                                                                            Ipsum omnis deleniti saepe sapiente, quibusdam
                                                                                                            neque aspernatur delectus quasi iusto a facilis, tenetur
                                                                                                            nostrum incidunt nesciunt veritatis, velit sunt nostrum


    h2 = stylesheet['Heading2']
                                                animi quidem ea excepturi, recusandae quasi dolor           quo quae necessitatibus? Delectus suscipit soluta
                                                nulla molestiae unde repellendus odit sint non officia      veniam harum sunt, laudantium iusto voluptatibus,
                                                omnis.                                                      fuga facere nihil sed aspernatur placeat, impedit libero
                                                Cupiditate minima pariatur itaque alias suscipit, nulla     repellendus laudantium nisi nihil eveniet reiciendis?


    bt = stylesheet['BodyText']                 culpa atque deleniti id et tenetur aliquid unde qui vel     Exercitationem nemo possimus debitis? Aliquid
                                                sint, cumque rerum maiores voluptate, quas et quia?         nesciunt cum natus eveniet obcaecati fugiat
                                                Quam debitis praesentium vitae, nesciunt quas               repellendus, et numquam odit velit alias, dolor aut
                                                distinctio quisquam, impedit tempora architecto aut?        quasi ut tempora itaque nemo earum animi, ipsa
                                                Perspiciatis et ullam sit commodi cumque optio              similique natus inventore nobis sed quia eaque totam
                                                pariatur, eum totam minus et quis, vero itaque              tempore incidunt dolorum, molestias rem blanditiis ad
                                                molestias eius sed eligendi veniam quae dolore              autem.
                                                doloribus, unde rem odit similique sapiente eveniet?

    st = story = []
                                                                                                            Tempora voluptatibus quo dicta expedita tempore
                                                                                                            harum porro?
                                                Cumque blanditiis ut facilis quasi                          Cupiditate possimus dignissimos laborum consectetur
                                                                                                            laudantium, illum ipsa perferendis adipisci veritatis

    p = li.words(3, common=False)
                                                Aut omnis atque molestiae est inventore delectus
                                                ipsam a commodi, tempora ratione unde quia non              nemo voluptate, assumenda molestias unde aperiam
                                                pariatur nobis dolores, quisquam corporis iste quaerat      quisquam cumque debitis, ea incidunt odit expedita
                                                illum atque ea sint doloribus iusto nemo, amet quidem       facilis, molestiae quam sint doloremque officia nemo
                                                                                                            explicabo qui. Libero maxime magnam, dolores

    p = p.capitalize()
                                                nesciunt dolor commodi accusantium cumque ipsum,
                                                praesentium illum pariatur? Dicta nobis culpa placeat       quaerat quos nisi dolorem libero eaque at, nobis eaque
                                                tenetur repellat distinctio pariatur debitis praesentium,   omnis labore libero magnam officia. Quis aperiam
                                                exercitationem repudiandae dolore et fugiat neque?          tempore perferendis asperiores pariatur cum,


    st.append(Paragraph(p, style=h1))
                                                Doloremque et non architecto quas, laudantium               accusamus error ratione, consectetur minus saepe
                                                repellat a deserunt minima explicabo beatae possimus,       veritatis harum, similique aliquid exercitationem cum
                                                facilis fugit similique ad porro sapiente suscipit odit     assumenda, natus unde non veniam quas illum enim
                                                alias quod qui excepturi, autem provident fugiat            amet sequi quis molestias.


    for i in range(10):                         pariatur ullam perferendis ipsa fugit. Minus fugiat sint
                                                consequatur delectus necessitatibus eius eum.
                                                Voluptate sit ratione nobis aperiam omnis fugit
                                                                                                            Mollitia amet voluptatum facere
                                                                                                            blanditiis

        p = li.words(5, common=False)
                                                accusantium totam sequi accusamus, nulla perspiciatis
                                                ut corporis eos possimus, ducimus id veniam earum,          Et ullam placeat ut accusamus recusandae quidem
                                                molestias ipsa dolorum aut eligendi doloremque              totam veritatis voluptatibus. Officia quae voluptates
                                                laudantium atque aliquam voluptatibus hic esse,             necessitatibus beatae atque laudantium voluptas
                                                                                                            voluptate veritatis sequi vero, dolore asperiores at

        p = p.capitalize()
                                                explicabo amet assumenda eaque autem molestiae
                                                exercitationem fugiat quasi sequi? Facilis tenetur qui      molestias iusto eum ab necessitatibus, voluptatibus
                                                eveniet obcaecati saepe porro repellat doloremque           quis minus? Distinctio eos dolore corporis corrupti
                                                magni, dolor assumenda error recusandae rem                 ducimus facilis iste doloribus nisi eligendi.


        st.append(Paragraph(p, style=h2))
        for j in range(3):
            p = li.paragraph()
            st.append(Paragraph(p, style=bt))

    doc = TwoColumnDocTemplate(outPath, pagesize=PAGESIZE)
    doc.build(story)
3rd Layer: RML
• ”Report Markup Language“
• Platypus in XML + Black Box + ¥$€
• See also: z3c.rml (S. Richter et al. – free)
• PageCatcher (more ¥$€) for PDF import
• See also: one of my next announcements…
Paragraphs
Features
• Subclass of the Flowable class
• Core class in Platypus (paragraph.py)
• No alternative (except para.py – R.I.P.)
• Central feature: linebreaks
• Knows style attributes
Global Style Attributes
• fontName, fontSize, textColor, backColor
• firstLineIndent, leftIndent, rightIndent
• alignment, leading, (spaceBefore, spaceAfter)
• bulletColor, bulletFontName,
    bulletFontSize, bulletIndent, bulletOffsetY
•   Sample:   stylesheet = getSampleStyleSheet()
              bt = stylesheet['BodyText']
              bt.leading = 16
              bt.textColor = colors.blue
Local Style Attributes
• XML tags in paragraph text:
• font, br, b, i, u, strong, strike, a, link, img
• superscript, subscript, greek
• seq, seqDefault, seqReset
• Sample:
   t = "Hello <font color='red'>red</font> world!"
   p = Paragraph(t, style=myStyle)
Lacking…
• Inline images (new in SVN)
• Hyphenation
• Kerning
• Code comprehensibility
• Code extensibility
          ”Reporting Solutions“!?
               Efficiency!?
Paragraphs Reloaded
New Approach
• New Flowable!
• MinimalParagraph class
• Easily extensible (shown in subclasses)
• Linebreaks (and not much more)!
• Critical methods: wrap, split, draw
Sample: XBox
class XBox(Flowable):

    def __init__(self, width, height, text='A Box'):
        Flowable.__init__(self)
        self.width, self.height, self.text = width, height, text

    def draw(self):
        canv, w, h =   self.canv, self.width, self.height
        canv.rect(0,   0, w, h)
        canv.line(0,   0, w, h)
        canv.line(0,   h, w, 0)

        canv.setFont('Times-Roman', 12)
        canv.drawCentredString(0.5*w, 0.5*h, self.text)

    # inherited by Flowable:

    def wrap(self, availWidth, availHeight):
        return (self.width, self.height)

    def split(self, availWidth, availheight):
        return []
Key Idea: ”Events“
• Input text: "Hello world"
• Parsed: [{"text":"Hello"}, {"text":"world"}]
• Word widths: [{"text":"Hello", "width":10},
  {text:"world", "width":11}]
• Placement: [{"text":"Hello", "width":10,
  "pos":(10, 5)}, {"text":"world", "width":11,
  "pos":(23, 5)}]
• Add attributes as needed
MinimalParagraph
• Global attributes: fontName, fontSize,
  leading, firstLineIndent, leftIndent,
  rightIndent, textColor, (spaceBefore,
  spaceAfter)
• No alignment (left only), …
• Focus on linebreaks and RL compliance
Alice was beginning to get very tired of sitting   well, and noticed that they were filled with
by her sister on the bank, and of having           cupboards and book-shelves; here and there
nothing to do: once or twice she had peeped        she saw maps and pictures hung upon pegs.
into the book her sister was reading, but it       She took down a jar from one of the shelves
had no pictures or conversations in it, `and       as she passed; it was labelled `ORANGE
what is the use of a book,' thought Alice          MARMALADE', but to her great
`without pictures or conversation?'                disappointment it was empty: she did not like
                                                   to drop the jar for fear of killing somebody, so
So she was considering in her own mind (as         managed to put it into one of the cupboards
well as she could, for the hot day made her        as she fell past it.
feel very sleepy and stupid), whether the
pleasure of making a daisy-chain would be          `Well!' thought Alice to herself, `after such a
worth the trouble of getting up and picking        fall as this, I shall think nothing of tumbling
the daisies, when suddenly a White Rabbit          down stairs! How brave they'll all think me at
with pink eyes ran close by her.                   home! Why, I wouldn't say anything about it,
                                                   even if I fell off the top of the house!' (Which
There was nothing so VERY remarkable in            was very likely true.)
that; nor did Alice think it so VERY much out
of the way to hear the Rabbit say to itself,       Down, down, down. Would the fall NEVER
`Oh dear! Oh dear! I shall be late!' (when she     come to an end! `I wonder how many miles
thought it over afterwards, it occurred to her     I've fallen by this time?' she said aloud. `I
that she ought to have wondered at this, but       must be getting somewhere near the centre
at the time it all seemed quite natural); but      of the earth. Let me see: that would be four
when the Rabbit actually TOOK A WATCH              thousand miles down, I think--' (for, you see,
OUT OF ITS WAISTCOAT- POCKET, and                  Alice had learnt several things of this sort in



         MinimalParagraph
looked at it, and then hurried on, Alice           her lessons in the schoolroom, and though
started to her feet, for it flashed across her     this was not a VERY good opportunity for
mind that she had never before seen a rabbit       showing off her knowledge, as there was no
with either a waistcoat-pocket, or a watch to      one to listen to her, still it was good practice
take out of it, and burning with curiosity, she    to say it over) `--yes, that's about the right
ran across the field after it, and fortunately     distance--but then I wonder what Latitude or
was just in time to see it pop down a large        Longitude I've got to?' (Alice had no idea
ColouredParagraph
#!/bin/env/python                        def draw(self):
# -*- coding: utf-8 -*-                    "Render words in paragraph on randomly 
                                            coloured background."
"An example for a coloured paragraph 
subclass."                                 if not self.words:
                                             return

import random                              canvas = self.canv
                                           style = self.style
from reportlab.lib import colors
                                           canvas.saveState()
from minimalparagraph import 
MinimalParagraph                           canvas.setFont(style.fontName, style.fontSize)

                                           for word in self.words:
RL_COLORS = [v for (k, v) in                if "meta" in word or not "pos" in word:
  colors.__dict__.items()                     continue
  if isinstance(v, colors.Color)]            text, (x, y) = word["text"], word["pos"]
                                             col = random.choice(RL_COLORS)
                                             canvas.setStrokeColor(col)
class ColouredParagraph(MinimalParagraph):   canvas.setFillColor(col)
  "A colourful tiny subclass                canvas.rect(x, y - self.dy,
  of MinimalParagraph."                        word["width"], style.fontSize,
                                               fill=True, stroke=True)
                                             canvas.setFillColor(style.textColor)
                                             canvas.drawString(x, y - self.dy, text)

                                           canvas.restoreState()
!"#$% &'( )# *+(, -+( .+(,/ 0 $#")-123 4")         1+(L5#6-E ,5- !"-6( )#$" +") 6##!-) +6#"8 (5-
5-1- 467*- .-8+" (# 8-( 1+(5-1 ,6--9:/ +")         9+,,+8- 7"(# (5- 6#C-67-,( 8+1)-" :#' -C-1
$-"( #" ,+:7"8 (# 5-1,-6;/ 7" + )1-+<: ,#1( #;     ,+$% N#$ ,5- 6#"8-) (# 8-( #'( #; (5+( )+1!
$+:/ =># *+(, -+( .+(,2 ># *+(, -+( .+(,23 +")     5+66/ +") $+")-1 +.#'( +<#"8 (5#,- .-), #;
,#<-(7<-,/ =># .+(, -+( *+(,23 ;#1/ :#' ,--/ +,    .1785( ;6#$-1, +") (5#,- *##6 ;#'"(+7",/ .'(
,5- *#'6)"3( +",$-1 -7(5-1 ?'-,(7#"/ 7( )7)"3(     ,5- *#'6) "#( -C-" 8-( 5-1 5-+) (51#'85 (5-
<'*5 <+((-1 $57*5 $+: ,5- 9'( 7(% @5- ;-6(         )##1$+:G =+") -C-" 7; <: 5-+) $#'6) 8#
(5+( ,5- $+, )#A7"8 #;;/ +") 5+) B',( .-8'" (#     (51#'85/3 (5#'85( 9##1 467*-/ =7( $#'6) .- #;
)1-+< (5+( ,5- $+, $+6!7"8 5+") 7" 5+") $7(5       C-1: 67((6- ',- $7(5#'( <: ,5#'6)-1,% K5/ 5#$ 0
>7"+5/ +") ,+:7"8 (# 5-1 C-1: -+1"-,(6:/ =D#$/     $7,5 0 *#'6) ,5'( '9 67!- + (-6-,*#9-F 0 (57"! 0
>7"+5/ (-66 <- (5- (1'(5E )7) :#' -C-1 -+( +       *#'6)/ 7; 0 #"6: !"#$ 5#$ (# .-87"%3 O#1/ :#'
.+(23 $5-" ,'))-"6:/ (5'<9F (5'<9F )#$"            ,--/ ,# <+": #'(L#;L(5-L$+: (57"8, 5+)
,5- *+<- '9#" + 5-+9 #; ,(7*!, +") )1: 6-+C-,/     5+99-"-) 6+(-6:/ (5+( 467*- 5+) .-8'" (# (57"!
+") (5- ;+66 $+, #C-1%                             (5+( C-1: ;-$ (57"8, 7")--) $-1- 1-+66:
                                                   7<9#,,7.6-%
467*- $+, "#( + .7( 5'1(/ +") ,5- B'<9-) '9 #"
(# 5-1 ;--( 7" + <#<-"(E ,5- 6##!-) '9/ .'( 7(     J5-1- ,--<-) (# .- "# ',- 7" $+7(7"8 .: (5-
$+, +66 )+1! #C-15-+)G .-;#1- 5-1 $+, +"#(5-1      67((6- )##1/ ,# ,5- $-"( .+*! (# (5- (+.6-/ 5+6;
6#"8 9+,,+8-/ +") (5- H57(- I+..7( $+, ,(766 7"    5#97"8 ,5- <785( ;7") +"#(5-1 !-: #" 7(/ #1 +(
,785(/ 5'11:7"8 )#$" 7(% J5-1- $+, "#( +           +": 1+(- + .##! #; 1'6-, ;#1 ,5'((7"8 9-#96- '9
<#<-"( (# .- 6#,(E +$+: $-"( 467*- 67!- (5-        67!- (-6-,*#9-,E (57, (7<- ,5- ;#'") + 67((6-
$7")/ +") $+, B',( 7" (7<- (# 5-+1 7( ,+:/ +, 7(   .#((6- #" 7(/ P=$57*5 *-1(+7"6: $+, "#( 5-1-
('1"-) + *#1"-1/ =K5 <: -+1, +") $57,!-1,/         .-;#1-/3 ,+7) 467*-/Q +") 1#'") (5- "-*! #; (5-
5#$ 6+(- 7(3, 8-((7"8F3 @5- $+, *6#,- .-57") 7(    .#((6- $+, + 9+9-1 6+.-6/ $7(5 (5- $#1),
$5-" ,5- ('1"-) (5- *#1"-1/ .'( (5- I+..7(         =>I0DR ST3 .-+'(7;'66: 917"(-) #" 7( 7" 6+18-


     ColouredParagraph
$+, "# 6#"8-1 (# .- ,--"E ,5- ;#'") 5-1,-6; 7"     6-((-1,%
+ 6#"8/ 6#$ 5+66/ $57*5 $+, 67( '9 .: + 1#$ #;
6+<9, 5+"87"8 ;1#< (5- 1##;%                       0( $+, +66 C-1: $-66 (# ,+: =>17"! <-/3 .'( (5-
                                                   $7,- 67((6- 467*- $+, "#( 8#7"8 (# )# JN4J 7" +
J5-1- $-1- )##1, +66 1#'") (5- 5+66/ .'( (5-:      5'11:% =D#/ 0366 6##! ;71,(/3 ,5- ,+7)/ =+") ,--
$-1- +66 6#*!-)G +") $5-" 467*- 5+) .--" +66       $5-(5-1 7(3, <+1!-) U9#7,#"U #1 "#(3G ;#1 ,5-
(5- $+: )#$" #"- ,7)- +") '9 (5- #(5-1/            5+) 1-+) ,-C-1+6 "7*- 67((6- 57,(#17-, +.#'(
!"#$% &'( )# *+(, -+( .+(,/ 0 $#")-123 4")         1+(L5#6-E ,5- !"-6( )#$" +") 6##!-) +6#"8 (5-
5-1- 467*- .-8+" (# 8-( 1+(5-1 ,6--9:/ +")         9+,,+8- 7"(# (5- 6#C-67-,( 8+1)-" :#' -C-1
$-"( #" ,+:7"8 (# 5-1,-6;/ 7" + )1-+<: ,#1( #;     ,+$% N#$ ,5- 6#"8-) (# 8-( #'( #; (5+( )+1!
$+:/ =># *+(, -+( .+(,2 ># *+(, -+( .+(,23 +")     5+66/ +") $+")-1 +.#'( +<#"8 (5#,- .-), #;
,#<-(7<-,/ =># .+(, -+( *+(,23 ;#1/ :#' ,--/ +,    .1785( ;6#$-1, +") (5#,- *##6 ;#'"(+7",/ .'(
,5- *#'6)"3( +",$-1 -7(5-1 ?'-,(7#"/ 7( )7)"3(     ,5- *#'6) "#( -C-" 8-( 5-1 5-+) (51#'85 (5-
<'*5 <+((-1 $57*5 $+: ,5- 9'( 7(% @5- ;-6(         )##1$+:G =+") -C-" 7; <: 5-+) $#'6) 8#
(5+( ,5- $+, )#A7"8 #;;/ +") 5+) B',( .-8'" (#     (51#'85/3 (5#'85( 9##1 467*-/ =7( $#'6) .- #;
)1-+< (5+( ,5- $+, $+6!7"8 5+") 7" 5+") $7(5       C-1: 67((6- ',- $7(5#'( <: ,5#'6)-1,% K5/ 5#$ 0
>7"+5/ +") ,+:7"8 (# 5-1 C-1: -+1"-,(6:/ =D#$/     $7,5 0 *#'6) ,5'( '9 67!- + (-6-,*#9-F 0 (57"! 0
>7"+5/ (-66 <- (5- (1'(5E )7) :#' -C-1 -+( +       *#'6)/ 7; 0 #"6: !"#$ 5#$ (# .-87"%3 O#1/ :#'
.+(23 $5-" ,'))-"6:/ (5'<9F (5'<9F )#$"            ,--/ ,# <+": #'(L#;L(5-L$+: (57"8, 5+)
,5- *+<- '9#" + 5-+9 #; ,(7*!, +") )1: 6-+C-,/     5+99-"-) 6+(-6:/ (5+( 467*- 5+) .-8'" (# (57"!
+") (5- ;+66 $+, #C-1%                             (5+( C-1: ;-$ (57"8, 7")--) $-1- 1-+66:
                                                   7<9#,,7.6-%
467*- $+, "#( + .7( 5'1(/ +") ,5- B'<9-) '9 #"
(# 5-1 ;--( 7" + <#<-"(E ,5- 6##!-) '9/ .'( 7(     J5-1- ,--<-) (# .- "# ',- 7" $+7(7"8 .: (5-
$+, +66 )+1! #C-15-+)G .-;#1- 5-1 $+, +"#(5-1      67((6- )##1/ ,# ,5- $-"( .+*! (# (5- (+.6-/ 5+6;
6#"8 9+,,+8-/ +") (5- H57(- I+..7( $+, ,(766 7"    5#97"8 ,5- <785( ;7") +"#(5-1 !-: #" 7(/ #1 +(
,785(/ 5'11:7"8 )#$" 7(% J5-1- $+, "#( +           +": 1+(- + .##! #; 1'6-, ;#1 ,5'((7"8 9-#96- '9
<#<-"( (# .- 6#,(E +$+: $-"( 467*- 67!- (5-        67!- (-6-,*#9-,E (57, (7<- ,5- ;#'") + 67((6-
$7")/ +") $+, B',( 7" (7<- (# 5-+1 7( ,+:/ +, 7(   .#((6- #" 7(/ P=$57*5 *-1(+7"6: $+, "#( 5-1-
('1"-) + *#1"-1/ =K5 <: -+1, +") $57,!-1,/         .-;#1-/3 ,+7) 467*-/Q +") 1#'") (5- "-*! #; (5-
5#$ 6+(- 7(3, 8-((7"8F3 @5- $+, *6#,- .-57") 7(    .#((6- $+, + 9+9-1 6+.-6/ $7(5 (5- $#1),
$5-" ,5- ('1"-) (5- *#1"-1/ .'( (5- I+..7(         =>I0DR ST3 .-+'(7;'66: 917"(-) #" 7( 7" 6+18-


 HighlightedParagraph
$+, "# 6#"8-1 (# .- ,--"E ,5- ;#'") 5-1,-6; 7"     6-((-1,%
+ 6#"8/ 6#$ 5+66/ $57*5 $+, 67( '9 .: + 1#$ #;
6+<9, 5+"87"8 ;1#< (5- 1##;%                       0( $+, +66 C-1: $-66 (# ,+: =>17"! <-/3 .'( (5-
                                                   $7,- 67((6- 467*- $+, "#( 8#7"8 (# )# JN4J 7" +
J5-1- $-1- )##1, +66 1#'") (5- 5+66/ .'( (5-:      5'11:% =D#/ 0366 6##! ;71,(/3 ,5- ,+7)/ =+") ,--
$-1- +66 6#*!-)G +") $5-" 467*- 5+) .--" +66       $5-(5-1 7(3, <+1!-) U9#7,#"U #1 "#(3G ;#1 ,5-
(5- $+: )#$" #"- ,7)- +") '9 (5- #(5-1/            5+) 1-+) ,-C-1+6 "7*- 67((6- 57,(#17-, +.#'(
R1#*6" .#00%*;-%%7< >"# O%'0# $):# )
")+ 0%/#"%, 2)..#* 4*&% &"# 0#)5 =)*+ 4* &")&     0'++#* .#)( %'& %2 &"# ,)&#15 )*+ 0##/#+ &%
6)0# E 6)* $% -)67 -3 1)4.,)35B 0"# 0)4+ &%       K'4:#1 ).. %:#1 ,4&" 214$"&< =N"5 E -#$ 3%'1
"#10#.2< G@.46# ")+ -##* &% &"# 0#)04+# %*6# 4*   ()1+%*AB 614#+ @.46# ")0&4.35 )21)4+ &")& 0"# ")+
"#1 .42#5 )*+ ")+ 6%/# &% &"# $#*#1). 6%*6.';     "'1& &"# (%%1 )*4/).B0 2##.4*$0< =E K'4&# 2%1$%&
04%*5 &")& ,"#1#:#1 3%' $% &% %* &"# H*$.40"      3%' +4+*B& .47# 6)&0<B
6%)0& 3%' 24*+ ) *'/-#1 %2 -)&"4*$ /)6"4*#0
4* &"# 0#)5 0%/# 6"4.+1#* +4$$4*$ 4* &"# 0)*+     =T%& .47# 6)&0AB 614#+ &"# O%'0#5 4* ) 0"14..5 ()0;
,4&" ,%%+#* 0()+#05 &"#* ) 1%, %2 .%+$4*$         04%*)&# :%46#< =?%'.+ UNV .47# 6)&0 42 3%' ,#1#
"%'0#05 )*+ -#"4*+ &"#/ ) 1)4.,)3 0&)&4%*<I       /#MB
F%,#:#15 0"# 0%%* /)+# %'& &")& 0"# ,)0 4*
&"# (%%. %2 &#)10 ,"46" 0"# ")+ ,#(& ,"#*
0"# ,)0 *4*# 2##& "4$"<

=E ,40" E ")+*B& 614#+ 0% /'6"AB 0)4+ @.46#5 )0
0"# 0,)/ )-%'&5 &134*$ &% 24*+ "#1 ,)3 %'&< =E
0").. -# ('*40"#+ 2%1 4& *%,5 E 0'((%0#5 -3
-#4*$ +1%,*#+ 4* /3 %,* &#)10A >")& ?EJJ -#
) K'##1 &"4*$5 &% -# 0'1#A F%,#:#15 #:#13&"4*$
40 K'##1 &%;+)3<B

L'0& &"#* 0"# "#)1+ 0%/#&"4*$ 0(.)0"4*$
)-%'& 4* &"# (%%. ) .4&&.# ,)3 %225 )*+ 0"#
0,)/ *#)1#1 &% /)7# %'& ,")& 4& ,)08 )& 2410&
0"# &"%'$"& 4& /'0& -# ) ,).1'0 %1 "4((%(%&;
)/'05 -'& &"#* 0"# 1#/#/-#1#+ "%, 0/)..
0"# ,)0 *%,5 )*+ 0"# 0%%* /)+# %'& &")& 4&
,)0 %*.3 ) /%'0# &")& ")+ 0.4((#+ 4* .47#
"#10#.2<


HyphenatedParagraph
R1#*6" .#00%*;-%%7< >"# O%'0# $):# )
 ")+ 0%/#"%, 2)..#* 4*&% &"# 0#)5 =)*+ 4* &")&     0'++#* .#)( %'& %2 &"# ,)&#15 )*+ 0##/#+ &%
 6)0# E 6)* $% -)67 -3 1)4.,)35B 0"# 0)4+ &%       K'4:#1 ).. %:#1 ,4&" 214$"&< =N"5 E -#$ 3%'1
 "#10#.2< G@.46# ")+ -##* &% &"# 0#)04+# %*6# 4*   ()1+%*AB 614#+ @.46# ")0&4.35 )21)4+ &")& 0"# ")+
 "#1 .42#5 )*+ ")+ 6%/# &% &"# $#*#1). 6%*6.';     "'1& &"# (%%1 )*4/).B0 2##.4*$0< =E K'4&# 2%1$%&
 04%*5 &")& ,"#1#:#1 3%' $% &% %* &"# H*$.40"      3%' +4+*B& .47# 6)&0<B
 6%)0& 3%' 24*+ ) *'/-#1 %2 -)&"4*$ /)6"4*#0
 4* &"# 0#)5 0%/# 6"4.+1#* +4$$4*$ 4* &"# 0)*+     =T%& .47# 6)&0AB 614#+ &"# O%'0#5 4* ) 0"14..5 ()0;
 ,4&" ,%%+#* 0()+#05 &"#* ) 1%, %2 .%+$4*$         04%*)&# :%46#< =?%'.+ UNV .47# 6)&0 42 3%' ,#1#
 "%'0#05 )*+ -#"4*+ &"#/ ) 1)4.,)3 0&)&4%*<I       /#MB
 F%,#:#15 0"# 0%%* /)+# %'& &")& 0"# ,)0 4*
 &"# (%%. %2 &#)10 ,"46" 0"# ")+ ,#(& ,"#*
 0"# ,)0 *4*# 2##& "4$"<

 =E ,40" E ")+*B& 614#+ 0% /'6"AB 0)4+ @.46#5 )0
 0"# 0,)/ )-%'&5 &134*$ &% 24*+ "#1 ,)3 %'&< =E
 0").. -# ('*40"#+ 2%1 4& *%,5 E 0'((%0#5 -3
 -#4*$ +1%,*#+ 4* /3 %,* &#)10A >")& ?EJJ -#
 ) K'##1 &"4*$5 &% -# 0'1#A F%,#:#15 #:#13&"4*$
 40 K'##1 &%;+)3<B

 L'0& &"#* 0"# "#)1+ 0%/#&"4*$ 0(.)0"4*$
 )-%'& 4* &"# (%%. ) .4&&.# ,)3 %225 )*+ 0"#
 0,)/ *#)1#1 &% /)7# %'& ,")& 4& ,)08 )& 2410&
 0"# &"%'$"& 4& /'0& -# ) ,).1'0 %1 "4((%(%&;
 )/'05 -'& &"#* 0"# 1#/#/-#1#+ "%, 0/)..
 0"# ,)0 *%,5 )*+ 0"# 0%%* /)+# %'& &")& 4&
 ,)0 %*.3 ) /%'0# &")& ")+ 0.4((#+ 4* .47#
 "#10#.2<


HyphenlightedParagraph
IconizedParagraph
• Input text: "Hello file://smiley.jpeg world"
• Events: [{"text":"Hello", …}, {"text":"file://
  smiley.jpg", "type":"Image", "width":16,
  "height":16}, {"text":"world", …}]
• draw method picks and renders image
  events…
*"56 N35 *$, /3';,( #3 ;,# 34# 3= #$"# ("-1
$"//& "'( 5"'(,- "%34# "23'; #$3*, %,(* 3=
%-0;$# =/35,-* "'( #$3*, !33/ =34'#"0'*& %4#
*$, !34/( '3# ,+,' ;,# $,- $,"( #$-34;$ #$,
(33-5".G >"'( ,+,' 0= 2. $,"( 534/( ;3
#$-34;$&) #$34;$# <33- :/0!,& >0# 534/( %, 3=
+,-. /0##/, 4*, 50#$34# 2. *$34/(,-*6 K$& $35 8
50*$ 8 !34/( *$4# 4< /01, " #,/,*!3<,F 8 #$0'1 8
!34/(& 0= 8 3'/. 1'35 $35 #3 %,;0'6) O3-& .34
*,,& *3 2"'. 34#L3=L#$,L5". #$0';* $"(
$"<<,',( /"#,/.& #$"# :/0!, $"( %,;4' #3 #$0'1
#$"# +,-. =,5 #$0';* 0'(,,( 5,-, -,"//.
       IconizedParagraph
02<3**0%/,6
CHAPTER II

The Pool of Tears

`Curiouser       and curiouser!' cried Alice (she
was so much surprised, that for the moment she
quite forgot how to speak good English); `now
I'm opening out like the largest telescope that
ever was! Good-bye, feet!' (for when she looked
down at her feet, they seemed to be almost out of
sight, they were getting so far off). `Oh, my poor
        GraphicsParagraph
little feet, I wonder who will put on your shoes
and stockings for you now, dears? I'm sure _I_
shan't be able! I shall be a great deal too far off to
ReportLab Paragraph                  CountingParagraph

 If you need something that      0    If you need something that
 isn't on the feature list,      1    isn't on the feature list,
 please check the mailing-list   2    please check the mailing-list
 archives. Lots of features      3    archives. Lots of features
 are yet to be documented,       4    are yet to be documented,
 but most of the functionality   5    but most of the functionality
 has been commented in the       6    has been commented in the
 mailing-list. If you have a     7    mailing-list. If you have a




 problem that has not been       0    problem that has not been

      CountingParagraph
 dealt with yet...               1    dealt with yet...
Summary
Code Length
rlpara dinu$ pycount2.py *.py
   lines    code     doc comment    blank   file
    2380    1831      66      338     145   para-svn.py
    1432    1127     131       59     115   paragraph-svn.py
    1299     998     129       58     114   paragraph-2.1.py


alterparagraphs dinu$ pycount2.py *paragraph.py
   lines    code     doc comment   blank file
      48      30       0       2      16 colouredparagraph.py
     101      64       0       7      30 graphicsparagraph.py
      75      53       0       3      19 highlightedparagraph.py
     204     132       0      33      39 hyphenatedparagraph.py
     264     182       0      32      50 hyphenlightedparagraph.py
     186     128       0      11      47 iconizedparagraph.py
     202     111      25      13      53 minimalparagraph.py
     271     163      26      18      64 simpleparagraph.py
      31      15       2       4      10 ttfparagraph.py
$ run_performance_test.py --mnp 500 ../input/alice30.txt
input file: ../input/alice30.txt

                    Runtime
#words: 28200
#lines: 3854
#paragraphs: 500
Paragraph,              time needed: 0.564515 (s)
                        file size:   91901    (Byte)
MinimalParagraph,       time needed: 1.143239 (2.03 x)
                        file size:   210104   (2.29 x)
SimpleParagraph,        time needed: 1.872415 (3.32 x)
                        file size:   262991   (2.86 x)
TTFParagraph,           time needed: 1.635452 (2.90 x)
                        file size:   244040   (2.66 x)
ColouredParagraph,      time needed: 2.368929 (4.20 x)
                        file size:   544549   (5.93 x)
HyphenatedParagraph,    time needed: 4.455254 (4.86 x)
                        file size:   363638   (2.51 x)
HighlightedParagraph,   time needed: 2.958230 (3.23 x)
                        file size:   403546   (2.79 x)
HyphenlightedParagraph, time needed: 4.993915 (5.45 x)
                        file size:   413874   (2.86 x)
IconizedParagraph,      time needed: 1.979934 (3.51 x)
                        file size:   270026   (2.94 x)
GraphicsParagraph,      time needed: 1.799298 (3.19 x)
                        file size:   269538   (2.93 x)
Current State
• Family of paragraph classes
• Usually domain specific (e.g. kerning)
• Small code size
• Ca. 2–3 x slower than RL (pure text)
• Easier extensible than RL
Future
• Further Paragraph attributes
• KerningParagraph
• XMLParagraph (tags)
• General callback mechanism
• RTLParagraph? (Right to Left)
Links
•   http://www.dinu-gherman.net/tmp/
    alterparagraphs-0.3.2.tar.gz

•   http://www.reportlab.com

•   http://pypi.python.org/pypi/z3c.rml (z3c.rml)

•   http://deco-cow.sourceforge.net (wordaxe)
Questions?
            ” three questions, and that is enough,‘
’I have answered
      Said his father; ’don't give yourself airs!
   Do you think I can listen all day to such stuff?
        Be off, or I'll kick you down stairs!‘
                                        “
             Alice‘s Adventures in Wonderland, Lewis Carroll

Weitere ähnliche Inhalte

Kürzlich hochgeladen

activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfJamie (Taka) Wang
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Websitedgelyza
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxGDSC PJATK
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureEric D. Schabell
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesMd Hossain Ali
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Brian Pichman
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDELiveplex
 
Building AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxBuilding AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxUdaiappa Ramachandran
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostMatt Ray
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarPrecisely
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxMatsuo Lab
 

Kürzlich hochgeladen (20)

activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Website
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptx
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability Adventure
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
 
Building AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxBuilding AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptx
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity Webinar
 
20150722 - AGV
20150722 - AGV20150722 - AGV
20150722 - AGV
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptx
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 

ReportLab Paragraphs Reloaded-EuroPython 2008

  • 1. ReportLab Paragraphs Reloaded Dinu C. Gherman gherman@python.net EuroPython Conference 2008-07-07, Vilnius
  • 2. Agenda • ReportLab Overview • Paragraphs • Paragraphs Reloaded & Examples • Summary
  • 4. General Features • Generating PDF with Python (+ some C) • Content: fonts, graphics, images, tables • PDF features: page transitions, hyperlinks, outline, … • Graphics import as bitmaps and SVG (ext.) • Graphics export as bitmaps, PDF, EPS, SVG
  • 5. Technologies • PDF • Type1 and TrueType fonts • PIL • libart • Unicode (UTF-8)
  • 6. Meta Info • Developped since ca. 1996 • By Andy Robinson, Robin Becker, et al. • Current: SVN (v. 2.1 + 12 months) • Open Source • Closed Source: RML, PDF encryption, PDF import
  • 7. 1st Layer: Canvas • Corresponds to a single page with • Text, • Graphics, • PDF features (hyperlinks, page transitions...) • Can also be saved as a bitmap, EPS, SVG
  • 8. Example 1 #!/usr/bin/env python # _*_ coding: UTF-8 _*_ from reportlab.pdfgen.canvas import Canvas from reportlab.lib.pagesizes import A4 canv = Canvas("helloworld.pdf", pagesize=A4) ### ... canv.showPage() canv.save() …
  • 9. ### from reportlab.lib import colors from reportlab.lib.units import cm # circle canv.setStrokeColor(colors.green) canv.setFillColor(colors.red) canv.setLineWidth(0.5*cm) x, y = 10*cm, 10*cm canv.circle(x, y, 5*cm, stroke=True, fill=True) Hello world! # text canv.setFillColor(colors.yellow) canv.setFont("Helvetica", 36) canv.drawCentredString(x, y, u"Hello world!")
  • 10. 2nd Layer: Platypus • ”Page LAyout TYPography Using Scripts“ • Frames • PageTemplate • DocumentTemplate • Content: Flowables & Styles (”Story“) • Rendered as PDF document
  • 11. Structure Flow. Flow. Flow. Frame Flow. Flow. Flow. Flow. Flow. Flow. Flow. Flow. Flow. Flow. Frame Frame Frame Frame PageTemplate PageTemplate DocumentTemplate
  • 12. Flowables • Content related: Paragraph, Preformatted, Image, Table, XBox, Spacer, … • Logic related: FrameBreak, PageBreak, CondPageBreak, … • Layout related: KeepWithNext, KeepInFrame, …
  • 13. Example 2 from reportlab.lib.units import cm from reportlab.lib.pagesizes import A4 from reportlab.pdfgen.canvas import Canvas from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, Paragraph from reportlab.lib.styles import getSampleStyleSheet from django.contrib.webdesign import lorem_ipsum as li PAGESIZE = A4 …
  • 14. class TwoColumnDocTemplate(BaseDocTemplate): "A simple two-column document template." def __init__(self, filename, **kw): m = margin = 2*cm tm = topMargin = 2*cm bm = bottomMargin = 2*cm cw, ch = (PAGESIZE[0]-2*m)/2., (PAGESIZE[1]-tm) leftCol = Frame(m, bm, cw-0.75*cm, ch-tm, leftPadding=0, topPadding=0, rightPadding=0, bottomPadding=0, id="left", showBoundary=True ) rightCol = Frame(cw+2.7*cm, bm, cw-0.75*cm, ch-tm, leftPadding=0, topPadding=0, rightPadding=0, bottomPadding=0, id="right", showBoundary=True ) apply(BaseDocTemplate.__init__, (self, filename), kw) allPages = PageTemplate("all", [leftCol, rightCol]) self.addPageTemplates([allPages]) …
  • 15. explicabo distinctio animi ad ipsam veniam enim, Maiores cupiditate placeat fugit quis recusandae amet eveniet praesentium def generateTwoColDocument(outPath): veniam obcaecati consectetur maxime delectus? Dolorem perferendis accusantium Harum molestias iure at nemo labore quod repellat veniam optio quas ducimus eum similique, incidunt facilis itaque "Create a 2-col doc with rand. text." obcaecati iusto fugiat, enim unde voluptas illo? Enim Quidem explicabo officiis quasi soluta exercitationem eaque repudiandae cupiditate ad accusantium, alias blanditiis ullam nobis suscipit praesentium? Nostrum error tempore ducimus a dicta aut voluptates vitae, quaerat ullam recusandae esse nulla maiores eos error cupiditate assumenda quia culpa id illum rerum eligendi adipisci consequatur dolores, sequi cum ipsam ipsum, quisquam blanditiis corporis fugiat veniam dolor voluptates ipsa tempora, quibusdam excepturi facilis quaerat exercitationem cum tempore nostrum quasi labore nobis perspiciatis illo eaque vero voluptas repudiandae? Eos hic reiciendis excepturi pariatur quos? Ipsum odio ipsa quidem amet impedit recusandae ad esse. stylesheet = getSampleStyleSheet() recusandae quis, corporis cupiditate laboriosam alias ratione tempore? Exercitationem voluptates alias aspernatur odio laboriosam dolores unde vero. Excepturi sed repellendus facere Blanditiis quo at consectetur impedit, iure fugiat sed ullam h1 = stylesheet['Heading1'] voluptate nesciunt temporibus facilis, dignissimos aspernatur maiores assumenda nostrum, error nisi accusamus officiis quo deleniti facere recusandae Ipsum omnis deleniti saepe sapiente, quibusdam neque aspernatur delectus quasi iusto a facilis, tenetur nostrum incidunt nesciunt veritatis, velit sunt nostrum h2 = stylesheet['Heading2'] animi quidem ea excepturi, recusandae quasi dolor quo quae necessitatibus? Delectus suscipit soluta nulla molestiae unde repellendus odit sint non officia veniam harum sunt, laudantium iusto voluptatibus, omnis. fuga facere nihil sed aspernatur placeat, impedit libero Cupiditate minima pariatur itaque alias suscipit, nulla repellendus laudantium nisi nihil eveniet reiciendis? bt = stylesheet['BodyText'] culpa atque deleniti id et tenetur aliquid unde qui vel Exercitationem nemo possimus debitis? Aliquid sint, cumque rerum maiores voluptate, quas et quia? nesciunt cum natus eveniet obcaecati fugiat Quam debitis praesentium vitae, nesciunt quas repellendus, et numquam odit velit alias, dolor aut distinctio quisquam, impedit tempora architecto aut? quasi ut tempora itaque nemo earum animi, ipsa Perspiciatis et ullam sit commodi cumque optio similique natus inventore nobis sed quia eaque totam pariatur, eum totam minus et quis, vero itaque tempore incidunt dolorum, molestias rem blanditiis ad molestias eius sed eligendi veniam quae dolore autem. doloribus, unde rem odit similique sapiente eveniet? st = story = [] Tempora voluptatibus quo dicta expedita tempore harum porro? Cumque blanditiis ut facilis quasi Cupiditate possimus dignissimos laborum consectetur laudantium, illum ipsa perferendis adipisci veritatis p = li.words(3, common=False) Aut omnis atque molestiae est inventore delectus ipsam a commodi, tempora ratione unde quia non nemo voluptate, assumenda molestias unde aperiam pariatur nobis dolores, quisquam corporis iste quaerat quisquam cumque debitis, ea incidunt odit expedita illum atque ea sint doloribus iusto nemo, amet quidem facilis, molestiae quam sint doloremque officia nemo explicabo qui. Libero maxime magnam, dolores p = p.capitalize() nesciunt dolor commodi accusantium cumque ipsum, praesentium illum pariatur? Dicta nobis culpa placeat quaerat quos nisi dolorem libero eaque at, nobis eaque tenetur repellat distinctio pariatur debitis praesentium, omnis labore libero magnam officia. Quis aperiam exercitationem repudiandae dolore et fugiat neque? tempore perferendis asperiores pariatur cum, st.append(Paragraph(p, style=h1)) Doloremque et non architecto quas, laudantium accusamus error ratione, consectetur minus saepe repellat a deserunt minima explicabo beatae possimus, veritatis harum, similique aliquid exercitationem cum facilis fugit similique ad porro sapiente suscipit odit assumenda, natus unde non veniam quas illum enim alias quod qui excepturi, autem provident fugiat amet sequi quis molestias. for i in range(10): pariatur ullam perferendis ipsa fugit. Minus fugiat sint consequatur delectus necessitatibus eius eum. Voluptate sit ratione nobis aperiam omnis fugit Mollitia amet voluptatum facere blanditiis p = li.words(5, common=False) accusantium totam sequi accusamus, nulla perspiciatis ut corporis eos possimus, ducimus id veniam earum, Et ullam placeat ut accusamus recusandae quidem molestias ipsa dolorum aut eligendi doloremque totam veritatis voluptatibus. Officia quae voluptates laudantium atque aliquam voluptatibus hic esse, necessitatibus beatae atque laudantium voluptas voluptate veritatis sequi vero, dolore asperiores at p = p.capitalize() explicabo amet assumenda eaque autem molestiae exercitationem fugiat quasi sequi? Facilis tenetur qui molestias iusto eum ab necessitatibus, voluptatibus eveniet obcaecati saepe porro repellat doloremque quis minus? Distinctio eos dolore corporis corrupti magni, dolor assumenda error recusandae rem ducimus facilis iste doloribus nisi eligendi. st.append(Paragraph(p, style=h2)) for j in range(3): p = li.paragraph() st.append(Paragraph(p, style=bt)) doc = TwoColumnDocTemplate(outPath, pagesize=PAGESIZE) doc.build(story)
  • 16. 3rd Layer: RML • ”Report Markup Language“ • Platypus in XML + Black Box + ¥$€ • See also: z3c.rml (S. Richter et al. – free) • PageCatcher (more ¥$€) for PDF import • See also: one of my next announcements…
  • 18. Features • Subclass of the Flowable class • Core class in Platypus (paragraph.py) • No alternative (except para.py – R.I.P.) • Central feature: linebreaks • Knows style attributes
  • 19. Global Style Attributes • fontName, fontSize, textColor, backColor • firstLineIndent, leftIndent, rightIndent • alignment, leading, (spaceBefore, spaceAfter) • bulletColor, bulletFontName, bulletFontSize, bulletIndent, bulletOffsetY • Sample: stylesheet = getSampleStyleSheet() bt = stylesheet['BodyText'] bt.leading = 16 bt.textColor = colors.blue
  • 20. Local Style Attributes • XML tags in paragraph text: • font, br, b, i, u, strong, strike, a, link, img • superscript, subscript, greek • seq, seqDefault, seqReset • Sample: t = "Hello <font color='red'>red</font> world!" p = Paragraph(t, style=myStyle)
  • 21. Lacking… • Inline images (new in SVN) • Hyphenation • Kerning • Code comprehensibility • Code extensibility ”Reporting Solutions“!? Efficiency!?
  • 23. New Approach • New Flowable! • MinimalParagraph class • Easily extensible (shown in subclasses) • Linebreaks (and not much more)! • Critical methods: wrap, split, draw
  • 24. Sample: XBox class XBox(Flowable): def __init__(self, width, height, text='A Box'): Flowable.__init__(self) self.width, self.height, self.text = width, height, text def draw(self): canv, w, h = self.canv, self.width, self.height canv.rect(0, 0, w, h) canv.line(0, 0, w, h) canv.line(0, h, w, 0) canv.setFont('Times-Roman', 12) canv.drawCentredString(0.5*w, 0.5*h, self.text) # inherited by Flowable: def wrap(self, availWidth, availHeight): return (self.width, self.height) def split(self, availWidth, availheight): return []
  • 25. Key Idea: ”Events“ • Input text: "Hello world" • Parsed: [{"text":"Hello"}, {"text":"world"}] • Word widths: [{"text":"Hello", "width":10}, {text:"world", "width":11}] • Placement: [{"text":"Hello", "width":10, "pos":(10, 5)}, {"text":"world", "width":11, "pos":(23, 5)}] • Add attributes as needed
  • 26. MinimalParagraph • Global attributes: fontName, fontSize, leading, firstLineIndent, leftIndent, rightIndent, textColor, (spaceBefore, spaceAfter) • No alignment (left only), … • Focus on linebreaks and RL compliance
  • 27. Alice was beginning to get very tired of sitting well, and noticed that they were filled with by her sister on the bank, and of having cupboards and book-shelves; here and there nothing to do: once or twice she had peeped she saw maps and pictures hung upon pegs. into the book her sister was reading, but it She took down a jar from one of the shelves had no pictures or conversations in it, `and as she passed; it was labelled `ORANGE what is the use of a book,' thought Alice MARMALADE', but to her great `without pictures or conversation?' disappointment it was empty: she did not like to drop the jar for fear of killing somebody, so So she was considering in her own mind (as managed to put it into one of the cupboards well as she could, for the hot day made her as she fell past it. feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be `Well!' thought Alice to herself, `after such a worth the trouble of getting up and picking fall as this, I shall think nothing of tumbling the daisies, when suddenly a White Rabbit down stairs! How brave they'll all think me at with pink eyes ran close by her. home! Why, I wouldn't say anything about it, even if I fell off the top of the house!' (Which There was nothing so VERY remarkable in was very likely true.) that; nor did Alice think it so VERY much out of the way to hear the Rabbit say to itself, Down, down, down. Would the fall NEVER `Oh dear! Oh dear! I shall be late!' (when she come to an end! `I wonder how many miles thought it over afterwards, it occurred to her I've fallen by this time?' she said aloud. `I that she ought to have wondered at this, but must be getting somewhere near the centre at the time it all seemed quite natural); but of the earth. Let me see: that would be four when the Rabbit actually TOOK A WATCH thousand miles down, I think--' (for, you see, OUT OF ITS WAISTCOAT- POCKET, and Alice had learnt several things of this sort in MinimalParagraph looked at it, and then hurried on, Alice her lessons in the schoolroom, and though started to her feet, for it flashed across her this was not a VERY good opportunity for mind that she had never before seen a rabbit showing off her knowledge, as there was no with either a waistcoat-pocket, or a watch to one to listen to her, still it was good practice take out of it, and burning with curiosity, she to say it over) `--yes, that's about the right ran across the field after it, and fortunately distance--but then I wonder what Latitude or was just in time to see it pop down a large Longitude I've got to?' (Alice had no idea
  • 28. ColouredParagraph #!/bin/env/python def draw(self): # -*- coding: utf-8 -*- "Render words in paragraph on randomly coloured background." "An example for a coloured paragraph subclass." if not self.words: return import random canvas = self.canv style = self.style from reportlab.lib import colors canvas.saveState() from minimalparagraph import MinimalParagraph canvas.setFont(style.fontName, style.fontSize) for word in self.words: RL_COLORS = [v for (k, v) in if "meta" in word or not "pos" in word: colors.__dict__.items() continue if isinstance(v, colors.Color)] text, (x, y) = word["text"], word["pos"] col = random.choice(RL_COLORS) canvas.setStrokeColor(col) class ColouredParagraph(MinimalParagraph): canvas.setFillColor(col) "A colourful tiny subclass canvas.rect(x, y - self.dy, of MinimalParagraph." word["width"], style.fontSize, fill=True, stroke=True) canvas.setFillColor(style.textColor) canvas.drawString(x, y - self.dy, text) canvas.restoreState()
  • 29. !"#$% &'( )# *+(, -+( .+(,/ 0 $#")-123 4") 1+(L5#6-E ,5- !"-6( )#$" +") 6##!-) +6#"8 (5- 5-1- 467*- .-8+" (# 8-( 1+(5-1 ,6--9:/ +") 9+,,+8- 7"(# (5- 6#C-67-,( 8+1)-" :#' -C-1 $-"( #" ,+:7"8 (# 5-1,-6;/ 7" + )1-+<: ,#1( #; ,+$% N#$ ,5- 6#"8-) (# 8-( #'( #; (5+( )+1! $+:/ =># *+(, -+( .+(,2 ># *+(, -+( .+(,23 +") 5+66/ +") $+")-1 +.#'( +<#"8 (5#,- .-), #; ,#<-(7<-,/ =># .+(, -+( *+(,23 ;#1/ :#' ,--/ +, .1785( ;6#$-1, +") (5#,- *##6 ;#'"(+7",/ .'( ,5- *#'6)"3( +",$-1 -7(5-1 ?'-,(7#"/ 7( )7)"3( ,5- *#'6) "#( -C-" 8-( 5-1 5-+) (51#'85 (5- <'*5 <+((-1 $57*5 $+: ,5- 9'( 7(% @5- ;-6( )##1$+:G =+") -C-" 7; <: 5-+) $#'6) 8# (5+( ,5- $+, )#A7"8 #;;/ +") 5+) B',( .-8'" (# (51#'85/3 (5#'85( 9##1 467*-/ =7( $#'6) .- #; )1-+< (5+( ,5- $+, $+6!7"8 5+") 7" 5+") $7(5 C-1: 67((6- ',- $7(5#'( <: ,5#'6)-1,% K5/ 5#$ 0 >7"+5/ +") ,+:7"8 (# 5-1 C-1: -+1"-,(6:/ =D#$/ $7,5 0 *#'6) ,5'( '9 67!- + (-6-,*#9-F 0 (57"! 0 >7"+5/ (-66 <- (5- (1'(5E )7) :#' -C-1 -+( + *#'6)/ 7; 0 #"6: !"#$ 5#$ (# .-87"%3 O#1/ :#' .+(23 $5-" ,'))-"6:/ (5'<9F (5'<9F )#$" ,--/ ,# <+": #'(L#;L(5-L$+: (57"8, 5+) ,5- *+<- '9#" + 5-+9 #; ,(7*!, +") )1: 6-+C-,/ 5+99-"-) 6+(-6:/ (5+( 467*- 5+) .-8'" (# (57"! +") (5- ;+66 $+, #C-1% (5+( C-1: ;-$ (57"8, 7")--) $-1- 1-+66: 7<9#,,7.6-% 467*- $+, "#( + .7( 5'1(/ +") ,5- B'<9-) '9 #" (# 5-1 ;--( 7" + <#<-"(E ,5- 6##!-) '9/ .'( 7( J5-1- ,--<-) (# .- "# ',- 7" $+7(7"8 .: (5- $+, +66 )+1! #C-15-+)G .-;#1- 5-1 $+, +"#(5-1 67((6- )##1/ ,# ,5- $-"( .+*! (# (5- (+.6-/ 5+6; 6#"8 9+,,+8-/ +") (5- H57(- I+..7( $+, ,(766 7" 5#97"8 ,5- <785( ;7") +"#(5-1 !-: #" 7(/ #1 +( ,785(/ 5'11:7"8 )#$" 7(% J5-1- $+, "#( + +": 1+(- + .##! #; 1'6-, ;#1 ,5'((7"8 9-#96- '9 <#<-"( (# .- 6#,(E +$+: $-"( 467*- 67!- (5- 67!- (-6-,*#9-,E (57, (7<- ,5- ;#'") + 67((6- $7")/ +") $+, B',( 7" (7<- (# 5-+1 7( ,+:/ +, 7( .#((6- #" 7(/ P=$57*5 *-1(+7"6: $+, "#( 5-1- ('1"-) + *#1"-1/ =K5 <: -+1, +") $57,!-1,/ .-;#1-/3 ,+7) 467*-/Q +") 1#'") (5- "-*! #; (5- 5#$ 6+(- 7(3, 8-((7"8F3 @5- $+, *6#,- .-57") 7( .#((6- $+, + 9+9-1 6+.-6/ $7(5 (5- $#1), $5-" ,5- ('1"-) (5- *#1"-1/ .'( (5- I+..7( =>I0DR ST3 .-+'(7;'66: 917"(-) #" 7( 7" 6+18- ColouredParagraph $+, "# 6#"8-1 (# .- ,--"E ,5- ;#'") 5-1,-6; 7" 6-((-1,% + 6#"8/ 6#$ 5+66/ $57*5 $+, 67( '9 .: + 1#$ #; 6+<9, 5+"87"8 ;1#< (5- 1##;% 0( $+, +66 C-1: $-66 (# ,+: =>17"! <-/3 .'( (5- $7,- 67((6- 467*- $+, "#( 8#7"8 (# )# JN4J 7" + J5-1- $-1- )##1, +66 1#'") (5- 5+66/ .'( (5-: 5'11:% =D#/ 0366 6##! ;71,(/3 ,5- ,+7)/ =+") ,-- $-1- +66 6#*!-)G +") $5-" 467*- 5+) .--" +66 $5-(5-1 7(3, <+1!-) U9#7,#"U #1 "#(3G ;#1 ,5- (5- $+: )#$" #"- ,7)- +") '9 (5- #(5-1/ 5+) 1-+) ,-C-1+6 "7*- 67((6- 57,(#17-, +.#'(
  • 30. !"#$% &'( )# *+(, -+( .+(,/ 0 $#")-123 4") 1+(L5#6-E ,5- !"-6( )#$" +") 6##!-) +6#"8 (5- 5-1- 467*- .-8+" (# 8-( 1+(5-1 ,6--9:/ +") 9+,,+8- 7"(# (5- 6#C-67-,( 8+1)-" :#' -C-1 $-"( #" ,+:7"8 (# 5-1,-6;/ 7" + )1-+<: ,#1( #; ,+$% N#$ ,5- 6#"8-) (# 8-( #'( #; (5+( )+1! $+:/ =># *+(, -+( .+(,2 ># *+(, -+( .+(,23 +") 5+66/ +") $+")-1 +.#'( +<#"8 (5#,- .-), #; ,#<-(7<-,/ =># .+(, -+( *+(,23 ;#1/ :#' ,--/ +, .1785( ;6#$-1, +") (5#,- *##6 ;#'"(+7",/ .'( ,5- *#'6)"3( +",$-1 -7(5-1 ?'-,(7#"/ 7( )7)"3( ,5- *#'6) "#( -C-" 8-( 5-1 5-+) (51#'85 (5- <'*5 <+((-1 $57*5 $+: ,5- 9'( 7(% @5- ;-6( )##1$+:G =+") -C-" 7; <: 5-+) $#'6) 8# (5+( ,5- $+, )#A7"8 #;;/ +") 5+) B',( .-8'" (# (51#'85/3 (5#'85( 9##1 467*-/ =7( $#'6) .- #; )1-+< (5+( ,5- $+, $+6!7"8 5+") 7" 5+") $7(5 C-1: 67((6- ',- $7(5#'( <: ,5#'6)-1,% K5/ 5#$ 0 >7"+5/ +") ,+:7"8 (# 5-1 C-1: -+1"-,(6:/ =D#$/ $7,5 0 *#'6) ,5'( '9 67!- + (-6-,*#9-F 0 (57"! 0 >7"+5/ (-66 <- (5- (1'(5E )7) :#' -C-1 -+( + *#'6)/ 7; 0 #"6: !"#$ 5#$ (# .-87"%3 O#1/ :#' .+(23 $5-" ,'))-"6:/ (5'<9F (5'<9F )#$" ,--/ ,# <+": #'(L#;L(5-L$+: (57"8, 5+) ,5- *+<- '9#" + 5-+9 #; ,(7*!, +") )1: 6-+C-,/ 5+99-"-) 6+(-6:/ (5+( 467*- 5+) .-8'" (# (57"! +") (5- ;+66 $+, #C-1% (5+( C-1: ;-$ (57"8, 7")--) $-1- 1-+66: 7<9#,,7.6-% 467*- $+, "#( + .7( 5'1(/ +") ,5- B'<9-) '9 #" (# 5-1 ;--( 7" + <#<-"(E ,5- 6##!-) '9/ .'( 7( J5-1- ,--<-) (# .- "# ',- 7" $+7(7"8 .: (5- $+, +66 )+1! #C-15-+)G .-;#1- 5-1 $+, +"#(5-1 67((6- )##1/ ,# ,5- $-"( .+*! (# (5- (+.6-/ 5+6; 6#"8 9+,,+8-/ +") (5- H57(- I+..7( $+, ,(766 7" 5#97"8 ,5- <785( ;7") +"#(5-1 !-: #" 7(/ #1 +( ,785(/ 5'11:7"8 )#$" 7(% J5-1- $+, "#( + +": 1+(- + .##! #; 1'6-, ;#1 ,5'((7"8 9-#96- '9 <#<-"( (# .- 6#,(E +$+: $-"( 467*- 67!- (5- 67!- (-6-,*#9-,E (57, (7<- ,5- ;#'") + 67((6- $7")/ +") $+, B',( 7" (7<- (# 5-+1 7( ,+:/ +, 7( .#((6- #" 7(/ P=$57*5 *-1(+7"6: $+, "#( 5-1- ('1"-) + *#1"-1/ =K5 <: -+1, +") $57,!-1,/ .-;#1-/3 ,+7) 467*-/Q +") 1#'") (5- "-*! #; (5- 5#$ 6+(- 7(3, 8-((7"8F3 @5- $+, *6#,- .-57") 7( .#((6- $+, + 9+9-1 6+.-6/ $7(5 (5- $#1), $5-" ,5- ('1"-) (5- *#1"-1/ .'( (5- I+..7( =>I0DR ST3 .-+'(7;'66: 917"(-) #" 7( 7" 6+18- HighlightedParagraph $+, "# 6#"8-1 (# .- ,--"E ,5- ;#'") 5-1,-6; 7" 6-((-1,% + 6#"8/ 6#$ 5+66/ $57*5 $+, 67( '9 .: + 1#$ #; 6+<9, 5+"87"8 ;1#< (5- 1##;% 0( $+, +66 C-1: $-66 (# ,+: =>17"! <-/3 .'( (5- $7,- 67((6- 467*- $+, "#( 8#7"8 (# )# JN4J 7" + J5-1- $-1- )##1, +66 1#'") (5- 5+66/ .'( (5-: 5'11:% =D#/ 0366 6##! ;71,(/3 ,5- ,+7)/ =+") ,-- $-1- +66 6#*!-)G +") $5-" 467*- 5+) .--" +66 $5-(5-1 7(3, <+1!-) U9#7,#"U #1 "#(3G ;#1 ,5- (5- $+: )#$" #"- ,7)- +") '9 (5- #(5-1/ 5+) 1-+) ,-C-1+6 "7*- 67((6- 57,(#17-, +.#'(
  • 31. R1#*6" .#00%*;-%%7< >"# O%'0# $):# ) ")+ 0%/#"%, 2)..#* 4*&% &"# 0#)5 =)*+ 4* &")& 0'++#* .#)( %'& %2 &"# ,)&#15 )*+ 0##/#+ &% 6)0# E 6)* $% -)67 -3 1)4.,)35B 0"# 0)4+ &% K'4:#1 ).. %:#1 ,4&" 214$"&< =N"5 E -#$ 3%'1 "#10#.2< G@.46# ")+ -##* &% &"# 0#)04+# %*6# 4* ()1+%*AB 614#+ @.46# ")0&4.35 )21)4+ &")& 0"# ")+ "#1 .42#5 )*+ ")+ 6%/# &% &"# $#*#1). 6%*6.'; "'1& &"# (%%1 )*4/).B0 2##.4*$0< =E K'4&# 2%1$%& 04%*5 &")& ,"#1#:#1 3%' $% &% %* &"# H*$.40" 3%' +4+*B& .47# 6)&0<B 6%)0& 3%' 24*+ ) *'/-#1 %2 -)&"4*$ /)6"4*#0 4* &"# 0#)5 0%/# 6"4.+1#* +4$$4*$ 4* &"# 0)*+ =T%& .47# 6)&0AB 614#+ &"# O%'0#5 4* ) 0"14..5 ()0; ,4&" ,%%+#* 0()+#05 &"#* ) 1%, %2 .%+$4*$ 04%*)&# :%46#< =?%'.+ UNV .47# 6)&0 42 3%' ,#1# "%'0#05 )*+ -#"4*+ &"#/ ) 1)4.,)3 0&)&4%*<I /#MB F%,#:#15 0"# 0%%* /)+# %'& &")& 0"# ,)0 4* &"# (%%. %2 &#)10 ,"46" 0"# ")+ ,#(& ,"#* 0"# ,)0 *4*# 2##& "4$"< =E ,40" E ")+*B& 614#+ 0% /'6"AB 0)4+ @.46#5 )0 0"# 0,)/ )-%'&5 &134*$ &% 24*+ "#1 ,)3 %'&< =E 0").. -# ('*40"#+ 2%1 4& *%,5 E 0'((%0#5 -3 -#4*$ +1%,*#+ 4* /3 %,* &#)10A >")& ?EJJ -# ) K'##1 &"4*$5 &% -# 0'1#A F%,#:#15 #:#13&"4*$ 40 K'##1 &%;+)3<B L'0& &"#* 0"# "#)1+ 0%/#&"4*$ 0(.)0"4*$ )-%'& 4* &"# (%%. ) .4&&.# ,)3 %225 )*+ 0"# 0,)/ *#)1#1 &% /)7# %'& ,")& 4& ,)08 )& 2410& 0"# &"%'$"& 4& /'0& -# ) ,).1'0 %1 "4((%(%&; )/'05 -'& &"#* 0"# 1#/#/-#1#+ "%, 0/).. 0"# ,)0 *%,5 )*+ 0"# 0%%* /)+# %'& &")& 4& ,)0 %*.3 ) /%'0# &")& ")+ 0.4((#+ 4* .47# "#10#.2< HyphenatedParagraph
  • 32. R1#*6" .#00%*;-%%7< >"# O%'0# $):# ) ")+ 0%/#"%, 2)..#* 4*&% &"# 0#)5 =)*+ 4* &")& 0'++#* .#)( %'& %2 &"# ,)&#15 )*+ 0##/#+ &% 6)0# E 6)* $% -)67 -3 1)4.,)35B 0"# 0)4+ &% K'4:#1 ).. %:#1 ,4&" 214$"&< =N"5 E -#$ 3%'1 "#10#.2< G@.46# ")+ -##* &% &"# 0#)04+# %*6# 4* ()1+%*AB 614#+ @.46# ")0&4.35 )21)4+ &")& 0"# ")+ "#1 .42#5 )*+ ")+ 6%/# &% &"# $#*#1). 6%*6.'; "'1& &"# (%%1 )*4/).B0 2##.4*$0< =E K'4&# 2%1$%& 04%*5 &")& ,"#1#:#1 3%' $% &% %* &"# H*$.40" 3%' +4+*B& .47# 6)&0<B 6%)0& 3%' 24*+ ) *'/-#1 %2 -)&"4*$ /)6"4*#0 4* &"# 0#)5 0%/# 6"4.+1#* +4$$4*$ 4* &"# 0)*+ =T%& .47# 6)&0AB 614#+ &"# O%'0#5 4* ) 0"14..5 ()0; ,4&" ,%%+#* 0()+#05 &"#* ) 1%, %2 .%+$4*$ 04%*)&# :%46#< =?%'.+ UNV .47# 6)&0 42 3%' ,#1# "%'0#05 )*+ -#"4*+ &"#/ ) 1)4.,)3 0&)&4%*<I /#MB F%,#:#15 0"# 0%%* /)+# %'& &")& 0"# ,)0 4* &"# (%%. %2 &#)10 ,"46" 0"# ")+ ,#(& ,"#* 0"# ,)0 *4*# 2##& "4$"< =E ,40" E ")+*B& 614#+ 0% /'6"AB 0)4+ @.46#5 )0 0"# 0,)/ )-%'&5 &134*$ &% 24*+ "#1 ,)3 %'&< =E 0").. -# ('*40"#+ 2%1 4& *%,5 E 0'((%0#5 -3 -#4*$ +1%,*#+ 4* /3 %,* &#)10A >")& ?EJJ -# ) K'##1 &"4*$5 &% -# 0'1#A F%,#:#15 #:#13&"4*$ 40 K'##1 &%;+)3<B L'0& &"#* 0"# "#)1+ 0%/#&"4*$ 0(.)0"4*$ )-%'& 4* &"# (%%. ) .4&&.# ,)3 %225 )*+ 0"# 0,)/ *#)1#1 &% /)7# %'& ,")& 4& ,)08 )& 2410& 0"# &"%'$"& 4& /'0& -# ) ,).1'0 %1 "4((%(%&; )/'05 -'& &"#* 0"# 1#/#/-#1#+ "%, 0/).. 0"# ,)0 *%,5 )*+ 0"# 0%%* /)+# %'& &")& 4& ,)0 %*.3 ) /%'0# &")& ")+ 0.4((#+ 4* .47# "#10#.2< HyphenlightedParagraph
  • 33. IconizedParagraph • Input text: "Hello file://smiley.jpeg world" • Events: [{"text":"Hello", …}, {"text":"file:// smiley.jpg", "type":"Image", "width":16, "height":16}, {"text":"world", …}] • draw method picks and renders image events…
  • 34. *"56 N35 *$, /3';,( #3 ;,# 34# 3= #$"# ("-1 $"//& "'( 5"'(,- "%34# "23'; #$3*, %,(* 3= %-0;$# =/35,-* "'( #$3*, !33/ =34'#"0'*& %4# *$, !34/( '3# ,+,' ;,# $,- $,"( #$-34;$ #$, (33-5".G >"'( ,+,' 0= 2. $,"( 534/( ;3 #$-34;$&) #$34;$# <33- :/0!,& >0# 534/( %, 3= +,-. /0##/, 4*, 50#$34# 2. *$34/(,-*6 K$& $35 8 50*$ 8 !34/( *$4# 4< /01, " #,/,*!3<,F 8 #$0'1 8 !34/(& 0= 8 3'/. 1'35 $35 #3 %,;0'6) O3-& .34 *,,& *3 2"'. 34#L3=L#$,L5". #$0';* $"( $"<<,',( /"#,/.& #$"# :/0!, $"( %,;4' #3 #$0'1 #$"# +,-. =,5 #$0';* 0'(,,( 5,-, -,"//. IconizedParagraph 02<3**0%/,6
  • 35. CHAPTER II The Pool of Tears `Curiouser and curiouser!' cried Alice (she was so much surprised, that for the moment she quite forgot how to speak good English); `now I'm opening out like the largest telescope that ever was! Good-bye, feet!' (for when she looked down at her feet, they seemed to be almost out of sight, they were getting so far off). `Oh, my poor GraphicsParagraph little feet, I wonder who will put on your shoes and stockings for you now, dears? I'm sure _I_ shan't be able! I shall be a great deal too far off to
  • 36. ReportLab Paragraph CountingParagraph If you need something that 0 If you need something that isn't on the feature list, 1 isn't on the feature list, please check the mailing-list 2 please check the mailing-list archives. Lots of features 3 archives. Lots of features are yet to be documented, 4 are yet to be documented, but most of the functionality 5 but most of the functionality has been commented in the 6 has been commented in the mailing-list. If you have a 7 mailing-list. If you have a problem that has not been 0 problem that has not been CountingParagraph dealt with yet... 1 dealt with yet...
  • 38. Code Length rlpara dinu$ pycount2.py *.py lines code doc comment blank file 2380 1831 66 338 145 para-svn.py 1432 1127 131 59 115 paragraph-svn.py 1299 998 129 58 114 paragraph-2.1.py alterparagraphs dinu$ pycount2.py *paragraph.py lines code doc comment blank file 48 30 0 2 16 colouredparagraph.py 101 64 0 7 30 graphicsparagraph.py 75 53 0 3 19 highlightedparagraph.py 204 132 0 33 39 hyphenatedparagraph.py 264 182 0 32 50 hyphenlightedparagraph.py 186 128 0 11 47 iconizedparagraph.py 202 111 25 13 53 minimalparagraph.py 271 163 26 18 64 simpleparagraph.py 31 15 2 4 10 ttfparagraph.py
  • 39. $ run_performance_test.py --mnp 500 ../input/alice30.txt input file: ../input/alice30.txt Runtime #words: 28200 #lines: 3854 #paragraphs: 500 Paragraph, time needed: 0.564515 (s) file size: 91901 (Byte) MinimalParagraph, time needed: 1.143239 (2.03 x) file size: 210104 (2.29 x) SimpleParagraph, time needed: 1.872415 (3.32 x) file size: 262991 (2.86 x) TTFParagraph, time needed: 1.635452 (2.90 x) file size: 244040 (2.66 x) ColouredParagraph, time needed: 2.368929 (4.20 x) file size: 544549 (5.93 x) HyphenatedParagraph, time needed: 4.455254 (4.86 x) file size: 363638 (2.51 x) HighlightedParagraph, time needed: 2.958230 (3.23 x) file size: 403546 (2.79 x) HyphenlightedParagraph, time needed: 4.993915 (5.45 x) file size: 413874 (2.86 x) IconizedParagraph, time needed: 1.979934 (3.51 x) file size: 270026 (2.94 x) GraphicsParagraph, time needed: 1.799298 (3.19 x) file size: 269538 (2.93 x)
  • 40. Current State • Family of paragraph classes • Usually domain specific (e.g. kerning) • Small code size • Ca. 2–3 x slower than RL (pure text) • Easier extensible than RL
  • 41. Future • Further Paragraph attributes • KerningParagraph • XMLParagraph (tags) • General callback mechanism • RTLParagraph? (Right to Left)
  • 42. Links • http://www.dinu-gherman.net/tmp/ alterparagraphs-0.3.2.tar.gz • http://www.reportlab.com • http://pypi.python.org/pypi/z3c.rml (z3c.rml) • http://deco-cow.sourceforge.net (wordaxe)
  • 43. Questions? ” three questions, and that is enough,‘ ’I have answered Said his father; ’don't give yourself airs! Do you think I can listen all day to such stuff? Be off, or I'll kick you down stairs!‘ “ Alice‘s Adventures in Wonderland, Lewis Carroll