Chapter 6. Annotations

This chapter will go into detail on a special type of object in PDF—the annotation. Annotations are PDF objects that enable user-clickable actions as well as new types of content including 3D, video, and audio.

The content that a user sees on a PDF page is described using a content stream of PDF graphic operators (see Content Streams for more). However, sometimes it is necessary to overlay that content with active or “hot” areas, or additional graphics. You may also want to incorporate new types of content onto your pages, such as 3D graphics or videos that cannot be described using those graphic operators. To accomplish these things, the annotation object is used.

As with page content, annotations are associated directly with a page. In any page dictionary for a page containing annotations, there has to be an Annots key whose value is an array of the annotations.

Appearance Streams

Annotation dictionaries may contain entries that describe shapes and colors to be drawn by the PDF viewer, instead of a content stream. However, a PDF that requires a guaranteed appearance may also associate a special type of content stream, called an appearance stream, with an annotation. It does this by including an AP key in the annotation dictionary whose value is an appearance dictionary that references one or more appearance streams. When an appearance stream is present, the viewer will simply draw that instead of recreating the drawing instructions using the other values.

The appearance dictionary that references the appearance stream can have up to three keys present: N (the normal appearance), R (the rollover appearance), and D (the down appearance). For the types of annotations discussed here, we only use the N key, but AcroForms, discussed in Chapter 7, supports the others.

An example of using an appearance stream can be found in Figure 6-6.

Markup Annotations

As the name implies, these types of annotations are used to apply various types of common markup operations on top of the page content. There are many types of markups that can be applied (shown in Table 6-1), from the simple Highlight and StrikeOut to the generic Ink, and the specialized Redact.

These are the types of annotations that most users are familiar with when commenting on a PDF—highlight, underline, and strike out, along with the unusual addition of the squiggly (a jagged underline).

In each case, the Subtype will be one of those four values (Highlight, Underline, StrikeOut, or Squiggly) and the Rect will encompass the area on the page (usually covering text) in which the graphical representation of the annotation will be drawn. Additionally, we want to define the color that the annotation will be drawn in, so the C key will be used.

The value of the C key is an array of either 1, 3, or 4 values representing not only the color value but also (implicitly) the color space in which that value should be handled. A one-element array represents DeviceGray, three elements for DeviceRGB and four elements for DeviceCMYK. Figure 6-1 shows a few sample text markup annotations.

If the text being annotated is rotated or otherwise transformed, you can use the QuadPoints key to define an array of eight points representing the four corners of a quadrilateral that bounds the text.

Figure 6-2 shows an example of highlighted text that is also being rotated.

PDF defines a series of six types of annotations that enable drawing-like operations that can be used to mark up a PDF. While it is unfortunate that each of them has a slightly different way of describing the graphic shape that is being represented, they all support a standard set of attributes such as colors, weights, and more.

The square and circle annotations are the simplest of the drawing annotations, in that they don’t need any extra keys in their dictionaries. Instead, they rely on the existing Rect key for the shape bounding area and the BS and IC keys for any styling.

One nice additional key that can be specified on these annotations is the BE key, which can be used to turn a simple circle (or rectangle) into one that resembles a cloud. The BE key’s value is a border effect dictionary that can contain either an S key (with a value of S for “simple” or a C for “cloudy”) or an I key with an integer value between 0 and 2 that declares the intensity of the effect.

When including a border effect (BE), it is frequently useful to include an RD key in the annotation dictionary. It allows for the specification of an “offset margin” from the bounding rectangle to the one used to draw the shape. Figure 6-3 shows a few examples of square and circle annotations.

The line annotation is used to draw a simple line. It has a single required key in its dictionary: L, which is an array of four numbers that specify the two endpoints of the line.

One additional key that the line annotation dictionary supports is the LE key, which allows the specification of different types of line endings, including arrowheads, boxes, and circles (see Figure 6-4). There are 10 different types of possible line endings, as you can see in Table 6-2.

While a single line is useful, in most cases a series of lines that connect to each other creating an open (polyline) or closed (polygon) shape will address more cases for drawing and markup of the content on the page. As with line and square annotations, the LE, BS, BE, IC, and C keys serve to provide some styling attributes.

The actual points along the shape are specified as an array value for the Vertices key, with alternating horizontal and vertical coordinates.

One other key that is specific to polyline and polygon annotations is the IT key, which provides the intent of the object. It takes a name value of PolygonCloud, PolyLineDimension, or PolygonDimension. Figure 6-5 provides a few exmaples of polygon and polyline annotations.

As flexible as the polygon and polyline annotations are, sometimes a completely freeform drawing connecting a series of arbitrary points is needed. Additionally, polygon and polyline segments are connected via straight lines, but sometimes a curve is necessary. For that purpose, the ink annotation is provided in PDF.

As with the other annotation types we’ve seen, the LE, BS, and C keys serve to provide some styling attributes (see Example 6-1). The points themselves are stored in an array that is the value of the InkList key, and since it is usually a very long list, it’s quite common (though not required) to have the list as a separate indirect object.

Example 6-1. Examples of ink annotations
some examples of ink annotations
% red ink
141 0 obj
<<
    /C [ 1 0 0 ]
    /InkList 126 0 R
    /Rect [ 40.283199 451.471008 158.264999 517.778992 ]
    /Subtype Ink
    /Type Annot
>>

