File Coverage

blib/lib/PDF/API2/Annotation.pm
Criterion Covered Total %
statement 87 150 58.0
branch 12 58 20.6
condition 2 9 22.2
subroutine 17 23 73.9
pod 11 17 64.7
total 129 257 50.1


line stmt bran cond sub pod time code
1             package PDF::API2::Annotation;
2              
3 2     2   3048 use base 'PDF::API2::Basic::PDF::Dict';
  2         5  
  2         267  
4              
5 2     2   14 use strict;
  2         3  
  2         45  
6 2     2   10 use warnings;
  2         3  
  2         87  
7              
8             our $VERSION = '2.043'; # VERSION
9              
10 2     2   14 use Carp;
  2         6  
  2         146  
11 2     2   15 use PDF::API2::Basic::PDF::Utils;
  2         5  
  2         4173  
12              
13             =head1 NAME
14              
15             PDF::API2::Annotation - Add annotations to a PDF
16              
17             =head1 SYNOPSIS
18              
19             my $pdf = PDF::API2->new();
20             my $font = $pdf->font('Helvetica');
21             my $page1 = $pdf->page();
22             my $page2 = $pdf->page();
23              
24             my $content = $page1->text();
25             my $message = 'Go to Page 2';
26             my $size = 18;
27             $content->distance(1 * 72, 9 * 72);
28             $content->font($font, $size);
29             $content->text($message);
30              
31             my $annotation = $page1->annotation();
32             my $width = $content->text_width($message);
33             $annotation->rect(1 * 72, 9 * 72, 1 * 72 + $width, 9 * 72 + $size);
34             $annotation->link($page2);
35              
36             $pdf->save('sample.pdf');
37              
38             =head1 METHODS
39              
40             =cut
41              
42             sub new {
43 6     6 1 11 my $class = shift();
44 6         20 my $self = $class->SUPER::new();
45 6         15 $self->{'Type'} = PDFName('Annot');
46 6         14 $self->{'Border'} = PDFArray(PDFNum(0), PDFNum(0), PDFNum(0));
47 6         18 return $self;
48             }
49              
50             =head2 Annotation Types
51              
52             =head3 link
53              
54             $annotation = $annotation->link($destination, $location, @args);
55              
56             Link the annotation to another page in this PDF. C<$location> and C<@args> are
57             optional and set which part of the page should be displayed, as defined in
58             L.
59              
60             C<$destination> can be either a L object or the name of a named
61             destination defined elsewhere.
62              
63             =cut
64              
65             sub link {
66 1     1 1 8 my $self = shift();
67 1         1 my $destination = shift();
68              
69 1         4 my $location;
70             my @args;
71              
72             # Deprecated options
73 1         0 my %options;
74 1 50 33     13 if ($_[0] and $_[0] =~ /^-/) {
75 0         0 %options = @_;
76             }
77             else {
78 1         5 $location = shift();
79 1         2 @args = @_;
80             }
81              
82 1         11 $self->{'Subtype'} = PDFName('Link');
83 1 50       5 unless (ref($destination)) {
84 0         0 $self->{'Dest'} = PDFStr($destination);
85 0         0 return $self;
86             }
87              
88 1         3 $self->{'A'} = PDFDict();
89 1         3 $self->{'A'}->{'S'} = PDFName('GoTo');
90              
91 1 50       3 unless (%options) {
92 1         3 $self->{'A'}->{'D'} = _destination($destination, $location, @args);
93             }
94             else {
95             # Deprecated
96 0         0 $self->dest($destination, %options);
97 0 0       0 $self->rect(@{$options{'-rect'}}) if defined $options{'-rect'};
  0         0  
98 0 0       0 $self->border(@{$options{'-border'}}) if defined $options{'-border'};
  0         0  
99             }
100              
101 1         3 return $self;
102             }
103              
104             sub _destination {
105 2     2   11 require PDF::API2::NamedDestination;
106 2         9 return PDF::API2::NamedDestination::_destination(@_);
107             }
108              
109             =head3 url
110              
111             $annotation = $annotation->uri($uri);
112              
113             Launch C<$uri> -- typically a web page -- when the annotation is selected.
114              
115             =cut
116              
117             # Deprecated (renamed)
118 1     1 1 23 sub url { return uri(@_) }
119              
120             sub uri {
121 1     1 0 2 my ($self, $uri, %options) = @_;
122              
123 1         3 $self->{'Subtype'} = PDFName('Link');
124 1         2 $self->{'A'} = PDFDict();
125 1         9 $self->{'A'}->{'S'} = PDFName('URI');
126 1         3 $self->{'A'}->{'URI'} = PDFStr($uri);
127              
128             # Deprecated
129 1 50       3 $self->rect(@{$options{'-rect'}}) if defined $options{'-rect'};
  0         0  
130 1 50       4 $self->border(@{$options{'-border'}}) if defined $options{'-border'};
  0         0  
131              
132 1         4 return $self;
133             }
134              
135             =head3 file
136              
137             $annotation = $annotation->launch($file);
138              
139             Open C<$file> when the annotation is selected.
140              
141             =cut
142              
143 1     1 1 12 sub file { return launch(@_) }
144              
145             sub launch {
146 1     1 0 3 my ($self, $file, %options) = @_;
147 1         3 $self->{'Subtype'} = PDFName('Link');
148 1         4 $self->{'A'} = PDFDict();
149 1         2 $self->{'A'}->{'S'} = PDFName('Launch');
150 1         3 $self->{'A'}->{'F'} = PDFStr($file);
151              
152             # Deprecated
153 1 50       4 $self->rect(@{$options{'-rect'}}) if defined $options{'-rect'};
  0         0  
154 1 50       3 $self->border(@{$options{'-border'}}) if defined $options{'-border'};
  0         0  
155              
156 1         2 return $self;
157             }
158              
159             =head3 pdf
160              
161             $annotation = $annotation->pdf($file, $page_number, $location, @args);
162              
163             Open the PDF file located at C<$file> to the specified page number.
164             C<$location> and C<@args> are optional and set which part of the page should be
165             displayed, as defined in L.
166              
167             =cut
168              
169             # Deprecated
170 0     0 0 0 sub pdfile { return pdf_file(@_) }
171 1     1 0 7 sub pdf_file { return pdf(@_) }
172              
173             sub pdf {
174 1     1 1 2 my $self = shift();
175 1         2 my $file = shift();
176 1         2 my $page_number = shift();
177 1         3 my $location;
178             my @args;
179              
180             # Deprecated options
181 1         0 my %options;
182 1 50 33     5 if ($_[0] and $_[0] =~ /^-/) {
183 0         0 %options = @_;
184             }
185             else {
186 1         2 $location = shift();
187 1         2 @args = @_;
188             }
189              
190 1         4 $self->{'Subtype'} = PDFName('Link');
191 1         2 $self->{'A'} = PDFDict();
192 1         4 $self->{'A'}->{'S'} = PDFName('GoToR');
193 1         2 $self->{'A'}->{'F'} = PDFStr($file);
194              
195 1 50       6 unless (%options) {
196 1         20 my $destination = PDFNum($page_number);
197 1         7 $self->{'A'}->{'D'} = _destination($destination, $location, @args);
198             }
199             else {
200             # Deprecated
201 0         0 $self->dest(PDFNum($page_number), %options);
202 0 0       0 $self->rect(@{$options{'-rect'}}) if defined $options{'-rect'};
  0         0  
203 0 0       0 $self->border(@{$options{'-border'}}) if defined $options{'-border'};
  0         0  
204             }
205              
206 1         3 return $self;
207             }
208              
209             =head3 text
210              
211             $annotation = $annotation->text($text);
212              
213             Define the annotation as a text note with the specified content.
214              
215             =cut
216              
217             sub text {
218 2     2 1 25 my ($self, $text, %options) = @_;
219 2         5 $self->{'Subtype'} = PDFName('Text');
220 2         12 $self->content($text);
221              
222             # Deprecated
223 2 50       6 $self->rect(@{$options{'-rect'}}) if defined $options{'-rect'};
  2         7  
224 2 50       6 $self->open($options{'-open'}) if defined $options{'-open'};
225              
226 2         4 return $self;
227             }
228              
229             =head3 movie
230              
231             $annotation = $annotation->movie($filename, $content_type);
232              
233             Embed and link to the movie located at $filename with the specified MIME type.
234              
235             =cut
236              
237             sub movie {
238 0     0 1 0 my ($self, $file, $content_type, %options) = @_;
239 0         0 $self->{'Subtype'} = PDFName('Movie');
240 0         0 $self->{'A'} = PDFBool(1);
241 0         0 $self->{'Movie'} = PDFDict();
242 0         0 $self->{'Movie'}->{'F'} = PDFDict();
243              
244 0         0 $self->{' apipdf'}->new_obj($self->{'Movie'}->{'F'});
245 0         0 my $f = $self->{'Movie'}->{'F'};
246 0         0 $f->{'Type'} = PDFName('EmbeddedFile');
247 0         0 $f->{'Subtype'} = PDFName($content_type);
248 0         0 $f->{' streamfile'} = $file;
249              
250             # Deprecated
251 0 0       0 $self->rect(@{$options{'-rect'}}) if defined $options{'-rect'};
  0         0  
252              
253 0         0 return $self;
254             }
255              
256             =head2 Common Annotation Attributes
257              
258             =head3 rect
259              
260             $annotation = $annotation->rect($llx, $lly, $urx, $ury);
261              
262             Define the rectangle around the annotation.
263              
264             =cut
265              
266             sub rect {
267 2     2 1 6 my ($self, @coordinates) = @_;
268 2 50       5 unless (scalar @coordinates == 4) {
269 0         0 die "Incorrect number of parameters (expected four) for rectangle";
270             }
271 2         5 $self->{'Rect'} = PDFArray(map { PDFNum($_) } @coordinates);
  8         14  
272 2         4 return $self;
273             }
274              
275             =head3 border
276              
277             $annotation = $annotation->border($h_radius, $v_radius, $width);
278              
279             Define the border style. Defaults to 0, 0, 0 (no border).
280              
281             =cut
282              
283             sub border {
284 0     0 1 0 my ($self, @attributes) = @_;
285 0 0       0 unless (scalar @attributes == 3) {
286 0         0 croak "Incorrect number of parameters (expected three) for border";
287             }
288 0         0 $self->{'Border'} = PDFArray(map { PDFNum($_) } @attributes);
  0         0  
289 0         0 return $self;
290             }
291              
292             =head3 content
293              
294             $annotation = $annotation->content(@lines);
295              
296             Define the text content of the annotation, if applicable.
297              
298             =cut
299              
300             sub content {
301 2     2 1 4 my ($self, @lines) = @_;
302 2         6 my $text = join("\n", @lines);
303 2         6 $self->{'Contents'} = PDFStr($text);
304 2         4 return $self;
305             }
306              
307             sub name {
308 0     0 0   my ($self, $name) = @_;
309 0           $self->{'Name'} = PDFName($name);
310 0           return $self;
311             }
312              
313             =head3 open
314              
315             $annotation = $annotation->open($boolean);
316              
317             Set the annotation to initially be either open or closed. Only relevant for
318             text annotations.
319              
320             =cut
321              
322             sub open {
323 0     0 1   my ($self, $value) = @_;
324 0 0         $self->{'Open'} = PDFBool($value ? 1 : 0);
325 0           return $self;
326             }
327              
328             sub dest {
329 0     0 0   my ($self, $page, %options) = @_;
330              
331 0 0         unless (ref($page)) {
332 0           $self->{'Dest'} = PDFStr($page);
333 0           return $self;
334             }
335              
336 0   0       $self->{'A'} //= PDFDict();
337 0 0         $options{'-xyz'} = [undef, undef, undef] unless keys %options;
338              
339 0 0         if (defined $options{'-fit'}) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
340 0           $self->{'A'}->{'D'} = _destination($page, 'fit');
341             }
342             elsif (defined $options{'-fith'}) {
343 0           $self->{'A'}->{'D'} = _destination($page, 'fith', $options{'-fith'});
344             }
345             elsif (defined $options{'-fitb'}) {
346 0           $self->{'A'}->{'D'} = _destination($page, 'fitb');
347             }
348             elsif (defined $options{'-fitbh'}) {
349 0           $self->{'A'}->{'D'} = _destination($page, 'fitbh', $options{'-fitbh'});
350             }
351             elsif (defined $options{'-fitv'}) {
352 0           $self->{'A'}->{'D'} = _destination($page, 'fitv', $options{'-fitv'});
353             }
354             elsif (defined $options{'-fitbv'}) {
355 0           $self->{'A'}->{'D'} = _destination($page, 'fitbv', $options{'-fitbv'});
356             }
357             elsif (defined $options{'-fitr'}) {
358 0           $self->{'A'}->{'D'} = _destination($page, 'fitr', @{$options{'-fitr'}});
  0            
359             }
360             elsif (defined $options{'-xyz'}) {
361 0           $self->{'A'}->{'D'} = _destination($page, 'xyz', @{$options{'-xyz'}});
  0            
362             }
363              
364 0           return $self;
365             }
366              
367             1;