Open source Java projects: SwingLabs PDF Renderer

View and render PDF content from your Java programs

1 2 3 4 5 Page 5
Page 5 of 5

Application example: PDFPrinter

Listing 4 presents the source code to an application that uses PDFRenderer to render a user-specified range of a PDF document's pages to the default printer.

Listing 4. PDFPrinter.java (click to view)

PDFPrinter responds to the user selecting the Print menu item by invoking its doPrint() method. This method begins by prompting the user to select a PDF document via a file chooser. Assuming that the user doesn't cancel the chooser, doPrint() uses the selected file as the basis for a new PDFFile instance.

Moving on, doPrint() creates a new printer job, specifying the PDFPrinter object as the job's printable. This method then initializes the "range of pages" print attribute to the number of pages in the PDF document. Assuming that the user doesn't cancel the print dialog box that is subsequently displayed, doPrint() initiates the printing task.

The most interesting code resides in the printable's print() method, which is called for each page that is to be printed. Following a quick conversion of the zero-based index argument to a one-based page number, this method saves the printer context's transformation matrix because PDFRenderer's constructor modifies this matrix.

After retrieving a PDFPage object corresponding to the page number, print() invokes this object's public Dimension getUnstretchedSize(int width, int height, Rectangle2D clip) method to obtain the best possible dimensions for rendering the page, at the proper aspect ratio, within the printer context's imageable area.

These dimensions are used to construct a boundary rectangle (within the imageable area) in which the entire page is rendered. This rectangle is passed as one of the arguments to PDFRenderer's constructor, along with the PDFPage, printer graphics context, and a pair of null arguments to specify that the entire page be rendered and to not render a background color.

Because the PDFParser that works with PDFPage to parse page commands may still be running on its own thread, print() invokes waitForFinish(). This method returns after parsing finishes, making it possible to start the rendering-to-printer-context task via the call to run(). After restoring the saved transformation matrix, print() renders a border around the imageable area.

Invoke the following command to compile PDFPrinter.java:

javac -cp PDFRenderer-2008_05_18.jar PDFPrinter.java

Assuming a Windows platform, invoke the following command to launch PDFPrinter -- unlike PDFViewer, PDFPrinter takes no command-line arguments:

java -cp PDFRenderer-2008_05_18.jar;. PDFPrinter

PDF Renderer and a Java disassembler

The pdf-renderer project site lists several uses for PDF Renderer, one of them being the ability to view PDFs in the context of an application. For example, as an alternative to working with JavaHelp, you could store your application's help content in a PDF document, and then use PDF Renderer with a custom dialog box to render and present this content to the user.

I've created a Java disassembler application (essentially a GUI front-end for the JDK's javap tool, which does the actual work of disassembling a class file) to demonstrate PDF Renderer's usefulness in a help context. After you've selected a class file via the application's menu, the application reveals the resulting disassembly in its scrollable content area -- see Figure 3.

Along with the mouse, you can use the up and down arrow keys to scroll through the disassembly.
Figure 3. Along with the mouse, you can use the up and down arrow keys to scroll through the disassembly. (Click to enlarge.)

Move the mouse pointer and click the left mouse button. The application responds by identifying the text below the pointer. If this text refers to an instruction mnemonic, the application creates and shows a help dialog box that uses PDF Renderer to render mnemonic-specific pages from a PDF document. Figure 4 shows this dialog box presenting the first page of the invokevirtual instruction's help content.

Click the buttons to transition from page to page in multiple-page help content.
Figure 4. Click the < and > buttons to transition from page to page in multiple-page help content. (Click to enlarge.)

The application obtains its help pages from a jvmins.pdf file, whose content originates from a jvmins.doc Microsoft Word document -- after modifying the Word-based content, you can use a tool such as Virtual PDF Printer to save this content to a PDF file. These files and the application's JD.java source code (see Listing 5) are located in this article's code archive.

Listing 5. JD.java (click to view)

PDF Renderer does its work in the HelpViewer class's getImages() method. It reads all of the pages associated with the selected instruction mnemonic, and renders their content to an array of Images after removing half an inch of empty border space (for aesthetic reasons) -- jvmins.pdf has a default unit length of 1/72 inch.

The getImages() method employs PDFPage's getUnstretchedSize() method to size the page so that an Image doesn't exceed 700 pixels horizontally by 700 pixels vertically while maintaining the correct aspect ratio. The result should be readable and vertically scrollable (without also being horizontally scrollable) within the confines of a 600-by-600-pixel dialog box.

Invoke the following command to compile JD.java:

javac -cp PDFRenderer-2008_05_18.jar JD.java

Assuming a Windows platform, invoke the command below to start the GUI (you might want to modify the source code to support passing the name of a class file as a command-line argument):

java -cp PDFRenderer-2008_05_18.jar;. JD

In conclusion

PDF Renderer fills an important niche in the Java developer's open source toolbox, making it much easier to access and render PDF files using Java libraries. This tool was developed for in-house use at Sun Labs and has only recently been announced as an open source project under SwingLabs. Its youthful weaknesses include not being able to render every possible PDF document; rendering text in fonts that aren't identical to the fonts used when the document was created; and a Javadoc that is sparse in explanatory information. Given the relevance of the project and the proven track record of its contributors, however, I'm confident that PDF Renderer will continue to improve as it matures.

See the Resources section to learn more about PDF Renderer and SwingLabs.

Jeff Friesen is a freelance software developer and educator who specializes in Java technology. Check out his javajeff.mb.ca website to discover all of his published Java articles and more.

Learn more about this topic

1 2 3 4 5 Page 5
Page 5 of 5