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.
Annotation objects are dictionary objects containing at least two keys: Rect
and Subtype
. The Rect
key, of course, has a value that is a rectangle representing the page coordinates where the annotation is to be placed by the viewing application. The Subtype
key has a name value that represents which one of the 27 types of annotations is being described by this particular dictionary. Many types of annotations will also have a Contents
key whose value is a text string that is displayed either directly on the page or is an alternate description of the annotation’s content in a human-readable form. Depending on the type of annotation, the other keys in the annotation dictionary may be either required or optional. Some of these keys are common to all types of annotations, while others are specific to a particular type.
ISO 32000 separates annotations into two categories: markup (discussed below) and non-markup (discussed in Non-Markup Annotations). ISO 32000-1 defines most annotations as being markup annotations because they are used primarily to mark up the content of a PDF document. Additionally, these annotations have text that appears as part of the annotation and may be displayed in other ways by a conforming reader.
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.
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.
Annotation type | Description |
Caret | Caret annotation |
Circle | Circle annotation |
FileAttachment | File attachment annotation |
FreeText | Free text annotation |
Highlight | Highlight annotation |
Ink | Ink annotation |
Line | Line annotation |
Polygon | Polygon annotation |
PolyLine | Polyline annotation |
Redact | Redact annotation |
Square | Square annotation |
Squiggly | Squiggly-underline annotation |
Sound | Sound annotation |
Stamp | Rubber stamp annotation |
StrikeOut | Strikeout annotation |
Text | Text annotation |
Underline | Underline annotation |
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.
9 0 obj << /Type /Page /Annots [ 20 0 R 22 0 R 24 0 R 26 0 R ] % other stuff that we need for a valid page dictionary >> 20 0 obj << /Type /Annot /Subtype /Highlight /Rect [ 252.594 593.733 322.077 623.211 ] /C [ 1 1 0 ] >> 22 0 obj << /Type /Annot /Subtype /StrikeOut /Rect [ 313.07 592.866 392.279 624.078 ] /C [ 1 0 0 ] >> 24 0 obj << /Type /Annot /Subtype /Underline /Rect [ 251.727 528.21 322.944 559.422 ] /C [ 0 1 0 ] >> 26 0 obj << /Type /Annot /Subtype /Squiggly /Rect [ 313.07 528.21 392.279 559.422 ] /C [ 0 0 1 ] >>
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.
Although you don’t need QuadPoints
for simple rotations (0, 90, 180, 270), it won’t hurt to have one since a rect described in eight points instead of four is perfectly acceptable.
Figure 6-2 shows an example of highlighted text that is also being rotated.
51 0 obj << /Type /Annot /Subtype /Highlight /Rect [ 258.483 291.978 368.238 401.733 ] /QuadPoints [ 259.709 312.822 347.394 400.507 279.327 293.204 367.012 380.889 ] /C [ 1 1 0 ] >>
Even though a QuadPoints
array is more specific than the Rect
, the Rect
is always required to be present because it serves as a “maximum bounding area” for the QuadPoints
. In fact, ISO 32000-1 says “QuadPoints shall be ignored if any coordinate in the array lies outside the region specified by Rect.”
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 two most common attributes describe the lines (or strokes, if you prefer) that are being drawn: the color (and associated color space) as well as the line weight and any dash pattern. Both the C
(stroke) and the IC
(fill) keys use an array of numbers to specify the color space and the color values, as described earlier in Text Markup.
The BS
key has a border style dictionary as its value. As described in ISO 32000-1:2008, Table 166, this dictionary consists of only two possible keys: S
for the border style and D
for a dash array. The border style can have values that specify a solid border (S
), a dashed border (D
), different types of embossing (B
and I
), and an underline style (U
). The dash array takes the same form as it does when including it in a content stream.
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.
For square and circle annotations, the value of the IC
key is used to fill the entire shape, much as the F
operator would fill a shape in a content stream.
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.
% A red stroked square 60 0 obj << /C [ 1 0 0 ] /RD [ 0.50 0.50 0.50 0.50 ] /Rect [ 281.239990 680.687012 355.390991 754.838013 ] /Subtype Square /Type Annot >> % A circle stroked in (RGB) green and filled in (grayscale) gray 62 0 obj << /BS << /W 3 >> /C [ 0 1 0 ] /IC [ .50 ] /RD [ 1.50 1.50 1.50 1.50 ] /Rect [ 375.842987 680.411011 456.338989 760.908020 ] /Subtype Circle /Type Annot >> % A blue circle with a cloud effect 64 0 obj << /BE << /I 2 /S C >> /BS << /W 2 >> /C [ 0 0 1 ] /RD [ 1 1 1 1 ] /Rect [ 483.533997 685.257019 551.442993 753.164978 ] /Subtype Circle /Type Annot >>
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.
Name | Description |
| A square filled with the annotation’s interior color, if any |
| A circle filled with the annotation’s interior color, if any |
| A diamond shape filled with the annotation’s interior color, if any |
| Two short lines meeting in an acute angle to form an open arrowhead |
| Two short lines meeting in an acute angle, as in the |
| No line ending |
| A short line at the endpoint perpendicular to the line itself |
| Two short lines angled in the reverse direction from |
| A triangular closed arrowhead in the reverse direction from |
| A short line at the endpoint approximately 30 degrees clockwise from perpendicular to the line itself |
% Simple red line 20 0 obj << /Type Annot /Subtype Line /C [ 1 0 0 ] /L [ 30.098700 755.213013 204.001999 755.213013 ] /Rect [ 24.598700 749.713013 209.501999 760.713013 ] >> % Dashed green line 22 0 obj << /Type Annot /Subtype Line /BS << /D [ 4 4 ] /S D /W 5 >> /C [ 0 1 0 ] /L [ 28.869200 717.310974 202.772995 717.310974 ] /Rect [ 21.369200 709.810974 210.272995 724.810974 ] >> % Blue line with an arrowhead at the end 24 0 obj << /Type Annot /Subtype Line /BS << /W 3 >> /C [ 0 0 1 ] /L [ 30.098700 687.211975 200.658005 687.211975 ] /LE [ None OpenArrow ] /Rect [ 23.598700 680.711975 207.158005 693.711975 ] >>
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.
For polyline annotations, the value of the IC
key is used to fill only the line ending. However, for Polygon annotations, the value of the IC
key is used to fill the entire shape, much as the F
operator would fill a shape in a content stream.
The actual points along the shape are specified as an array value for the Vertices
key, with alternating horizontal and vertical coordinates.
As with QuadPoints
, even though a Vertices
array is more specific than the Rect
, the Rect
is always required to be present.
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.
% red polyline (as the shape is open) 105 0 obj << /Type Annot /Subtype PolyLine /C [ 1 0 0 ] /Rect [ 272.049011 536.856018 372.549011 640.978027 ] /Vertices [ 301.295013 626.216003 273.049011 578.414978 316.505005 537.856018 371.549011 578.414978 314.332001 575.518005 323.747009 602.315979 349.096985 597.969971 350.545013 625.492004 350.545013 624.768005 323.023010 639.978027 ] >> % polygon stroked in (RGB) green and filled in (CMYK) yellow 107 0 obj << /Type Annot /Subtype Polygon /BS << /W 5 >> /C [ 0 1 0 ] /IC [ 0 0 1 0 ] /Rect [ 376.688995 529.958984 491.707001 638.458984 ] /Vertices [ 399.071014 600.143005 415.729004 613.179993 446.148010 593.624023 415.005005 565.377991 388.931000 579.862976 381.688995 559.583984 429.489990 534.958984 486.707001 574.794006 459.908997 613.179993 400.519989 633.458984 399.071014 600.143005 ] >> % polygon stroked in (grayscale) black 109 0 obj << /Type Annot /Subtype Polygon /BE << /I 2 /S C >> /BS << /W 3 >> /C [ 0 ] /IT PolygonCloud /Rect [ 497.958008 525.330994 598.528015 633.752014 ] /Vertices [ 512.057007 621.146973 585.932007 601.591003 583.034973 537.856018 510.608002 553.789978 510.608002 582.036011 512.057007 621.146973 ] >>
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.
% 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.
25 0 obj << /AP << /N 18 0 R >> /CA 0.5 % set the opacity to 50% /Rect [ 109.597 104.905 206.597 201.905 ] /Subtype Stamp /Type Annot >> 18 0 obj << /Type /XObject /Subtype /Form /BBox [ 0 0 147 147 ] /FormType 1 /Length 74 % or whatever it really is /Matrix [ 1 0 0 1 0 0 ] /Resources << /XObject << /FRM 20 0 R >> >> % refers to subsequent XObject stream q 0 0 147 147 re W n q 0 0 147 147 re W n 1 0 0 1 73.5 73.5 cm /FRM Do Q Q endstream endobj 20 0 obj << /Type /XObject /Subtype /Form /BBox [ 249 421 396 568 ] /FormType 1 /Length 348 % or whatever it really is /Matrix [ 1 0 0 1 -322.5 -494.5 ] stream 0 0 1 0 k 0 0 0 1 K 0 J 0 j 6 w 4 M []0 d /GS2 gs 1 i 322.787 425.358 m 360.798 425.358 391.612 456.173 391.612 494.184 c 391.612 532.194 360.798 563.009 322.787 563.009 c 284.777 563.009 253.962 532.194 253.962 494.184 c 253.962 456.173 284.777 425.358 322.787 425.358 c b 0 g 353.747 517.033 m 353.747 522.313 350.147 526.153 345.107 526.153 c 340.067 526.153 335.987 522.073 335.987 517.273 c 335.987 512.473 340.307 508.633 344.867 508.633 c 349.427 508.633 353.747 512.233 353.747 517.033 c f 307.08 517.033 m 307.08 522.313 303.48 526.153 298.44 526.153 c 293.4 526.153 289.32 522.073 289.32 517.273 c 289.32 512.473 293.64 508.633 298.2 508.633 c 302.76 508.633 307.08 512.233 307.08 517.033 c f 1 J 278.216 481.06 m 284 468.393 298.267 456.076 323 456.076 c 347.733 456.076 362 469.06 367.783 481.06 c S endstream endobj
In the preceding example, a form XObject references another form XObject. This is not a requirement for the stamp annotation, but it is a common pattern.
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:
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).
19 0 obj << /Popup 20 0 R /Name /Comment /Contents (This is the pop-up for a text annotation) /Type /Annot /Rect [261.52 558.755 279.52 576.755] /Subtype /Text >> endobj 20 0 obj << /Parent 19 0 R /Subtype /Popup /Type /Annot /Rect [287.427 457.785 467.428 578.222] /Open true >> endobj 21 0 obj << /Subtype /Highlight /C [1 1 0] /Popup 22 0 R /QuadPoints [321.343 622.344 384.006 622.344 321.343 594.6 384.006 594.6] /Contents (this is text associated with the highlight annotation over "World") /Type /Annot /Rect [313.937 593.733 391.412 623.211] >> endobj 22 0 obj << /Parent 21 0 R /Subtype /Popup /Type /Annot /Rect [395.62 592.048 575.62 712.485] /Open true >> endobj
Annotation type | Description |
3D | 3D annotation |
FileAttachment | File attachment |
Link | Link annotation |
Movie | Movie annotation |
Popup | Pop-up annotation |
PrinterMark | Printer’s mark annotation |
Screen | Screen annotation |
Sound | Sound |
TrapNet | Trap network annotation |
Watermark | Watermark annotation |
Widget | Widget annotation |
Non-markup annotations can themselves be divided into a number of subcategories:
GoTo
actions in Example 5-3, and widget annotations have an entire chapter (Chapter 7) dedicated to them.
There are two other types of annotations that don’t fall into any of these categories: FileAttachment and Watermark.
File attachment annotations are one way to embed/attach files to a PDF, much like you would with an email message. These are covered in Chapter 8.
The watermark annotation was introduced into PDF for use by engineers as a way to designate a special graphic that does not scale when printed. They aren’t used very much and so won’t get any coverage here either.
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.
3.145.75.217