Lazy PDF creation with Prawn: A Tutorial In One Part

What is Prawn?

Prawn is a pure Ruby library to generate PDFs. It takes much of the pain away (though, using a publishing tool like Scribus or Adobe InDesign CS5.5 make a more visual approach much easier. However, to create PDFs on the fly, Prawn is the most convenient tool you can find.

Get It

gem install prawn

Use It

require 'prawn'

Creating PDFs

No matter what the PDF shall contain, you will always use the Prawn::Document.generate method. I prefer the block invocation:

Prawn::Document.generate "example.pdf" do end

Sample Content

I want to show off as many of Prawn’s features, so I’ve prepared some sample data:

# Our headings  heading = "The Traditional Filler Content"  sub_heading = "It Has No Inherent Meaning"  # Our body body = <<-EOS Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quisnostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.  EOS  formatted = "<b>Inline</b> <i>formatting</i> is a <strikethrough>useless<strikethrough> <u>useful</u> feature!"

Simple Text And Inline Formatting

PDF is, first and foremost, a text format. Everything else is just sugar (or a liability, as the case may be). Since an introduction to everything Prawn (and PDFs) have to offer would be far from a Lazy Tutorial, we will deal with outputting text as PDF.

Simple Text…

Let’s take our sample text, and create a PDF with a large heading, a smaller sub-heading, and a creation date as cover page, and let’s fill the PDF with a bit of dummy text:

Prawn::Document.generate "example.pdf" do text heading, :align => :center, :size => 48  text sub_heading, :align => :center, :size => 32  text "\nCreated on #{Time.now}\n", :align => :center  start_new_page  10.times do group do text body end end end

As you have already guessed, the text method takes text, and outputs it to the PDF, and it takes the :align and the size arguments. If you look at the freshly created PDF, the headings are larger than the creation date, and all of them are aligned in the center of the document.

start_new_page does exactly what it says on the tin, and starts a new page. text body outputs the text we’ve assigned to the variable. And you will have noticed the group do…end block. This tells prawn to keep the stuff enclosed with group do…end as a group, and, if possible, keep them on the same page. Otherwise, the paragraph would overflow.

…And Inline Formatting

I have hinted at it quite a bit, so it won’t be surprising you when I say that Prawn allows for inline formatting, with the help of the tiniest HTML syntax subset: , , , and are supported. However, Prawn will not automatically parse HTML for you. Instead you have to manually invoke the feature:

Prawn::Document.generate "example.pdf" do # ...  font_size 12 do text formatted, :inline_format => true end end

It’s as simple as that. Just so that it looks like I did some work, I’ve also used the font_size size do…end, which does what it says on the tin for everything that’s within the block.

Custom Fonts

One of the strengths of the PDF format is typography: Preserving the typeface of the text you added. Since not every document is (or can be) limited to the “built in” fonts—see Standard Type 1 Fonts for details which are defined, Prawn lets you define custom font_families:

font_families["Nobile"] = { :normal => "./nobile.ttf", :bold => "./nobile_bold.ttf", :bold_italic => "./nobile_bold_italic.ttf", :italic => "./nobile_italic.ttf" }  text formatted, :inline_format => true, :font => "Nobile"

For typographical / dead tree print reasons, it is expected that you define font faces for bold, italic (or cursive), and italicized bold weights. With font my_font you can assign this font for everything that follows. If you want to limit the font directive, you can use the block form, or a :font => my_font hash.

Pagination and Page Numbering

Few documents are exactly one page long, so it’s no surprise that Prawn offers page numbering:

number_pages "Page  of  pages", :at => [bounds.right - 100,0], :page_filter => :all

Simple enough. :at determines where the numbering is printed, and page_filter determines on which page (:all, :odd, or :even).

Resources

1 comment:

Unknown said...

Well written article. I have no knowledge regarding it.You explained such a new thing. Thanks for sharing this type of information. Please share some more information regarding this.
e signatures