In PDF language, we often use the terms outline tree or outlines as synonyms for bookmarks. In topic 2, you created bookmarks automatically by using topic and Section objects. The result was nice, but you can do better if you create the outline using PdfOutline objects. The PdfOutline class offers much more functionality, and you can use it to create bookmarks for existing documents.
Let’s start using them in a document that’s created from scratch.
Creating bookmarks for a new document
Take a look at figure 7.4. The bookmarks consist of movie titles printed in bold; one of the movie titles is shown using Korean characters. If you click one of these titles, you’ll jump to the movie in the document. For every movie, there’s also a bookmark shown in blue to the corresponding site on IMDB. If you click the Instant Info bookmark, an alert window opens showing the year and run length of the movie.
Figure 7.4 Document with bookmarks created using PdfOutline
This is different from what you did before with topic and Section objects. These bookmarks aren’t referring to a specific destination in the document; they cause the execution of actions.
Listing 7.14 CreateOutlineTree
The first thing you need is the root of the outline tree. You can get this with the get-RootOutline() method O. During the creating of the document, you can use this root PdfOutline to create children ©.
The constructor of the PdfOutline class accepts four parameters:
■ The parent—Another PdfOutline object of which the newly created bookmark is a kid.
■ A destination or an action—A PdfDestination if you want to add a local goto link, or a PdfAction object for any other action.
■ A title for the bookmark—This can be a Paragraph, a String, or even a PdfString.
■ A boolean value open (optional)—Indicates whether the outline has to be open (the default) or closed when the user opens the bookmark panel.
In listing 7.14, you create a PdfDestination to create a traditional bookmark that jumps to the vertical position just before you add a movie title. The zoom factor will be adapted so that the complete horizontal width is visible (look for FITH in table 7.1). Because you are creating the document from scratch, you don’t have to pass the page number; iText uses the reference to the current page.
NOTE When adding basic building blocks to a document, you normally don’t have to bother about pagination or the current Y position. But if you want to create a PdfDestination object, you need to know the vertical position. You can retrieve this coordinate with the getVerticalPosition() method. This method doesn’t just “get” the Y value. It can also ensure that you get the position of the next line. That’s why you pass the boolean value true in listing 7.14.
In listing 7.14, you’re using actions to create outlines that are added as children of the movie title bookmark. © serves as a link to IMBD using a URL action. Q adds aJavaScript action. The script consists of a single line that can be found in the INFO String: app.alert(‘Movie produced in %s; run length: %s’); The String will be formatted for each movie so that %s is replaced with the year and duration found in your database.
NOTE You can use a Paragraph for the bookmark title, but the style of the Paragraph object will not be taken into account. You can change the style only with the methods setStyle() © and setColor() ©. Observe that Unicode characters are accepted. In listing 7.14, the title of the movie “3-Iron” is replaced with the characters for “Bin-Jip” (which is the original Korean title of this excellent movie).
You’ve now created a new PDF document with bookmarks, but this part of the topic is mainly about manipulating existing documents. Suppose that you receive a document like the one you’ve just created—how can you retrieve the bookmarks? That’s what we’re going to look at in the next example.
Retrieving bookmarks from an existing document
In section 7.1.1, you used the SimpleNamedDestination class to retrieve the named destinations from a document in the form of a HashMap or an XML file. Here you use a similar object to extract the bookmarks from an existing PDF: SimpleBookmark.
Listing 7.15 CreateOutlineTree
You first obtain a List of HashMap objects. Each HashMap item contains at least one of the keys listed in table 7.2.
Table 7.2 Possible keys for a bookmark entry
Key | Value | Description |
The bookmark title that is used in the outline tree. | ||
Color values for red, green, and blue ranging from 0 to 1, defining the color of the title. |
Table 7.2 Possible keys for a bookmark entry (continued)
You can export the bookmarks list to an XML file O (in listing 7.15) using the Latin-1 encoding (see the “ISO8859-1″ parameter), accepting only ASCII characters (see the true parameter). The resulting XML file looks like this:
You can use table 7.2 to interpret this XML file. The root tag is always named Bookmark. The Title tags are used for its children. There’s no Kids tag; the entries of the Kids list are nested Title tags. All other key-value pairs are attributes of the Title tag.
You can also use table 7.2 as a reference to create new bookmarks for an existing document.
Adding bookmarks to an existing document
Suppose that you want to add bookmarks to the timetable PDF, as in figure 7.5.
Figure 7.15 Bookmarks added to an existing document
There’s a top-level entry in the Bookmarks list for this timetable with the title “Calendar”. Nothing happens if you click it; it’s just a structural element with eight children: one for each festival day. If you click one of these dates, the corresponding page is opened. You can create this outline tree and add it to an existing document using PdfStamper.
Listing 7.16 BookmarkedTimeTable
You can use table 7.2 to create Maps with titles, kids, and actions. You can consult table 7.1 to create the destination for the Page value. You can use the setOutlines() method to add the bookmarks to the stamper object. This also works for PdfCopy.
You’ve concatenated documents with bookmarks in topic 6, and found that all your bookmarks were lost. We’ll see how to fix this in the next example.
Concatenating documents with bookmarks
For this example, you’ll take the timetable PDF you created in the previous example, and concatenate it with the MovieHistory document you created in topic 2. Both documents have bookmarks, and you want these bookmarks to be merged as shown in figure 7.6.
Figure 7.15 Concatenated documents with concatenated bookmarks
In this code sample, we concatenate bookmarks, but in listing 6.21, we concatenated documents.
Listing 7.17 ConcatenateBookmarks
Just like in the PdfStamper example, you create an ArrayList for the bookmarks. You could start adding new entries, but for this example you’ll get the bookmarks from the existing documents. These bookmarks will work correctly for the first document, but a bookmark that points at the first page in the second document won’t. It will point to the first page of the first document in the concatenated PDF. That’s why you need to shift the page numbers using the shiftPageNumbers() method O. After that’s done, you add the bookmarks to the new list. You use setOutlines() to inject the new list of bookmarks into the new document.
One of the parameters in O was null. That’s because you want to shift the page numbers of the bookmarks for all the pages. You can also pass an array with an even number of int values that define page ranges for which you want to shift the page numbers with the offset defined by the page_offset parameter. There’s also an elim-inatePages() method that can be used to remove the bookmarks that point at specific page ranges. That’s an interesting method if you want to split existing documents or remove a couple of pages.
Now that you know everything there is to know about bookmarks in PDF, what about creating bookmarks in HTML? With listing 7.3, you retrieved named destinations; with listing 7.15, you retrieved bookmarks. Wouldn’t it be nice if you could use that information to create a URL that can be used to open a PDF file in a browser at a specific position? The next section will give you an overview of the open parameters that can be used to achieve this.
Open parameters
When starting Adobe Reader from the command line, you can pass an open action (/A) with different parameters. When opening a PDF in a browser using a URL, you can achieve the same result by adding parameters after the # sign.
The following line called from the command line opens the JavaScript API documentation on page 28:
The following URL opens the documentation about open actions on page 5 using a magnifying factor that ensures that the complete page fits within the viewer window:
Table 7.3 lists the parameters that can be passed with the /A option, or that can be added to a URL, involving named and explicit destinations. For more open parameters, consult the Open Parameters for PDF document that can be found on the Adobe site.
Table 7.3 Overview of the open parameters
You’ve learned about destinations; you’ve learned about actions. You’ve used both with Chunks; you’ve used both with PdfOutlines. But what really makes a document interactive is annotations.