Adding bookmarks (iText 5)

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.

Document with bookmarks created using PdfOutline

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

Listing 7.14 CreateOutlineTree 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

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
tmp89-93 tmp89-94 The bookmark title that is used in the outline tree.
tmp89-95 tmp89-96 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)

Key Value Description
tmp89-97 tmp89-98 Can be empty, “bold”, “italic”, or “italic bold”. Defines the style of the title.
tmp89-99 tmp89-100 If true, the bookmark is open, showing its kids. If false, the end user has to click the + sign in front of the bookmark to see the bookmarks of the sublevel.
tmp89-101 tmp89-102 A list with the Maps of the sublevel entries of this bookmark.
tmp89-103 tmp89-104 Can be “GoTo”, “GoToR”, “URI”, or “Launch”. Due to their possibly complex nature, JavaScript actions aren’t shown.
tmp89-105 tmp89-106 A destination on a page; see table 7.1 for the syntax; this entry occurs in combination with GoTo and GoToR actions.
tmp89-107 tmp89-108 The name of a named destination; this entry occurs in combination with GoTo and GoToR actions. Named is used when the name is stored as a PdfString; NamedN is used for PdfNames.
tmp89-109 tmp89-110 A path to the file to open or execute; this entry occurs in combination with GoToR and Launch actions.
tmp89-111 tmp89-112 Indicates whether the file to be opened must be opened in a new window; this entry occurs in combination with the GoToR action.
tmp89-113 tmp89-114 The URL that will be opened if the end user clicks the bookmark. This entry occurs in combination with an URI action.

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:

tmp89-115_thumb

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.

Bookmarks added to an existing document

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

Listing 7.16 BookmarkedTimeTable 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.

Concatenated documents with concatenated bookmarks

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

Listing 7.17 ConcatenateBookmarks 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:

tmp89-122_thumb[1]

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:

tmp89-123_thumb[1]

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

Parameter and value Description
nameddest=name Jumps to a named destination with name name in the PDF.
page=pagenum Jumps to the page with page number pagenum. This number indicates the actual page, not the label you may have given the page.
zoom=sca/e zoom=sca/e, left, top Sets the zoom and scroll factors. A scale value of 100 gives 100 percent zoom; left and top are set in a coordinate system where the origin is the top left of the visible page, regardless of the document rotation.
view=fit

view=fit, parameter

Sets the zoom factor based on the page size. The value for fit can be Fit, FitH, FitV, FitB, FitBH, or FitVH. The parameter has the same meaning as described in table 7.1. This isn’t supported with the command-line option.
viewrect=left, top, width, height Opens the file so that the rectangle specified with the parameters is visible. This isn’t supported with the command-line option.

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.

Next post:

Previous post: