Chapter 5. Navigation

Although you’ve spent the last three chapters talking strictly about static content, there is much more to PDF. This chapter will introduce various ways in which a PDF can gain interactivity, specifically around enabling navigation within and between documents.

A destination defines a particular view of a document. It will always refer to a specific page of the PDF, and may optionally include a smaller subsection of the page as well as a magnification (zoom) factor.

Destinations don’t stand alone; they are the values of keys in specific dictionaries related to parts of a PDF that could cause the invocation of an associated action. For example, in the document catalog, a destination can be the value of the OpenAction key. When present, that instructs the viewer to jump to that destination immediately upon opening the document.

Since the number of things that make up a destination is small and well defined, a destination is not based on a dictionary but instead on an array, unlike the other types of common objects that you’ve encountered so far (see Example 5-1). The first element of the array is always an indirect reference to the page object to which it refers, followed by a name object describing the type of zoom, and then any additional options needed for that zoom.

In addition to Fit, FitH, and FitV, there are other ways to zoom into a specific part of a page; the most powerful of these is XYZ, which includes the specific left and top coordinates of the page (for the viewer to align with) along with the zoom factor. If you don’t know them or want any of the top, left, or zoom factor values to change from what they are when the destination is invoked, provide a 0 or null value. Example 5-2 illustrates the use of XYZ.

Instead of being defined directly using the syntax shown previously, a destination may be referred to indirectly by means of a string.

This capability is especially useful when the destination is located in another PDF document. For example, a document (DocA) that wished to link to the beginning of Chapter 2 in another document (DocB) could refer to that destination by a name (e.g., Chapter2), instead of by an explicit page number in the other document. This would enable the actual physical page number of that chapter in DocB to change (due to edits, page insertions/deletions, etc.) without invalidating the destination in DocA.

Named destinations work by creating a correspondence between the name (which is represented as a string object) and the destination. This correspondence or mapping happens via the document’s name dictionary, which is the value of the Names key in the document’s catalog dictionary. In the name dictionary is a Dests key, whose value is a name tree with the string → destination mapping.

The destination value associated with a key in the name tree may be either an array or a dictionary. When the value of this entry is a dictionary, each key is a destination name and the corresponding value is either an explicit destination or a dictionary with a D entry whose value is an explicit destination.

Although destinations can be used by themselves, sometimes you need to incorporate them into an action in order for them to be usable. An action, as the name implies, is a form of command that is present in the document that invokes a particular behavior (action) in the viewer. There are both implicit actions and explicit actions. An implicit action happens through normal document navigation, such as the OpenAction that is invoked when a document is first opened, while an explicit action happens when the user interacts with some other object in the PDF, such as a button (see Button Fields) or bookmark (see Bookmarks or Outlines).

You’ve seen how GoTo actions can be quite useful, as long as you only need to navigate inside of the same PDF document. Similarly, the URI action enables redirecting the user to documents and web pages that are online. However, sometimes you want to refer to something in another PDF, or even another type of document (e.g., a word processing document or spreadsheet). For those situations you will need to use either a GoToR (for PDF) or a Launch (for other file types) action.

The GoToR action, also known as the “remote go-to” action, incorporates all of the aspects of a GoTo action, but with the addition of an F key in the action dictionary that points to the PDF in which the destination is to be resolved. A common use for this would be in a book that is broken up into chapters, where you want links between the chapters. Example 5-5 illustrates how to use GoToR to open up a PDF called “Chapter2.pdf” (which is in the same directory as the link’s PDF) and go to physical page #1.

For those situations where you need to externally link to a non-PDF document, the Launch action provides the solution. As you can see in Example 5-6, its syntax is almost exactly the same as that of the GoToR action.

It’s very common for structured documents to contain a tree-structured hierarchy of outline items that the reader presents to the user. These outline items allow the user to navigate interactively from one part of the document to another via their presentation as a visual table of contents separate from the actual page content. When such an item is activated, such as by the user clicking the text of an outline item in his UI, the conforming reader navigates to the destination or invokes the action associated with the item.

The root of a document’s outline hierarchy is an outline dictionary specified by the Outlines entry in the document catalog (see The Catalog Dictionary). Each individual outline item within the hierarchy is defined by an outline item dictionary. The items at each level of the hierarchy form a doubly linked list, chained together through their Prev and Next entries and accessed through the First and Last entries in the parent item (or in the outline dictionary in the case of top-level items). When displayed on the screen, the items at a given level appear in the order in which they occur in the linked list.

In a large or complex document, the outline hierarchy may be very large and deep, and having it displayed in its entirety by the viewer would be counter-productive. To this end, each outline item that has children can also specify if the children are to be displayed (open) or hidden (closed). Unfortunately, the key that is used to specify the visibility is also the key that is used for the number of outline entries—Count.

Count is defined as the “sum of the number of visible descendent outline items at all levels.” However, sometimes the value is negative. How can it be a sum if it’s negative? The sign of the sum represents whether the outline item is to be displayed open or closed in the reader’s UI. If the number is positive, then the children are shown; if negative, then the children are hidden.

In Example 5-7, you can see that there will be five visible outline items shown by the reader, since the Count in object 21 is positive. However, as you can see in the following figure, not all of those five are top-level items (direct children of the root)—there are only two of those (objects 22 and 29). You can see that these are the root’s children by following the First link from objects 21 to 22, then the Next link from objects 22 to 29. Object 22 has three children (which will all be visible): objects 25, 26, and 28. And finally, object 26 has a single child (object 27), but it will be shown as closed because the value of Count for this object is –1.

The preceding example is the most common type of document outline, where all of the items use destinations to point to specific parts of the document. However, instead of a Dest key, any outline item can have an A key pointing to an action.

For instance, as shown in Example 5-8, you could have an outline item that uses a URI action to take the user to an online game associated with the document.

In this chapter you learned about various types of navigational features that can be added to a PDF, including bookmarks and actions. In the next chapter, we will dive deeper into annotations.