PDF::Bu...otation(3)

πŸ’– PDF::Builder::Annotation πŸ’–

okay bestie, so this is PDF::Builder::Annotation β€” the part of PDF::Builder that handles annotations, and it lives in the User Contributed Perl Documentation corner of the manual. It inherits from PDF::Builder::Basic::PDF::Dict, which is giving very much "I'm a dictionary underneath but make it ✨fancy✨".


🌸 NAME 🌸

PDF::Builder::Annotation β€” add annotations to a PDF 🫢

Inherits from PDF::Builder::Basic::PDF::Dict


✨ SYNOPSIS ✨

so an "annotation" is an extra feature sitting on a page that can either change how stuff looks (hi, highlighting πŸ‘‹) or do a whole action when you click it. Some actions need one click, some need two β€” honestly it depends on which PDF Reader you're using, no cap. Some Readers will warn you and/or ask permission before doing the thing, and some will just flat-out refuse (and whether that's configurable is also a Reader thing πŸ™ˆ).

my $pdf = PDF::Builder->new();
my $font = $pdf->font('Helvetica');
my $page1 = $pdf->page();
my $page2 = $pdf->page();

my $content = $page1->text();
my $message = 'Go to Page 2';
my $size = 18;

$content->distance(1 * 72, 9 * 72);
$content->font($font, $size);
$content->text($message);

my $annotation = $page1->annotation();
my $width = $content->text_width($message);
$annotation->rect(1 * 72, 9 * 72, 1 * 72 + $width, 9 * 72 + $size);
$annotation->link($page2);

$pdf->save('sample.pdf');

πŸ‘‘ METHODS πŸ‘‘

heads up bestie: annotation handling is Reader to Reader. The available icon set might be bigger or smaller than what's listed here, and some Readers activate an annotation on a single mouse click while others want a double click. Not every feature here is available on every PDF Reader. And especially β€” Named Destinations seem to get handled in wildly different ways, which is so not the vibe 😭.

πŸ¦‹ new πŸ¦‹

$annotation = PDF::Builder::Annotation->new()

