Presenting Data as PDF

Previous Table of Contents Next

Presenting Data as PDF

The data on the weather report example is impressive, but the presentation isn't all that hot. And as you all know, presentation is very important.

For a printed document it's tough to beat PDF for presentation. PDF stands for Portable Document Format, and is a powerful and very common way of distributing electronic documents that require precise printing control. The most common tool for reading PDF documents is Adobe System's Acrobat Reader. This tool is freely available from http://adobe.com.

There is hardly enough room to go into all the details of creating PDF documents. The specification itself is over a thousand pages long! But a few short notes should be enough to get you started:

  • PDF documents are object-oriented. PDF documents have properties (creator, pages, encoding schemes, and so on). Each page in the PDF document is an object.

  • Page objects have properties like media size (paper size) and several properties to control clipping of text and graphics on the page (artbox, cropbox, and so on).

  • Text and graphics are placed onto pages by specifying coordinates, pen types, pen colors, and font names.

  • The coordinate system for PDF is upside down from what you're probably used to if you've done any graphics programming. On an 8 1/2''x11'' sheet of paper, the 0,0 coordinate is at the lower left. The upper-right corner is 612,792.

There are several modules on CPAN for writing PDF files. The module you'll use is PDF::API2. It's slightly more complicated than others (such as PDF::Create), but once mastered will provide a lot of flexibility.

Eventually, your weather report will look something like Figure 20.6.

Figure 20.6. The weather report in all its glory.

Example: Weather Report as PDF

To make this example work, you'll have to modify the Weather Report program in the prior example. Remove the last few lines from Listing 20.3 that look like this:

printf "The weather for Zip code %s %s is reported by\n", $zip, $poName;

printf "%s (%d miles away)\n%s\n", $w->{location},

       $bestDistance, $w->{observation_time};

printf "%s and %s degrees Farenheit,\n", $w->{weather}, $w->{temp_f};

printf "Winds are %s.\n", $w->{wind_string};

You can leave them in for debugging purposes, but it's not necessary. To the end of that program you'll add Listings 20.4, 20.5, and 20.6.

The first part of your PDF output code appears in Listing 20.4.

Listing 20.4. Setting Up the PDF Document

62: use PDF::API2;

63: my $ipp = 1/72;       # Inches Per Point


65: my $doc = new PDF::API2(-file => "outfile.pdf");

66: my %font = (

67:     Helvetica => {

68:            Bold   => $doc->corefont('Helvetica-Bold', -encoding => 'latin1'),

69:            Normal => $doc->corefont('Helvetica', -encoding => 'latin1'),

70:     },

71:      Times => {

72:           Roman  => $doc->corefont('Times', -encoding => 'latin1'),

73:     }

74: );



77: my $page = $doc->page();

78: $page->mediabox(8.5/$ipp, 11/$ipp);

Line 62: This brings in the PDF::API2 module that you'll need to produce the document.

Line 63: Because a PDF document is measured in points, but counting in points is a pain, you'll set $ipp to 1/72. There are 72 points per inch, so you can use inches everywhere and divide by this number to adjust to points.

Line 65: A PDF::API2 document object is created and stored in $doc. When you add text and graphics to this document, it will eventually get written to a file called output.pdf.

Lines 66–74: You're using the object in $doc to help create a structure of fonts. The corefont method returns yet another object (a PDF::API2::Font object). You'll need these font objects for placing text on the page.

Line 77: To actually put content in the document, you need to create a Page object using $doc->page(). From now on, almost all calls will use the $page, and not the $doc object.

Line 79: The mediabox() method sets the size of the page that you need. In this case, it's 8 1/2x11 (adjusted to points).

Now that you've created the PDF::API2::Page object ($page), you can start putting things onto the page.

To put graphics on the page, you'll have to obtain a graphics handle, and for text a text handle.

Both handles are objects. For the graphics handle there are many methods for drawing shapes (ellipse, arc, box, and so on) and they're all detailed in the PDF::API2::Gfx manual page. For drawing shapes, simply set the color, indicate what kind of shape you want and where you want it, and then instruct the module to draw it as shown:

$ghandle = $page->gfx();   # Get the graphics handle


# 1-inch circle, nearly centered on the page

$ghandle->circle(4/$ipp, 5/$ipp, 1/$ipp);

$ghandle->fill();  # Fill it in.

To draw lines, set the stroke color (the color of the line), move your "pen" to the starting position, use the line method to draw lines from there, and then apply the color:

$ghandle = $page->gfx(); # Or, re use the previous one


$ghandle->move(0, 0);  # Start at lower left-hand corner

$ghandle->line(8.5/$ipp, 11/$ipp);  # Upper right

$ghandle->stroke();  # Actually draw the line

Text starts off with a text handle, but proceeds a bit differently. First, set the font using one of the font objects you created using the document; next, use the TRanslate method to move the "cursor" where you want it, set the direction (defaults to horizontal, left to right), and then use one of the text methods to set and align the text. The entire list of text methods is in the PDF::API2::Text manual page.

There are lots of examples of this in Listing 20.5, where you continue your PDF weather report.

Listing 20.5. Writing the PDF Document

79: my $blue_box = $page->gfx;

80: $blue_box->fillcolor( 'lightblue' );

81: $blue_box->rect( 1/$ipp, 1/$ipp, 6.5/$ipp, 9/$ipp);

82: $blue_box->fill;


84: my $th = $page->text();

85: $th->font( $font{'Helvetica'}{'Bold'}, 18 );

86: $th->fillcolor( 'black');

87: $th->translate( 4.25/$ipp, 9.75/$ipp );

88: $th->text_center("Weather Report");

89: $th->font( $font{'Helvetica'}{'N
Previous Table of Contents Next
© 2000- NIV