JagPDF
Prev Up Home Next

A destination is a view of a document defined by a page number, a page location and a zoom factor. It can be associated with outline items (see section Document Outline) or annotations (see section Annotations).

Functions working with destinations accepts two types of destination:

  • a text string defining the destination
  • a destination object

Here is an example of a destination definition:

destination_str = "mode=XYZ; left=72; right=144; zoom=2.5"

A destination definition consists of a mode and parameters related to that mode. For example, the destination in the example above specifies a view of a page with the coordinates (72, 144) positioned at the upper-left corner of the window and the content of the page magnified to 250%. Refer to Destination Syntax for more details on the destination definition format.

Sometimes a destination can be shared among multiple annotations or outline items. To save some space in the produced PDF document it is better to create a destination object with destination_define():

destination_obj = doc.destination_define("mode=Fit")

Another reason for using a destination object can be forward link annotations (see an example in Annotations).

In the next sections we will show how to associate a destination with outline items and annotations.

A PDF document can optionally include a document outline. It is a tree of outline items (sometimes called bookmarks) which allows the user to quickly move from one part of the document to another.

JagPDF provides class DocumentOutline which allows to form a document outline. We can retrieve its instance from outline():

outline = doc.outline()

So let's create a document with six pages and create an outline item for each page:

for i in [1, 2, 3, 4, 5, 6]:
    doc.page_start(597.6, 848.68)
    outline.item('Go to page %d' % i)
    doc.page_end()

In the previous example we have created a flat document outline. Let's extend our example and form a hierarchy of outline items by with help of level_down() and level_up()

for i in [1, 2, 3, 4, 5, 6]:
    doc.page_start(597.6, 848.68)
    if i % 2:
        outline.item('Go to page %d' % i)
    else:
        outline.level_down()
        outline.item('Go to page %d' % i)
        outline.level_up()
    doc.page_end()

Now, we have made even pages children of odd pages.

The following example illustrates how to associate a destination with an outline item. We will create several outline items representing different views (destinations) of a single page.

doc.page_start(597.6, 848.68)
outline.item('mode XYZ, zoom 300%', 'mode=XYZ; zoom=3.0')
outline.item('mode Fit', 'mode=Fit')
outline.item('mode FitH', 'mode=FitH; top=800')
outline.item('mode FitV', 'mode=FitV; top=0')
doc.page_end()

In certain cases we might want a document outline not to follow the order of pages. For instance, let's create a document outline referring to pages in reverse order:

for i in [1, 2, 3]:
    doc.page_start(597.6, 848.68)
    doc.page_end()
for i in [2, 1, 0]:
    outline.item('Page %d' % (i+1), 'mode=XYZ; page=%d; top=848.68' % i)

The trick is the 'page' option in the destination definition. It explicitly says that we want the destination on that particular page. If we do not specify 'page', as we have done in our examples so far, then the current page is used (assuming we are between page_start() and page_end()). Thus, the 'page' option allows us to create an arbitrary document outline structure regardless of the order of pages.

Summary

Examples

pdficon_small basic document outline, pdficon_small hierarchical document outline, pdficon_small various destinations, pdficon_small reversed document outline

Document Outline Reference

class DocumentOutline

PDF Reference

the PDF Reference, chapter Interactive Features | Document-Level Navigation | Document Outline

PDF allows to annotate a location on a page. Clicking such location invokes behavior inherent to the nature of the annotation. The following sections describe individual annotation types.

A link annotation can be either a hypertext link to a destination or an action to be performed such as resolving a URI. The following sections presents examples of link annotations.

This section describes how to associate a destination with an area on a page. When the users clicks inside that area a PDF viewer application changes the document presentation according to the destination.

In the following example we will associate a text on the first page with a destination representing the second page. Let's start with showing a text on the first page:

font = doc.font_load('standard; name=Helvetica; size=24')
canvas.text_font(font)
x, y = 50, 800
text = 'Click this text to go to page 2.'
canvas.text(x, y, text)

Now, we need to calculate the bounding box of our text:

bbox_width = font.advance(text)
bbox_height = font.bbox_ymax() - font.bbox_ymin()

And associate a destination with it:

doc.page().annotation_goto(x, y + font.bbox_ymin(),
                           bbox_width, bbox_height,
                           "mode=Fit; page=1")

In this section we will show how to associate a URI with an area on a page. When the users clicks inside that area a PDF viewer application attempts to resolve the URI.

The following example illustrates how to associate a URI with a location on a page occupied by an image. First, we will paint the image:

img = doc.image_load_file('logo.png')
canvas.image(img, 50, 750)

Retrieve the image dimensions:

width = img.width() / img.dpi_x() * 72
height =img.height() / img.dpi_y() * 72

And use them to associate a URI with the image:

doc.page().annotation_uri(50, 750, width, height, "http://jagdpf.org")

In certain cases a destination might not be known when we want to use it. For instance, when we process a long document, we want to refer to a heading of a section which has not been formatted yet. We do not know neither the page nor the location where the heading is going to end up. The solution is to reserve an empty destination with destination_reserve() which can be used in the same way as a regular destination object. Later, when the formatting proceeds to the point when we know the destination, we can define it with destination_define_reserved().

The following example demonstrates how to work with reserved destinations. Let's paint a rectangle first:

doc.page_start(597.6, 848.68)
canvas = doc.page().canvas()
canvas.rectangle(100, 700, 80, 80)
canvas.path_paint('s')

Associate an empty destination with the rectangle:

dest = doc.destination_reserve()
doc.page().annotation_goto(100, 700, 80, 80, dest)
doc.page_end()

Now start the second page and show a text:

doc.page_start(597.6, 848.68)
doc.page().canvas().text(50, 300, 'Heading')

We know the destination now so we can define it:

doc.destination_define_reserved(dest, "mode=XYZ; top=315")
doc.page_end()

Examples

pdficon_small destination, pdficon_small URI, pdficon_small reserved destination

Annotations Reference

annotation_uri(), annotation_goto(), annotation_goto()

PDF Reference

the PDF Reference, chapter Interactive Features | Annotations

A destination is specified by a string which follows the options string format. The following table lists available destination modes and corresponding parameters:

Mode

Parameters

XYZ

left, top, zoom

Fit

FitH

top

FitV

left

FitR

left, bottom, right, top

FitB

FitBH

top

FitBV

left

For details on individual modes see table Destination syntax in the PDF Reference, chapter Interactive Features | Document-Level Navigation | Destinations | Explicit Destinations

The following are examples of valid destination specifications:

'page=0; mode=XYZ; zoom=.5'
'mode=Fit'
'mode=FitBH; top=100'

The mode option is mandatory, other parameters are optional.

Coordinate values (left, right, top and bottom) are expressed in default user space units. If a parameter is not specified then the current value of that parameter is retained unchanged. The only exception is the FitR mode where not specifying any of the parameters may result in unpredictable behavior.

Page numbering is zero based. If the page option is not specified then value of page_number() is used.

Prev Up Home Next