Generating a PDF Document Using PDFlib PDFlib is intended for generating dynamic PDF documents via the Web.. The only problem is that you need to read the PHP documentation, available at
Trang 1FIGURE 30.6
pdf.phpgenerates a certificate from an PDF template.
One problem with this approach is that the code runs quite slowly because of the regular
expression matching required Regular expressions run much more slowly than str_replace()
that we could use for the RTF version
If you are going to match a large number of placeholders or try to generate many of these
doc-uments on the same server, you might want look at other approaches This would be less of a
problem for a simpler template Much of the bulk in this file is data representing the images
Generating a PDF Document Using PDFlib
PDFlib is intended for generating dynamic PDF documents via the Web It is not strictly part
of PHP, but rather a separate library, with a large number of functions intended to be called
from a wide variety of programming languages Language bindings are available for C, C++,
Java, Perl, Python, Tcl, and ActiveX/COM
Interestingly, there is not an official PDFlib PHP binding available yet The current binding is
not documented or supported by PDFlib The PDFlib Web site states, “Other language
bind-ings, such as PHP, will be supported in the future,” but it has said this for at least a year
30
Trang 2Although it is possible that the official PHP binding might be better then the current one when (or if) it arrives, the current one is very good The only problem is that you need to read the PHP documentation, available at
http://www.php.net/manual/ref.pdf.php
for an overview, installation instructions, and the PDFlib documentation, available as the file PDFlib-manual.pdf in the PDFlib distribution, for a detailed reference on the API
A Hello World Script for PDFlib
After you have PHP and installed it with PDFlib enabled, you can test it with a simple program such as the Hello World example in Listing 30.5
L ISTING 30.5 testpdf.php—Classic Hello World Example Using PDFlib Via PHP
<?
//create file
$fp = fopen(“hello.pdf”, “w”);
if(!$fp) {
echo “Error: could not create the PDF file”;
exit;
} // start the pdf document
$pdf = pdf_open($fp);
pdf_set_info($pdf, “Creator”, “pdftest.php”);
pdf_set_info($pdf, “Author”, “Luke Welling and Laura Thomson”);
pdf_set_info($pdf, “Title”, “Hello World (PHP)”);
// US letter is 11” x 8.5” and there are approximately 72 points per inch pdf_begin_page($pdf, 8.5*72, 11*72);
pdf_add_outline($pdf, “Page 1”);
pdf_set_font($pdf, “Helvetica-Bold”, 24, “host”);
pdf_set_text_pos($pdf, 50, 700);
// write text pdf_show($pdf,”Hello,world!”);
pdf_continue_text($pdf,”(says PHP)”);
// end the document pdf_end_page($pdf);
pdf_close($pdf);
fclose($fp);
Trang 3LISTING 30.5 Continued
// display a link to download
echo “download the pdf <a href = ‘hello.pdf’>here</a>”;
?>
The most likely error you will see if this script fails is the following:
Fatal error: Call to undefined function: pdf_open() in
/home/book/public_html/chapter30/pdftest.php on line 6
This means that you do not have the PDFlib extension compiled into PHP
The installation is fairly straightforward, but some details change depending on the exact
ver-sions of PHP and PDFlib that you are using A good place to check for detailed suggestions is
the user contributed notes on the PDFlib page in the annotated PHP manual
When you have this script up and running on your system, it is time to look at how it works
The first section of the code, including the line
$fp = fopen(“hello.pdf”, “w”);
creates a writeable file It is worth noting that the code here is writing directly in to the current
directory even though we have already discussed a number of reasons why it is a bad idea to
have your permissions set up to allow PHP to write within the Web tree
The line
$pdf = pdf_open($fp);
initializes a PDF document using the file we already opened You can also call pdf_open()
without parameters to create a document in memory to be output directly to the browser In
any case, you will need to capture the return value of pdf_open(), as every subsequent call to
a PDF function will need it
The function pdf_set_info()enables you to tag the document with a subject, title, creator,
author, a list of keywords, and one custom, user-defined field
Here we are setting a creator, author, and title Note that all six info fields are optional
pdf_set_info($pdf, “Creator”, “pdftest.php”);
pdf_set_info($pdf, “Author”, “Luke Welling and Laura Thomson”);
pdf_set_info($pdf, “Title”, “Hello World (PHP)”);
A PDF document consists of a number of pages To start a new page, we need to call
pdf_begin_page() As well as the identifier returned by pdf_open(), pdf_begin_page()
requires the dimensions of the page Each page in a document can be a different size, but
unless you have a good reason not to, you should use a common paper size
30
Trang 4PDFlib works in points, both for page size, and for locating coordinate locations on each page For reference, A4 is approximately 595 by 842 points and U.S letter is 612 by 792 points This means that our line
pdf_begin_page($pdf, 8.5*72, 11*72);
creates a page in our document, sized for U.S letter paper
A PDF document does not need to be just a printable document Many PDF features can be included in the document such as hyperlinks and bookmarks The functionpdf_add_outline()
will add a bookmark to the document outline The bookmarks in a document will appear in a separate pane in Acrobat Reader, allowing us to skip straight to important sections
This line
pdf_add_outline($pdf, “Page 1”);
adds an outline entry labeled Page 1, which will refer to the current page
Fonts available on systems vary from operating system to operating system and even from indi-vidual machine to machine In order to guarantee consistent results, a set of core fonts will work with every PDF reader The 14 core fonts are
• Courier
• Courier-Bold
• Courier-Oblique
• Courier-BoldOblique
• Helvetica
• Helvetica-Bold
• Helvetica-Oblique
• Helvetica-BoldOblique
• Times-Roman
• Times-Bold
• Times-Italic
• Times-BoldItalic
• Symbol
• ZapfDingbats Fonts outside this set can be embedded in documents, but this will increase the file size and might not be acceptable under whatever license you own that particular font under We can choose a font, its size, and character encoding as follows:
Trang 5pdf_set_font($pdf, “Helvetica-Bold”, 24, “host”);
Font sizes are specified in points We have chosen host character encoding The allowable
val-ues are winansi, builtin, macroman, ebcdic, or host The meanings of the different valval-ues are as
follows:
• winansi—ISO 8859-1 plus special characters added by Microsoft such as a Euro symbol
• macroman—Mac Roman encoding The default Macintosh character set
• ebcdic—EBCDIC as used on IBM AS/400 systems
• builtin—Use the encoding built in to the font Normally used with non Latin fonts and symbols
• host—Automatically selects macroman on a Mac, ebcdic on an EBCDIC-based system, and winansi on all other systems
If you do not need to include special characters, the choice of encoding is not important
A PDF document is not like an HTML document or a word processor document Text does not
simply start at the top left and flow onto other lines as required We need to choose where to
place each line of text As already mentioned, PDF uses points to specify locations The origin
(the x, y coordinate [0, 0]) is at the bottom left corner of the page
Given that our page is 612 by 792 points, the point (50, 700) is about two thirds of an inch
from the left of the page and about one and one third inches from the top To set our text
position at this point, we use
pdf_set_text_pos($pdf, 50, 700);
Finally, having set up the page, we can write some text on it To add text at the current position
using the current font, we use pdf_show()
The line
pdf_show($pdf,”Hello,world!”);
adds the test “Hello World!”to our document
To move to the next line and write more text, we use pdf_continue_text() To add the string
“(says PHP)”, we use
pdf_continue_text($pdf,”(says PHP)”);
The exact location where this will appear will depend on the font and size selected
When we have finished adding elements to a page, we need to call pdf_end_page()as follows:
pdf_end_page($pdf);
30
Trang 6When we have finished the whole PDF document, we need to close it using pdf_close() When we are generating a file, we also need to close the file
The lines
pdf_close($pdf);
fclose($fp);
complete the generation of our Hello World document All we need to do is provide a way to download it
echo “download the pdf <a href = ‘hello.pdf’>here</a>”;
This example was derived from the C language example in the PDFlib documentation and should provide a starting point
The document we want to produce for the certificate is more complicated, including a border,
a vector image, and a bitmap image With the other two techniques, we added these features using our word processor With PDFlib, we must add them manually
Generating Our Certificate with PDFlib
In order to use PDFlib, we have chosen to make some compromises Although it is almost cer-tainly possible to exactly duplicate the certificate we used previously, a lot more effort would
be required to generate and position each element manually rather than using a tool such as Microsoft Word to help lay out the document
We are using the same text as before, including the red rosette and the bitmap signature, but we are not going to duplicate the complex border
The complete code for this script is shown in Listing 30.6
L ISTING 30.6 pdflib.php—Generating Our Certificate Using PDFlib
<?
if(!$name||!$score) {
echo “<h1>Error:</h1>This page was called incorrectly”;
} else { //generate the headers to help a browser choose the correct application header( “Content-type: application/pdf” );
header( “Content-Disposition: filename=cert.pdf”);
$date = date( “F d, Y” );
Trang 7LISTING 30.6 Continued
// create a pdf document in memory
$pdf = pdf_open();
// set up the page size in points // US letter is 11” x 8.5”
// there are approximately 72 points per inch
$width = 11*72;
$height = 8.5*72;
pdf_begin_page($pdf, $width, $height);
// draw a borders
$inset = 20; // space between border and page edge
$border = 10; // width of main border line
$inner = 2; // gap within the border //draw outer border
pdf_rect($pdf, $inset-$inner,
$inset-$inner,
$width-2*($inset-$inner),
$height-2*($inset-$inner));
pdf_stroke($pdf);
//draw main border $border points wide pdf_setlinewidth($pdf, $border);
pdf_rect($pdf, $inset+$border/2,
$inset+$border/2,
$width-2*($inset+$border/2),
$height-2*($inset+$border/2));
pdf_stroke($pdf);
pdf_setlinewidth($pdf, 1.0);
//draw inner border pdf_rect($pdf, $inset+$border+$inner,
$inset+$border+$inner,
$width-2*($inset+$border+$inner),
$height-2*($inset+$border+$inner));
pdf_stroke($pdf);
//add text pdf_set_font($pdf, “Times-Roman”, 48, “host”);
$startx = ($width - pdf_stringwidth($pdf, “PHP Certification”))/2;
pdf_show_xy($pdf, “PHP Certification”, $startx, 490);
pdf_set_font($pdf, “Times-Roman”, 26, “host”);
30
Trang 8L ISTING 30.6 Continued
$startx = 70;
pdf_show_xy($pdf, “This is to certify that:”, $startx, 430);
pdf_show_xy($pdf, strtoupper($name), $startx+90, 391);
pdf_set_font($pdf, “Times-Roman”, 20, “host”);
pdf_show_xy($pdf, “has demonstrated that they are certifiable “.
“by passing a rigorous exam”, $startx, 340);
pdf_show_xy($pdf, “consisting of three multiple choice questions.”,
$startx, 310);
pdf_show_xy($pdf, “$name obtained a score of $score”.”%.”, $startx, 260); pdf_show_xy($pdf, “The test was set and overseen by the “, $startx, 210); pdf_show_xy($pdf, “Fictional Institute of PHP Certification”,
$startx, 180);
pdf_show_xy($pdf, “on $date.”, $startx, 150);
pdf_show_xy($pdf, “Authorised by:”, $startx, 100);
// add bitmap signature image
$signature = pdf_open_image_file($pdf, “tiff”,
“/htdocs/book/chapter30/signature.tif”); pdf_place_image($pdf, $signature, 200, 75, 1);
pdf_close_image($pdf, $signature);
pdf_setrgbcolor_fill($pdf, 0, 0, 4); //dark blue pdf_setrgbcolor_stroke($pdf, 0, 0, 0); // black // draw ribbon 1
pdf_moveto($pdf, 630, 150);
pdf_lineto($pdf, 610, 55);
pdf_lineto($pdf, 632, 69);
pdf_lineto($pdf, 646, 49);
pdf_lineto($pdf, 666, 150);
pdf_closepath($pdf);
pdf_fill($pdf);
// outline ribbon 1 pdf_moveto($pdf, 630, 150);
pdf_lineto($pdf, 610, 55);
pdf_lineto($pdf, 632, 69);
pdf_lineto($pdf, 646, 49);
Trang 9LISTING 30.6 Continued
pdf_lineto($pdf, 666, 150);
pdf_closepath($pdf);
pdf_stroke($pdf);
// draw ribbon 2 pdf_moveto($pdf, 660, 150);
pdf_lineto($pdf, 680, 49);
pdf_lineto($pdf, 695, 69);
pdf_lineto($pdf, 716, 55);
pdf_lineto($pdf, 696, 150);
pdf_closepath($pdf);
pdf_fill($pdf);
// outline ribbon 2 pdf_moveto($pdf, 660, 150);
pdf_lineto($pdf, 680, 49);
pdf_lineto($pdf, 695, 69);
pdf_lineto($pdf, 716, 55);
pdf_lineto($pdf, 696, 150);
pdf_closepath($pdf);
pdf_stroke($pdf);
pdf_setrgbcolor_fill($pdf, 8, 0, 0); //red //draw rosette
draw_star(665, 175, 32, 57, 10, $pdf, true);
//outline rosette draw_star(665, 175, 32, 57, 10, $pdf, false);
pdf_end_page($pdf);
pdf_close($pdf);
}
function draw_star($centerx, $centery, $points, $radius,
$point_size, $pdf, $filled) {
$inner_radius = $radius-$point_size;
for ($i = 0; $i<=$points*2; $i++ ) {
$angle= ($i*2*pi())/($points*2);
if($i%2) {
$x = $radius*cos($angle) + $centerx;
30
Trang 10L ISTING 30.6 Continued
$y = $radius*sin($angle) + $centery;
} else {
$x = $inner_radius*cos($angle) + $centerx;
$y = $inner_radius*sin($angle) + $centery;
} if($i==0) pdf_moveto($pdf, $x, $y);
else if($i==$points*2) pdf_closepath($pdf);
else pdf_lineto($pdf, $x, $y);
} if($filled) pdf_fill($pdf);
pdf_stroke($pdf);
}
?>
The certificate produced using this script is shown in Figure 30.7 As you can see, it is quite similar to the others, except that the border is simpler and the star looks a little different This
is because we have drawn them into the document rather than using an existing clip art file
F IGURE 30.7
draws the certificate into a PDF document.