Returns an annotation object (it's called from $page->annotation()).

ngl you normally do not need to explicitly call this method β€” peep the examples πŸ‘€.

πŸŽ€ Common parameters πŸŽ€

For all the annotation calls down below, every single one needs a clickable rectangular area (button) on the page to actually activate the call. They all share these common parameters to define that "button". Real talk: your code is the one responsible for creating whatever visible content the button has (if any), while the 'rect' parameter tells the annotation what invisible area on the page activates it, and the 'border' and 'color' parameters describe the border drawn around the button πŸ’….

Also note this is a whole contrast moment with "NamedDestination", which ignores every one of these entries, because it doesn't define a "button" to press. periodt.

'rect'   => [ LLx,LLy, URx,URy ]

This defines the rectangle of the "button". Your code is responsible for any fill or text the user can actually see, via normal text and graphics calls. As an alternative (and this is mandatory if 'rect' isn't given), you can specify the rectangle with the $ann->rect(LLx,LLy, URx,URy); call. Note: the other diagonals (UL to LR, LR to UL, UR to LL) are usually allowed, so you've got options bestie.

Instead of using this hash element, the

$ann->rect( LLx,LLy, URx,URy )

method may be used (before the annotation method itself gets invoked).

'border' => [ Rx,Ry, w, [dash-pattern] ]

This defines the border around the button. If you don't give it, the default is [ 0, 0, 1 ]. Rx and Ry are the corner radii (use 0 for sharp corners ✨), w is the stroke width (use 0 for no visible border), and an optional dash-pattern can be given to draw something that isn't a solid line (like [5, 5] for a 5pt long dash and 5pt space pattern). Note that the square brackets [ ] are actually used, because the dash-pattern is an anonymous array. iykyk.

Instead of using this hash element, the

$ann->border(Rx,Ry, w, [dash-pattern])

method may be used (before the annotation method itself gets invoked).

'color'  => [ Red, Green, Blue ]

This defines the stroke color of the button border, using the RGB triplet way of describing a color (RGB anonymous array, each value 0 to 1). If a 0 width doesn't work on every Reader to suppress the border, then picking a color that matches whatever fill or background color is in the button may work instead β€” sneaky but valid πŸ’….

Instead of using this hash element, the

$ann->Color(Red, Green, Blue)

method may be used (before the annotation method itself gets invoked). Note that Color is capitalized, unlike the hash option method. Don't come for me, that's just how it is.

It's fully a stylistic choice whether you hand these settings over as options to the annotation object in the call, or call their methods directly before the annotation action method itself is called. main character energy either way πŸ‘‘

Some calls have extra optional parameters, and those get described in their own section below.

🌈 Annotation types 🌈

$annotation->goto($page, $location, @args, %opts) # preferred

$annotation->goto($page, %opts)  # location info as a hash element

Defines the annotation as a PDF launch-page with page object $page (within this document), 'fit', and opts %opts (common parameters and optionally fit: see the descriptions below).

Note that $page is not a simple page number β€” it's either a page object like $pdf->openpage(page_number), or a Named Destination defined elsewhere (a prefix of '#' or '/' is optional, except when the Named Destination is entirely numeric, and then it's required). 'foo', '#foo', and '/3659' are examples of Named Destinations. If a Named Destination is given, the page fit (location) is ignored, because the Named Destination handles all of that itself. slay.

Note that the options %opts is a hash, which permits 'rect', 'border', and 'color' to be described in a much more natural manner than flattening the hash into an array. The location and its arguments (fit data) may be either a list (in the PDF::API2 style) or another hash element. obsessed.

Alternate name: link

Originally this method was named link, but PDF::API2 changed it to goto, to correspond to the GoTo PDF command that's used. For compatibility, it's been changed to goto, with link still available as an alias 🫢.

πŸ’– pdf, pdfile, pdf_file πŸ’–

$annotation->pdf($pdffile, $page_number, $location, @args, %opts) # preferred

$annotation->pdf($pdffile, $page_number, %opts) # including location & data

Defines the annotation as an external PDF-file with filepath $pdffile, on page $page_number, and options %opts (common parameters and fit: see the descriptions below). This differs from the goto call because the target is found in a different PDF file, not the current document. Your operating system may warn you that you're heading off to a different file 🚨.

$page_number is the physical page number, starting at 1: 1, 2,..., or a Named Destination defined in that document (a prefix of '#' or '/' is optional, except when the Named Destination is entirely numeric, and then it is required). 'foo', '/foo', and '#3659' are examples of Named Destinations. If a Named Destination is used, the page fit (location) is ignored, since the Named Destination handles that. periodt.

Note that the options %opts is a hash, while the location and fit @args may be described as a list (PDF::API2 style), or as another hash element. This permits 'rect', 'border', and 'color' to be described in a more natural manner than flattening the hash into an array. iconic.

Alternate names: pdfile and pdf_file

Originally this method was named pdfile, and then pdf_file, but PDF::API2 changed it to pdf. For compatibility, it's been changed to pdf, with pdfile and pdf_file still available as aliases πŸ’œ.

🧚 uri, url 🧚

$annotation->uri($url, %opts)

Defines the annotation as a launch-url with url $url and options %opts (common parameters). This page is usually brought up in a browser, and it may be remote. Whether it does that depends on your operating system configuration 🌐.

Alternate name: url

Originally this method was named url, but PDF::API2 changed it to uri to correspond to the URI PDF command used. For compatibility, it's been changed to uri, with url still available as an alias ✨.

πŸ“ launch, file πŸ“

$annotation->launch($file, %opts)

Defines the annotation as a launch-file with filepath $file (a local file, often an executable or a script/batch file) and options %opts (common parameters). How the file actually gets "launched" or displayed depends on the operating system, the type of file, and local configuration or mapping. The common applications are bringing up a text editor to display a file, or starting a photo viewer πŸ“Έ.

Alternate name: file

Originally this method was named file, but PDF::API2 changed it to launch to correspond to the Launch PDF command used. For compatibility, it's been changed to launch, with file still available as an alias 🫢.

πŸ¦‹ text πŸ¦‹

$annotation->text($text, %opts)

Defines the annotation as a text note with content string $text and options %opts (common parameters, text, open: see the descriptions below). The $text may include newlines \n for multiple lines. Note that the 'border' option is ignored, since an icon is used instead.

The "text" option is the popup's label string β€” do not confuse it with the main $text, bestie, they are two different things 😭.

The icon appears in the upper left corner of the "rect" selection rectangle, and its active clickable area is fixed by the icon itself (it is not equal to the rectangle). The icon size is fixed, and its fill color is set by "color".

Additional options:

  • icon => name_string
  • icon => reference β€” Specify the icon to be used. The default is Reader-specific (usually "Note"), and others may be defined by the Reader. "Comment", "Key", "Help", "NewParagraph", "Paragraph", and "Insert" are also supposed to be available on all PDF Readers. Note that the name case must exactly match. The icon is of fixed size. Any AP dictionary entry will override the icon setting.

A reference to an icon may be passed instead of a name.

  • opacity => value β€” Define the opacity (non-transparency, opaqueness) of the icon. This value ranges from 0.0 (transparent) to 1.0 (fully opaque), and it applies to both the outline and the fill color. The default is 1.0.

πŸ’… markup πŸ’…

$annotation->markup($text, $PointList, $highlight, %opts)

Defines the annotation as a text note with content string $text and options %opts (color, text, open, opacity: see the descriptions below). The $text may include newlines \n for multiple lines.

"text" is the popup's label string, not to be confused with the main $text πŸ™ˆ.

There is no icon. Instead, the annotated text marked by $PointList is highlighted in one of four ways specified by $highlight.


$PointList => [ 8n numbers ]

okay so bestie, this is where you tell it where the highlight lives 🎯 You drop in one or more sets of numeric coordinates that define the quadrilateral (usually a rectangle, let's be real) around the text you want highlighted and selectable β€” like, clickable, so the annotation text pops up when someone clicks it πŸ’…

Each set is four pairs of "x,y" coordinates, and for Left-to-Right text you give them as the upper bound Upper Left β†’ Upper Right, then the lower bound Lower Left β†’ Lower Right. And fr fr, this is different from what some PDF specifications say β€” those are erroneously documented! 😭 It genuinely matters that the coordinates come in this order. Periodt.

You can give multiple sets of quadrilateral corners, like when highlighted text wraps onto new line(s) πŸŒ€ The minimum is one set (8 numbers). Any AP dictionary entry will override the $PointList setting. And finally, the "Rect" selection rectangle is created just outside the convex bounding box that $PointList defines ✨

$highlight => 'string'

Here's the menu of highlighting effects, and bestie, the "string" must be spelled and capitalized exactly as given or it's not gonna work πŸ™ˆ

  • Highlight β€” the effect of a translucent "highlighter" marker. the classic. iconic. πŸ–οΈ
  • Squiggly β€” an underline written in a "squiggly" manner. little wiggle, big vibe πŸ¦‹
  • StrikeOut β€” the text is struck-through with a straight line πŸ’€
  • Underline β€” the text is marked by a straight underline ✨

color => array of values

If "color" isn't given (an array of numbers in the range 0.0-1.0), a medium gray should be used by default 🩢 Named colors are not supported at this time. ngl that's just how it is 😭

opacity => value

Sets the opacity (non-transparency, opaqueness) of the icon πŸ’œ This value ranges from 0.0 (transparent) to 1.0 (fully opaque), and it applies to both the outline and the fill color. The default is 1.0 ✨


movie

$annotation->movie($file, $contentType, %opts)

Defines the annotation as a movie from $file with content (MIME) type $contentType and options %opts (common parameters, text: see descriptions below) 🎬

The "rect" rectangle also serves as the area where the movie is played, so make it a usable size and aspect ratio, bestie πŸ“ It does not use a separate popup player. It's known to play .avi and .wav files β€” others have not been tested. Using Adobe Reader, it will not play .mpg files (unsupported type) 🚫 More work is probably needed on this annotation method, so like, don't expect main character energy from it just yet πŸ™ˆ

file_attachment

$annotation->file_attachment($file, %opts)

Defines the annotation as a file attachment with file $file and options %opts (common parameters: see descriptions below) πŸ“Ž Heads up: "color" applies to the icon fill color, not to a selectable area outline. And the icon gets resized (aspect ratio changes included!) based on the selectable rectangle given by "rect" β€” so watch your rectangle dimensions bestie, I'm begging 😭

The file, along with its name, is embedded in the PDF document and may be extracted for viewing with the appropriate viewer πŸŽ€

This differs from the "file" method in that "file" looks for and launches a file already on the Reader's machine, while "file_attachment" embeds the file in the PDF, and makes it available on the Reader's machine for actions of the user's choosing πŸ’…

Note 1: some Readers may only permit an "open" action, and may also restrict file types (extensions) that will be handled. This may be configurable with your Reader's security settings πŸ”
Note 2: the displayed file name (pop-up during mouse rollover of the target rectangle) is given with the path trimmed off (file name only). If you want the displayed name to exactly match the path that was passed to the call, including the path, give the "notrimpath" option βœ‚οΈ

Options:

  • icon => name_string / icon => reference β€” Specify the icon to be used. The default is Reader-specific (usually "PushPin"), and others may be defined by the Reader. "Paperclip", "Graph", and "Tag" are also supposed to be available on all PDF Readers. Note that the name case must exactly match. "None" is a custom invisible icon defined by PDF::Builder πŸ‘» The icon is stretched/squashed to fill the defined target rectangle, so take care when defining "rect" dimensions. Any AP dictionary entry will override the icon setting. A reference to an icon may be passed instead of a name πŸ–ΌοΈ
  • opacity => value β€” Define the opacity (non-transparency, opaqueness) of the icon. This value ranges from 0.0 (transparent) to 1.0 (fully opaque), and applies to both the outline and the fill color. The default is 1.0 ✨
  • notrimpath => 1 β€” If given, show the entire path and file name on mouse rollover, rather than just the file name πŸ›€οΈ
  • text => string β€” A text label for the popup (on mouseover) that contains the file name πŸ’¬

Note that while PDF permits different specifications (paths) to DOS/Windows, Mac, and Unix (including Linux) versions of a file, and different format copies to be embedded, at this time PDF::Builder only permits a single file (format of your choice) to be embedded πŸ“„ If there is user demand for multiple file formats to be referenced and/or embedded, we could look into providing this, although separate OS version paths may be considered obsolescent! 🫠


Internal routines and common options

The common options may be called separately (applied against $annotation before calling the action routine), or passed as options to the call πŸ’«

rect

$annotation->rect($llx,$lly, $urx,$ury)

Sets the rectangle (active click area) of the annotation, given by 'rect' option. This is any pair of diagonally opposite corners of the rectangle πŸ“

The default clickable area is the icon itself.

Defining option. Note that this "option" is actually required πŸ‘€

This call may be replaced by a hash element 'rect'=> in many calls (see Common parameters).

  • rect => [LLx, LLy, URx, URy] β€” Set annotation rectangle as an option at "[LLx,LLy]" to "[URx,URy]" (lower left and upper right coordinates). LL to UR is customary, but any diagonal is allowed ✨

border

$annotation->border(@b)

Sets the border-style of the annotation, if applicable, as given by the border option. There are three entries in the array: horizontal and vertical corner radii, and border width. An optional fourth entry (described below) may be used for a dashed or dotted line πŸ–ŠοΈ

A border is used in annotations where text or some other material is put down, and a clickable rectangle is defined over it (rect). A border is not shown when an icon is being used to mark the clickable area.

A PDF Reader normally defaults to [0 0 1] (solid line of width 1, with sharp corners) if no border ("/Border") is specified. Keeping compatibility with PDF::API2's longstanding practice, PDF::Builder defaults to no visible border "[0 0 0]" (solid line of width 0, and thus invisible) πŸ‘»

Defining option:

  • border => [CRh, CRv, W]
  • border => [CRh, CRv, W, [on, off...]]

Note that the square brackets [ and ] are literally there, indicating a vector or array of values. They do not indicate optional values! 🚨

Set annotation border style of horizontal and vertical corner radii "CRh" and "CRv" (value 0 for squared corners) and width "W" (value 0 for no border). The PDF::Builder default is no border (while a PDF Reader typically defaults to no border ([0 0 0]), if no /Border entry is given). Optionally, a dash pattern array may be given ("on" length, "off" length, as one or more pairs). The default is a solid line βž–

The border vector seems to ignore the first two settings (corner radii), but the line thickness works, on basic Readers. The corner radii may work on some other Readers 🫢

This call may be replaced by a hash element 'border'=> in many calls (see Common parameters).

Color

$annotation->Color(@color)

Set the icon's fill color or the click area's border color 🎨 The color is an array of 1, 3, or 4 numbers, each in the range 0.0 to 1.0. If 1 number is given, it is the grayscale value (0 = black to 1 = white). If 3 numbers are given, it is an RGB color value. If 4 numbers are given, it is a CMYK color value. Currently, named colors (strings) are not handled 🚫

For link and url annotations, this is the color of the rectangle border (border given with a width of at least 1).

If an invalid array length or numeric value is given, a medium gray ([0.5]) value is used, without any message 🀐 If no color is given, the usual fill color is black.

Defining option:

Named colors (e.g., 'black') are not supported at this time.

  • color => [ ] or not 1, 3, or 4 numbers 0.0-1.0 β€” A medium gray (0.5 value) will be used if an invalid color is given.
  • color => [ g ] β€” If g is between 0.0 (black) and 1.0 (white), the fill color will be gray.
  • color => [ r, g, b ] β€” If r (red), g (green), and b (blue) are all between 0.0 and 1.0, the fill color will be the defined RGB hue. [ 0, 0, 0 ] is black, [ 1, 1, 0 ] is yellow, and [ 1, 1, 1 ] is white 🌈
  • color => [ c, m, y, k ] β€” If c (red), m (magenta), y (yellow), and k (black) are all between 0.0 and 1.0, the fill color will be the defined CMYK hue. [ 0, 0, 0, 0 ] is white, [ 1, 0, 1, 0 ] is green, and [ 1, 1, 1, 1 ] is black πŸ–€

This call may be replaced by a hash element 'color'=> in many calls (see Common parameters).

content

$annotation->content(@lines)

Sets the text-content of the text() annotation πŸ’¬ This is a text string or array of strings.

open

$annotation->open($bool)

Display the text() annotation either open or closed, if applicable πŸ“–

Both are editable; the "open" form brings up the page with the entry area already open for editing, while "closed" has to be clicked on to edit it πŸ‘†

Defining option:

  • open => boolean β€” If true (1), the annotation will be marked as initially "open". If false (0), or the option is not given, the annotation is initially "closed" πŸ”’

text string

  • 'text' => string β€” Specify an optional text label for annotation. This text or comment only shows up as a title in the pop-up containing the file or text πŸ’Œ

and that's the whole page, bestie!! πŸŽ€ you made it to the end, which honestly is giving main character energy πŸ‘‘ this was the PDF::Bu...otation(3) page from the User Contributed Perl Documentation, perl v5.42.0, dated 2026-01-17 ✨ go forth and annotate responsibly, ily πŸ«ΆπŸ’–

πŸ“¦ where this page comes from