SlideShare a Scribd company logo
1 of 43
Download to read offline
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

More Related Content

Recently uploaded

Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 

Recently uploaded (20)

Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

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