% green ink
143 0 obj
<<
    /BS << /W 5 >>
    /C [ 0 1 0 ]
    /InkList 192 0 R
    /Rect [ 186.205994 427.546997 299.170013 516.556030 ]
    /Subtype Ink
    /Type Annot
>>

% magenta ink
145 0 obj
<<
    /BS << /W 3 >>
    /C [ 0 1 0 0]
    /InkList 209 0 R
    /Rect [ 323.010986 408.593994 479.394989 506.535004 ]
    /Subtype Ink
    /Type Annot
>>

126 0 obj
[
    41.2832 487.808 42.0075 488.532 42.731700000000004 489.256 44.1803 490.705
    45.6288 492.154 47.0773 493.602 49.9744 496.499 52.8715 498.672 55.7685
    57.9413 503.018 61.5627 506.639 65.184 508.812 68.0811 510.984 69.5296
    70.2539 513.882 72.4267 515.33 72.4267 516.054 73.8752 516.779 73.1509
    72.4267 513.882 70.2539 511.709 68.0811 507.363 64.4597 503.018 60.1141
    56.4928 493.602 55.0443 487.808 52.8715 483.462 52.1472 479.841 52.1472
    52.8715 476.22 54.32 475.495 55.7685 475.495 58.6656 476.22 62.2869 478.392
    66.6325 480.565 70.2539 482.738 73.8752 484.911 75.3237 487.808 76.7723
    77.4965 492.154 77.4965 493.602 77.4965 494.326 77.4965 493.602 76.7723
    % Lots more numbers would go here...
]

192 0 obj
[
    348.372 500.845 348.372 500.12 348.372 499.396 348.372 498.672 348.372
    348.372 497.223 347.648 496.499 346.924 495.775 346.199 495.775 345.475
    344.751 493.602 343.302 493.602 342.578 492.154 341.854 491.429 341.13
    340.405 489.981 339.681 489.981 338.957 489.981 338.233 489.981 336.784
    336.06 490.705 334.611 491.429 333.163 492.154 330.99 493.602 330.266
    328.817 494.326 328.093 495.051 327.369 495.051 326.644 495.775 326.644
    326.644 497.223 326.644 497.948 326.644 498.672 328.093 498.672 328.817
    330.266 500.12 332.438 500.845 333.887 500.845 336.784 501.569 339.681
    344.027 502.293 348.372 502.293 351.994 502.293 356.339 502.293 359.236
    362.133 502.293 364.306 502.293 366.479 502.293 368.652 501.569 369.376
    370.825 498.672 371.549 497.223 372.273 495.775 372.997 494.326 372.997
    % Lots more numbers would go here...
]

209 0 obj
[
    191.206 504.466 191.206 503.742 191.206 502.293 191.206 500.845 191.206
    191.931 496.499 191.931 492.878 192.655 487.808 193.379 484.911 193.379
    194.828 478.392 194.828 476.22 194.828 474.047 195.552 473.323 196.276
    197.001 470.426 197.001 471.15 197.725 471.874 197.725 474.047 197.725
    198.449 479.117 199.173 482.738 200.622 485.635 202.07 489.981 204.243
    205.692 498.672 207.14 503.018 209.313 506.639 210.762 508.812 210.762
    210.762 510.984 211.486 510.984 211.486 508.812 211.486 505.915 211.486
    211.486 497.223 211.486 492.878 211.486 487.808 211.486 482.738 211.486
    212.21 473.323 212.934 468.977 213.659 467.528 213.659 466.08 214.383
    % Lots more numbers would go here...
]

When the drawing annotation types are not rich enough to represent the graphics that are to be drawn—for example, if you’d like to include a raster image (as discussed in Chapter 3)—the stamp annotation is the choice. It is in some ways the simplest annotation to create, as the annotation dictionary only requires the Type and Subtype keys from the standard dictionary. However, what makes it complex is that it also requires an AP key and its associated appearance stream (see Appearance Streams). Fortunately, an appearance stream is simply a form XObject (see Vector Images). Figure 6-6 demonstrates a stamp annotation.

In this example the annotation dictionary contains a CA key that specifies the amount of opacity to apply to the entire appearance stream of the annotation when it is drawn on the page.

The other interesting thing that this example demonstrates is that even the form XObject used in an annotation’s appearance stream can refer to additional resources, including any number of subsequent and nested form XObjects.

A text annotation is used to represent a “sticky note” that is placed at a specific place on the PDF page. The text of the note is the string value for the Contents key in the annotation dictionary. Although a standard appearance stream should be used to provide the drawing instructions, it is also possible to just provide a Name key with a value that gives the PDF viewer a clue what icon to use. ISO 32000-1, Table 172 lists the possible names that a PDF viewer is required to provide for. Some common icons used for those names are the following:

List of icons and names

The pop-up annotation is a special type of annotation that exists to allow the association of a string of text with markup annotations. It doesn’t have an appearance of its own, but instead has a parent key in its annotation dictionary that points to another annotation, which is one of the markup annotations. This parent annotation provides the actual appearance stream for the annotation, if any. Additionally, the parent annotation’s dictionary contains a Contents key whose value is a string that specifies the text to be displayed in the “note.”

In addition to the Parent annotation, the pop-up annotation dictionary can also contain an Open key whose Boolean value determines if the viewer should show it open or closed by default (see Figure 6-7).

Non-markup annotations can themselves be divided into a number of subcategories:

In this chapter, we learned about annotation. Next you will look at a specific type of annotation, the widget type, which serves as the basis for PDF forms.