A PDF Solution for All Programming Platforms

Let’s face it: Printing with the Windows WIN32 SDK can be nightmarish at best, and MFC adds only a little bit of help for this problem. Programming guru Jonathan de Halleux described printing as “the most mysterious feature in MFC.”

Traditionally, programmers have worked around the printing issue in a couple of clever ways. The first is printing plain ASCII text files or HTML files and handling them through the Web browser. The second, using Crystal Reports or another third-party add-in report system, applies to more complex layouts. However, a lot of border cases don’t neatly fit into one category or the other. For example, you may need a more complicated layout than HTML generally allows (such as drawing a line to connect two objects on the page), but without the sort of data repetition that is the forté of a report writer.

For these reasons and many more, programmers are attracted to the Adobe Portable Document Format (PDF) like moths to a porch light. Customers love PDF printing because it always comes out the same; it works great as an e-mail attachment, et cetera, et cetera. However, to begin writing raw PDF files, you need a pretty solid working knowledge of PostScript—and that’s not pretty. In reality, you need a complete PDF library, such as PDFlib (from PDFlib Gmbh), that handles all your document-creation needs.

PDFlib: A Solution for All Programming Platforms

The PDFlib main package for Windows works natively with C, C++, Java, and PHP applications. You also can reach other programming platforms such as Perl AS, Python, Tcl, Ruby, REALbasic, and Borland C++ Builder through optional add-on packages. Furthermore, you can choose the Windows COM/.NET Installer and make PDFlib available throughout your .NET regime (for example, C#, VB.NET, ASP.NET, and related language solutions).

PDFlib also has an impressive array of support available for other operating system platforms, including Linux (x86, AMD64, PPC, and eServer), Mac OS 9 and OS X, and every type of Unix you can think of (FreeBSD, OpenBSD, HP-UX, Solaris, and AIX, just to name a few).

Additionally, PDFlib supports all the extras that you probably had given up hope of incorporating in your own PDFs:

  • Layers: As found in CAD documents but also useful for multilingual documents and interactive control of document display
  • Unicode: Complete Unicode support from end to end, including file names, page content, hyper links, and form fields
  • Text formatting: Built-in textflow formatter for simple arrangement of ragged or justified text, font changes, multi-line body text, and very large tables
  • Images: Support for all types of TIFF, including JPEG compressed TIFFs, JPEG 2000, and 48-bit color PDF generation
  • Multimedia tags: Allows “read aloud”, page reflow, and simpler export of data
  • PDF/X and OPI: For anyone producing documents to be printed in “book quality”
  • Linearized PDF: optimized for page-at-a-time Web viewing

Getting Started

Perhaps because PDFlib has been ported so widely, integration is about as simple as you can imagine. I started off by downloading a free unlicensed evaluation version of PDFlib for Windows (6.0.3). A barebones version called PDFlib Lite also is available, which you can freely use for non-profit personal use. The Lite version can generate basic PDFs but does not edit them or include advanced font techniques (see this comparison chart for a feature breakdown).

After extracting the ZIP file, you basically just include the pdflib.h include file in your C/C++ application. Next, you add the supplied pdflib.lib import library to your Link step, and then make the pdflib.dll available in your application’s path at runtime. The DLL itself is just under 2 Mb and is completely self-contained (calling only native Win32 SDK DLLs). If you dislike import libraries or you want to make PDFlib an optional component, you can use the helper macros in pdflibdl.h to dynamically load the library entry points.

Writing Your First PDF

This section demonstrates a simple PDF creation C++ application that reads a template PDF file (“boilerplate.pdf”), fills in some data, and burns a new PDF file as its output. Specifically, it fills in the missing fields of a conventional business card.

It will turn this:

into this:

All the logic is enclosed in a try…catch construct to watch for PDFlib::Exception exceptions:

 1 // $Id: businesscard.cpp,v 1.16 2004/05/23 11:22:06 tm Exp $
 2 #include <iostream>
 3 #include "pdflib.hpp"
 5 int main(void)
 6 {
 7    try {
 8    PDFlib p;
 9    int         i, blockcontainer, page;
10    const string infile = "boilerplate.pdf";
11       /* This is where font/image/PDF input files live.
          * Adjust as necessary.
12        *
13        * Note that this directory must also contain the
14        * LuciduxSans font outline and metrics files.
15        */
16    const string searchpath = "../data";
17    struct blockdata {
18       blockdata(string n, string v): name(n), value(v){}
19       string name;
20       string value;
21    };
23    blockdata data[] = {
24       blockdata("name",                   "Victor Kraxi"),
25       blockdata("business.title",         "Chief Paper Officer"),
26       blockdata("business.address.line1", "17, Aviation Road"),
27       blockdata("business.address.city",  "Paperfield"),
28       blockdata("business.telephone.voice","phone +1 234 567-89"),
29       blockdata("business.telephone.fax", "fax +1 234 567-98"),
30       blockdata("business.email",         "[email protected]"),
31       blockdata("business.homepage",      "www.kraxi.com"),
32    };
34 #define BLOCKCOUNT (sizeof(data)/sizeof(data[0]))

The guts of the program really starts on Line 36, where it creates a new PDF document session with the begin_document() method call. As you might expect, the scope of a document is from begin_document() to end_document(). The begin_document() call can specify a host of options, including passwords, permissions (noprint, nomodify, nocopy, and so forth), output file (for example, “businesscard.pdf”), and PDF version, just to name a few.

You can create PDF documents in-memory by omitting the filename (“”):

36       if (p.begin_document("businesscard.pdf", "") == -1) {
37       cerr << "Error: " << p.get_errmsg() << endl;
38          return(2);
39       }
41    // Set the search path for fonts and PDF files
42    p.set_parameter("SearchPath", searchpath);
44    // This line is required to avoid problems on Japanese systems
45    p.set_parameter("hypertextencoding", "host");

Next, you set standard PDF info items that you can view from inside Adobe Acrobat, for example:

47    p.set_info("Creator", "businesscard.cpp");
48    p.set_info("Author", "Thomas Merz");
49    p.set_info("Title","PDFlib block processing sample (C++)");

More by Author

Must Read