clone your own copy | download snapshot

Snapshots | iceberg

Inside this repository


Download raw (11.7 KB)

Title: Valentine scripting
Date: 2010-01-29 13:09
Author: OSP
Tags: Works, Open Office, Scripting, Standards + Formats
Slug: valentine-scripting
Status: published

[![]({filename}/images/uploads/openbaar_poster.jpg "openbaar_poster"){: .alignleft .size-medium .wp-image-3799 }]({filename}/images/uploads/openbaar_poster.jpg)  
<small>Poster and flyer designed and produced in OpenOffice</small>

This week and next, colleague and friend [An
Mertens](http://www.adashboard.org/) (a.k.a. Ana Foor) works out of the
Elsene local library [Sans Souci](http://www.elsene.bibliotheek.be/).
She'll be listening to your account of meeting a loved one for the first
time, those habits that keep your relationship alive or which imaginary
place you would like to visit with your best friend. Just like an
oldfashioned *Ecrivain Public*, Ana Foor will transform these
conversations into unique Valentine letters and -stories published on
the fly. In the waiting room, a selection of (Dutch language) romantic
literature is available, plus a choice of styles and formats presented
in a catalog developed/designed by OSP's Femke, Ludivine, Ivan, Nicolas
and Pierre M.  
For practical and conceptual reasons, we wanted to produce the
customised stories and letters with the help of the well-known word
processing tool OpenOffice, and were curious to see what could happen if
we'd use that same tool for designing and printing the catalog, poster
and invitation too. Most of all we couldn't resist to play with
[odfpy](http://opendocumentfellowship.com/projects/odfpy), a Python
library that can generate .odt documents from scratch. It got us into
various strange and exotic problems, just the way we like it :-)


![]({filename}/images/uploads/form.png "form"){: .alignleft .size-medium .wp-image-3799 }  
lists all possible styles presented in the catalog</small>

We designed a set of 6 basic lay-outs mixed with 9 different decorative
'spices' and this for three different types of content (story, poem or
letter). On top of that, there are three types of media to choose from
(web, A4 sheet and booklet). To help identify each of the styles, we
came up with a flexible system of re-combinatorial template names that
also somehow explains how the project works:

-   Sexy Maan
-   Lavendel Panter
-   Lungo Ijs
-   Espresso Stormen
-   Chocolade Valleien
-   Koraal Verlangen
-   Kristallen Maan
-   Roze Panter
-   Champagne Ijs

"*Unlike other more convenient APIs, this one is essentially an
abstraction layer just above the XML format. The main focus has been to
prevent the programmer from creating invalid documents.*"

Nicolas had pointed us to the
[odfpy](http://opendocumentfellowship.com/projects/odfpy) library a
while ago, and this lovely catalog seemed the ultimate opportunity to
experiment with it.
[odfpy](http://opendocumentfellowship.com/projects/odfpy) adds a
Python-scripting interface to OpenOffice; with the help of this library
you can dynamically generate files in the Open Document Format (.odt,
.ods). [odfpy](http://opendocumentfellowship.com/projects/odfpy) uses
OpenOffice in the background, but without its graphical user interface.

![]({filename}/images/uploads/odt.png "odt"){: .alignleft .size-medium .wp-image-3799 }  
<small>To see what elements an .odt-file consists of, 'extract' it like
a .zip or .tar file</small>

`<office:body><office:text><text:sequence-decls><text:sequence-decl text:display-outline-level="0" text:name="Illustration"/><text:sequence-decl text:display-outline-level="0" text:name="Table"/><text:sequence-decl text:display-outline-level="0" text:name="Text"/><text:sequence-decl text:display-outline-level="0" text:name="Drawing"/></text:sequence-decls><text:p text:style-name="Standard">Hello World</text:p></office:text></office:body>`

<small>Fragment of *content.xml*</small>

The Open Document format is written in a rather clean kind of
[xhtml,](http://ffff) which means it is legible compared to most other
Word Processing or Desktop Publishing files we looked at. Still that did
not mean it was evident how odfpy generates a frame, or calculates the
size of a font. The odfpy documentation is rudimentary; it provides
extensive information on the hierarchy of frames, elements and styles
but for example not a list of what style-options are available. While it
is nice to know at what point a frame needs to be generated, without the
syntax for a single or triple border, whether it is red or shaded you
can only guess. We designed sample files and than browsed their
'source', reverse engineering document settings and -styles with the
help of the Open Document file specifications. It obviously took us a
ridiculous amount of time to generate 162 different templates in this

`# -*- coding: utf-8 -*- # drawing hearts in the snow! from odf.opendocument import OpenDocumentText from odf.text import P, Span from odf.style import Style, TextProperties, ParagraphProperties, BackgroundImage, GraphicProperties from odf.draw import Frame, TextBox from texts import * from liblove import *`  
<small>From the header of character\_spices.py: A heartwarming

Even when the odfpy-scripts Ivan was writing and rewriting, started to
read more and more like love letters themselves ... even with our
general distrust of efficient methods ... would we have been better off
doing all this by hand? With the printer deadline approaching rapidly,
we had to settle for a very basic set of styles but managed to use
nearly every OSP font currently available. This publication will be both
a *stalenboek* and fontcatalog.

<small>After having installed odfpy, run `$ python  name_of_script.py`
in your commandline and generate many .odt files at once</small>

<small>Sneak preview: Drop the contents of this folder into
\[yourhomefolder\]/.fonts and restart OpenOffice</small>

**Output to different media**  
Our next concern was to generate a pdf that could be handled by the
in-house city council printer of Elsene. We had 162 A4 .odt files and
three A5 .pdf files (produced in Scribus) that needed to be combined
into one pdf. We wrote a bash-script that takes all .odt files inside a
folder, transforms them into pdf, resizes them from A4 to A5 and than
gathers all files into a multi-page pdf.

<small>Using some of our favorite tools: unoconv, ps2pdf, psresize and
pdftk transform a series of A4 .odt files into a multi-page A5

As we were working on generating the files until the last minute, we
failed to notice that we somehow introduced full color into a pdf that
would need to be printed in black-and-white. Also, the printer needed
PDF1.3 and we were generating default PDF1.4. In a quick fix, we added
[ghostscript]() to the already long list of pdf-tools used in the
bash-script; probably making many other steps redundant (ps2pdf has
ghostscript integrated for example) but no time for clean-up or rewrite.


Still not all trouble was over. Our printer reported that he was unable
to deal with part of the embedded fonts (Unable to read .ttf? Using an
old-style rip?) but probably inspired by our friendly persistance, he
figured out a way to transform our files into postscript once more,
regenerate the font-images from there and finally ... the file passed.

**Textflow and style names**

[![]({filename}/images/uploads/character.png "character"){: .alignleft .size-medium .wp-image-3799 }]({filename}/images/uploads/character.png)  
<small>OpenOffice: Where did the characterstyles go?</small>

The custom publications An will produce on the fly are based on the same
.odt templates that we printed in the catalog. In a first dry-run, we
realised that they needed to be corrected since the documents we had
generated for the printed catalog, basically consisted of single frames.
Also, it took a bit of work to generate documents that made the applied
styles correctly available in the OpenOffice style menu. We managed by
making each of the documents 16 pages (maximum length of the booklet)
but gave up on making character styles behave correctly.

“*PoDoFo is a library to work with the PDF file format and includes also
a few tools. The name comes from the first two letters of PDF (Portable
Document Format)*”

After Ludivine converted three of our favourite templates into [css
stylesheets for
(we love @fontface!), our last challenge was to deal with was
imposition. [Since early
we've been experimenting with several ways to generate A5 booklets, but
we never managed 2 x 8 pages on an A4 (A7 booklet). Pierre Marchand
pointed us once again to PoDoFO, a pdf-processing tool to which he once
added *podofoimpose*, adding the useful function to run custom
imposition 'plans'. With only a bit of trouble and help, we installed
PoDoFo on our machines (We're using Ubuntu 8.10 and 9.10):

Start with downloading ('check out') the latest files with svn (install
svn with `$ sudo apt-get install subversion`)

`$ svn co https://podofo.svn.sourceforge.net/svnroot/podofo/podofo/trunk podofo`

Download and install the libraries PoDofo depends on:

`$ sudo apt-get install build-essential g++ cmake libz-dev libtiff-dev libjpeg-dev libfreetype6-dev libfontconfig-dev`  
`$ sudo apt-get install liblua5.1-0-dev`

Than, copy the files into a folder into your home directory (you need to
create the folder first):

`$ mkdir /home/[your_user_name]/src/podofo`  
`$ cp /home/[podofo_download] /home/[your_user_name]/src/podofo`

From inside the build folder, you now need to compile PoDoFo from source
with the help of the cmake-compiler (install cmake with
`$ sudo apt-get install cmake`)

`$ cd /home/[your_user_name]/src/podofo/build`  
`$ mkdir $ cd $ cmake ../podofo $ make $ sudo su $ make install`

podofoimpose can read imposition instructions from files written in lua,
a scripting language that is used with ConTeXt for example. With the
help of a proper paper dummy, Ludivine managed to write the correct
'plan' to output A7 booklets :-D


`PushRecord((pgroup*count)+9, (count*2)+1, rot2, 0, tw) PushRecord((pgroup*count)+16, (count*2)+1, rot1, 2*th, 0) PushRecord((pgroup*count)+13, (count*2)+1, rot1, 2*th, 3*tw) PushRecord((pgroup*count)+12, (count*2)+1, rot2, 0, 4*tw) PushRecord((pgroup*count)+1, (count*2)+1, rot1, 2*th, tw) PushRecord((pgroup*count)+8, (count*2)+1, rot2, 0, 2*tw) PushRecord((pgroup*count)+4, (count*2)+1, rot1, 2*th, 2*tw) PushRecord((pgroup*count)+5, (count*2)+1, rot2, 0, 3*tw)`  
<small>Turning and twisting: imposition from scratch</small>

You can use the plan like this:

`$ podofoimpose output.pdf input.pdf InOctavo.plan lua`

**A loose hand**  
When the printed catalog is finally delivered, the result is not what we
expected. Pages are out of order and it seems they only printed the left
bottom crop/bleed mark and than everything has been cut out of the
format at the top and right side. When we try to complain, we realise
that dealing with an in-house city council printer has its
complications. To explain our exotic project to them is not easy. But we
do not flinch and keep smiling, even if we did not hand in any certified
pdf's ... and even omitted page numbers! In the end, the responsible
politician grants us a re-print.

So ... after all: A Happy Valentine!