| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package PDF::Builder::Annotation; |
|
2
|
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
1670
|
use base 'PDF::Builder::Basic::PDF::Dict'; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
366
|
|
|
4
|
|
|
|
|
|
|
|
|
5
|
2
|
|
|
2
|
|
18
|
use strict; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
92
|
|
|
6
|
2
|
|
|
2
|
|
11
|
use warnings; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
246
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '3.028'; # VERSION |
|
9
|
|
|
|
|
|
|
our $LAST_UPDATE = '3.028'; # manually update whenever code is changed |
|
10
|
|
|
|
|
|
|
|
|
11
|
2
|
|
|
2
|
|
13
|
use PDF::Builder::Basic::PDF::Utils; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
272
|
|
|
12
|
2
|
|
|
2
|
|
15
|
use List::Util qw(min max); |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
222
|
|
|
13
|
2
|
|
|
2
|
|
16
|
use Carp; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
12361
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 NAME |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
PDF::Builder::Annotation - Add annotations to a PDF |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Inherits from L<PDF::Builder::Basic::PDF::Dict> |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
An "annotation" is an extra feature on a page that may change the appearance |
|
24
|
|
|
|
|
|
|
(e.g., highlighting), or perform some action when |
|
25
|
|
|
|
|
|
|
clicked on. Some actions may require a single click and others a double click; |
|
26
|
|
|
|
|
|
|
this depends on the PDF Reader used. Some may warn you and/or ask permission |
|
27
|
|
|
|
|
|
|
to perform a certain action, while others may refuse to do something (which |
|
28
|
|
|
|
|
|
|
may be configurable). |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
my $pdf = PDF::Builder->new(); |
|
31
|
|
|
|
|
|
|
my $font = $pdf->font('Helvetica'); |
|
32
|
|
|
|
|
|
|
my $page1 = $pdf->page(); |
|
33
|
|
|
|
|
|
|
my $page2 = $pdf->page(); |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
my $content = $page1->text(); |
|
36
|
|
|
|
|
|
|
my $message = 'Go to Page 2'; |
|
37
|
|
|
|
|
|
|
my $size = 18; |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
$content->distance(1 * 72, 9 * 72); |
|
40
|
|
|
|
|
|
|
$content->font($font, $size); |
|
41
|
|
|
|
|
|
|
$content->text($message); |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my $annotation = $page1->annotation(); |
|
44
|
|
|
|
|
|
|
my $width = $content->text_width($message); |
|
45
|
|
|
|
|
|
|
$annotation->rect(1 * 72, 9 * 72, 1 * 72 + $width, 9 * 72 + $size); |
|
46
|
|
|
|
|
|
|
$annotation->link($page2); |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
$pdf->save('sample.pdf'); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head1 METHODS |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Note that the handling of annotations can vary from Reader to Reader. The |
|
53
|
|
|
|
|
|
|
available icon set may be larger or smaller than given here, and some Readers |
|
54
|
|
|
|
|
|
|
activate an annotation on a single mouse click, while others require a double |
|
55
|
|
|
|
|
|
|
click. Not all features provided here may be available on all PDF Readers. |
|
56
|
|
|
|
|
|
|
In particular, Named Destinations seem to be handled in widely varying ways! |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head2 new |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
$annotation = PDF::Builder::Annotation->new() |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=over |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Returns an annotation object (called from $page->annotation()). |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
It is normally I<not> necessary to explicitly call this method (see examples). |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=back |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=cut |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# %opts removed, as there are currently none |
|
73
|
|
|
|
|
|
|
sub new { |
|
74
|
6
|
|
|
6
|
1
|
14
|
my $class = shift; |
|
75
|
|
|
|
|
|
|
|
|
76
|
6
|
|
|
|
|
36
|
my $self = $class->SUPER::new(); |
|
77
|
6
|
|
|
|
|
22
|
$self->{'Type'} = PDFName('Annot'); |
|
78
|
6
|
|
|
|
|
77
|
$self->{'Border'} = PDFArray(PDFNum(0), PDFNum(0), PDFNum(0)); # no border |
|
79
|
|
|
|
|
|
|
|
|
80
|
6
|
|
|
|
|
21
|
return $self; |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
#sub outobjdeep { |
|
84
|
|
|
|
|
|
|
# my ($self, @opts) = @_; |
|
85
|
|
|
|
|
|
|
# |
|
86
|
|
|
|
|
|
|
# foreach my $k (qw[ api apipdf apipage ]) { |
|
87
|
|
|
|
|
|
|
# $self->{" $k"} = undef; |
|
88
|
|
|
|
|
|
|
# delete($self->{" $k"}); |
|
89
|
|
|
|
|
|
|
# } |
|
90
|
|
|
|
|
|
|
# return $self->SUPER::outobjdeep(@opts); |
|
91
|
|
|
|
|
|
|
#} |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# ============== start of annotation types ======================= |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# note that %opts is given as the only format in most cases, as rect |
|
96
|
|
|
|
|
|
|
# is a mandatory "option" |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=head2 Common parameters |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
For the annotation calls given below, all require a clickable rectangular area |
|
101
|
|
|
|
|
|
|
(button) on the page to activate the call. These all share common parameters to |
|
102
|
|
|
|
|
|
|
define this "button". Note that I<your> code is responsible for creating the |
|
103
|
|
|
|
|
|
|
visible content of the button (if any), while the 'rect' parameter tells the |
|
104
|
|
|
|
|
|
|
annotation what (invisible) area on the page activates it, and the 'border' |
|
105
|
|
|
|
|
|
|
and 'color' parameters describe the border drawn around the button. |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
Note that this is in contrast to C<NamedDestination>, which ignores any of |
|
108
|
|
|
|
|
|
|
these entries, as it does not define a "button" to press. |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
'rect' => [ LLx,LLy, URx,URy ] |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
This defines the rectangle of the "button". Your code is responsible for any |
|
113
|
|
|
|
|
|
|
fill or text visible to the user, via normal text and graphics calls. |
|
114
|
|
|
|
|
|
|
As an alternative (mandatory if 'rect' is not given), you may |
|
115
|
|
|
|
|
|
|
specify the rectangle with the C<$ann-E<gt>rect(LLx,LLy, URx,URy);> call. |
|
116
|
|
|
|
|
|
|
I<Note:> the other diagonals (UL to LR, LR to UL, UR to LL) are usually allowed. |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
Instead of this hash element being used, the |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
$ann->rect( LLx,LLy, URx,URy ) |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
method may be used (I<before> the annotation method itself is invoked). |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
'border' => [ Rx,Ry, w, [dash-pattern] ] |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
This defines the border around the button. If not given, the default is |
|
127
|
|
|
|
|
|
|
[ 0, 0, 1 ]. Rx and Ry are corner radii (0 for sharp corners), I<w> is the |
|
128
|
|
|
|
|
|
|
stroke width (0 for no visible border), and an optional dash-pattern may be |
|
129
|
|
|
|
|
|
|
given to draw something other than a solid line (e.g., [5, 5] for a 5pt long |
|
130
|
|
|
|
|
|
|
dash and 5pt space pattern). Note that the square brackets [ ] are actually |
|
131
|
|
|
|
|
|
|
used, as the dash-pattern is an anonymous array. |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
Instead of this hash element being used, the |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
$ann->border(Rx,Ry, w, [dash-pattern]) |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
method may be used (I<before> the annotation method itself is invoked). |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
'color' => [ Red, Green, Blue ] |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
This defines the stroke color of the button border, using the RGB triplet way |
|
142
|
|
|
|
|
|
|
of describing a color (RGB anonymous array, each value 0 to 1). |
|
143
|
|
|
|
|
|
|
If 0 width does not work on all Readers to suppress the border, selecting a |
|
144
|
|
|
|
|
|
|
color that matches any fill or background color in the button may work instead. |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
Instead of this hash element being used, the |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
$ann->Color(Red, Green, Blue) |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
method may be used (I<before> the annotation method itself is invoked). Note |
|
151
|
|
|
|
|
|
|
that Color is capitalized, unlike the hash option method. |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
It's a matter of stylistic choice whether to give these settings as options |
|
154
|
|
|
|
|
|
|
to the annotation object in the call, or call their methods directly I<before> |
|
155
|
|
|
|
|
|
|
the annotation action method itself is called. |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Some calls have additional optional parameters, which will be described in |
|
158
|
|
|
|
|
|
|
their section. |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head2 Annotation types |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head3 goto, link |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
$annotation->goto($page, $location, @args, %opts) # preferred |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
$annotation->goto($page, %opts) # location info as a hash element |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=over |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Defines the annotation as a PDF launch-page with page object C<$page> (within |
|
171
|
|
|
|
|
|
|
I<this> document), 'fit', and opts %opts (common parameters and optionally |
|
172
|
|
|
|
|
|
|
I<fit>: see descriptions below). |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
B<Note> that C<$page> is I<not> a simple page number, but is either a page |
|
175
|
|
|
|
|
|
|
I<object> such as C<$pdf-E<gt>openpage(page_number)>, I<or> a Named |
|
176
|
|
|
|
|
|
|
Destination defined elsewhere (a prefix of '#' or '/' is optional, except when |
|
177
|
|
|
|
|
|
|
the Named Destination is entirely numeric, and then it is required). 'foo', |
|
178
|
|
|
|
|
|
|
'#foo', and '/3659' are examples of Named Destinations. |
|
179
|
|
|
|
|
|
|
If a Named Destination is given, the page fit (location) is ignored, as the |
|
180
|
|
|
|
|
|
|
Named Destination handles that. |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
Note that the I<options> %opts is a hash, permitting 'rect', 'border', and |
|
183
|
|
|
|
|
|
|
'color' to be described in a more natural manner than flattening the hash into |
|
184
|
|
|
|
|
|
|
an array. The location and its arguments (fit data) may be either a list |
|
185
|
|
|
|
|
|
|
(in the PDF::API2 style) or another hash element. |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
B<Alternate name:> C<link> |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
Originally this method was named C<link>, but PDF::API2 changed it to |
|
190
|
|
|
|
|
|
|
C<goto>, to correspond to the B<GoTo> PDF command used. For compatibility, it |
|
191
|
|
|
|
|
|
|
has been changed to C<goto>, with C<link> still available as an alias. |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=back |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=cut |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
# this nonsense seems to be necessary (to alias goto with link) because |
|
198
|
|
|
|
|
|
|
# Perl gets confused and thinks it's a "goto label" statement! |
|
199
|
|
|
|
|
|
|
sub link { ## no critic |
|
200
|
1
|
|
|
1
|
1
|
7
|
my $self = shift; |
|
201
|
1
|
|
|
|
|
7
|
return $self->goto(@_); } |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub goto { |
|
204
|
1
|
|
|
1
|
1
|
4
|
my ($self, $page, @args) = @_; |
|
205
|
|
|
|
|
|
|
# page may be a page object, or a Named Destination string |
|
206
|
|
|
|
|
|
|
# if location and its parms are a list, made a hash element, |
|
207
|
|
|
|
|
|
|
# like any rect/color/border hash elements |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
# dest() will process it again, but we need hash for button settings |
|
210
|
1
|
|
|
|
|
12
|
my %opts = PDF::Builder::NamedDestination->list2hash(@args); |
|
211
|
1
|
|
|
|
|
4
|
$self->{'Subtype'} = PDFName('Link'); |
|
212
|
1
|
|
|
|
|
4
|
$self->{'A'} = PDFDict(); |
|
213
|
1
|
|
|
|
|
3
|
$self->{'A'}->{'S'} = PDFName('GoTo'); |
|
214
|
1
|
50
|
|
|
|
4
|
if (ref($page)) { |
|
215
|
|
|
|
|
|
|
# page structure |
|
216
|
1
|
|
|
|
|
35
|
$self->{'A'}->{'D'} = |
|
217
|
|
|
|
|
|
|
PDF::Builder::NamedDestination->dest($page, %opts); |
|
218
|
|
|
|
|
|
|
# fit type and parameters in args |
|
219
|
|
|
|
|
|
|
} else { |
|
220
|
|
|
|
|
|
|
# named destination |
|
221
|
|
|
|
|
|
|
# strip off any # or /, make sure it's a string |
|
222
|
0
|
0
|
|
|
|
0
|
if ($page =~ /^[#\/](.+)/) { |
|
223
|
0
|
|
|
|
|
0
|
$page = "$1"; |
|
224
|
|
|
|
|
|
|
} |
|
225
|
0
|
|
|
|
|
0
|
$self->{'A'}->{'D'} = PDFString($page, 'n'); |
|
226
|
|
|
|
|
|
|
} |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# click area rectangle (button) |
|
229
|
1
|
50
|
|
|
|
5
|
$self->rect(@{$opts{'rect'}}) if defined $opts{'rect'}; |
|
|
0
|
|
|
|
|
0
|
|
|
230
|
1
|
50
|
|
|
|
4
|
$self->border(@{$opts{'border'}}) if defined $opts{'border'}; |
|
|
0
|
|
|
|
|
0
|
|
|
231
|
1
|
50
|
|
|
|
14
|
$self->Color(@{$opts{'color'}}) if defined $opts{'color'}; |
|
|
0
|
|
|
|
|
0
|
|
|
232
|
|
|
|
|
|
|
|
|
233
|
1
|
|
|
|
|
4
|
return $self; |
|
234
|
|
|
|
|
|
|
} |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=head3 pdf, pdfile, pdf_file |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
$annotation->pdf($pdffile, $page_number, $location, @args, %opts) # preferred |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
$annotation->pdf($pdffile, $page_number, %opts) # including location & data |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=over |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Defines the annotation as an B<external> PDF-file with filepath C<$pdffile>, |
|
245
|
|
|
|
|
|
|
on page C<$page_number>, and options %opts (common parameters and I<fit>: see |
|
246
|
|
|
|
|
|
|
descriptions below). This differs from the C<goto> call in that the target |
|
247
|
|
|
|
|
|
|
is found in a I<different> PDF file, not the current document. Your operating |
|
248
|
|
|
|
|
|
|
system may warn you that you are going to a different file. |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
C<$page_number> is the physical page number, starting at 1: 1, 2,..., I<or> a |
|
251
|
|
|
|
|
|
|
Named Destination defined in that document (a prefix of '#' or '/' is optional, |
|
252
|
|
|
|
|
|
|
except when the Named Destination is entirely numeric, and then it is |
|
253
|
|
|
|
|
|
|
required). 'foo', '/foo', and '#3659' are examples of Named Destinations. |
|
254
|
|
|
|
|
|
|
If a Named Destination is used, the page fit (location) is ignored, as the |
|
255
|
|
|
|
|
|
|
Named Destination handles that. |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
Note that the I<options> %opts is a hash, while the location and fit @args |
|
258
|
|
|
|
|
|
|
may be described as a list (PDF::API2 style), or as another hash element. |
|
259
|
|
|
|
|
|
|
This permits 'rect', 'border', and 'color' to be |
|
260
|
|
|
|
|
|
|
described in a more natural manner than flattening the hash into an array. |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
B<Alternate names:> C<pdfile> and C<pdf_file> |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
Originally this method was named C<pdfile>, and then C<pdf_file> but |
|
265
|
|
|
|
|
|
|
PDF::API2 changed it to C<pdf>. For compatibility, it has been changed to |
|
266
|
|
|
|
|
|
|
C<pdf>, with C<pdfile> and C<pdf_file> still available as aliases. |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=back |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=cut |
|
271
|
|
|
|
|
|
|
|
|
272
|
0
|
|
|
0
|
1
|
0
|
sub pdfile { return pdf(@_); } ## no critic |
|
273
|
0
|
|
|
0
|
1
|
0
|
sub pdf_file { return pdf(@_); } ## no critic |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
sub pdf { |
|
276
|
|
|
|
|
|
|
# page may be a page number, or a Named Destination string |
|
277
|
|
|
|
|
|
|
# args include location and its parms as either hash element or a list, |
|
278
|
|
|
|
|
|
|
# and optionally (if not set externally), rect/color/border hash elements |
|
279
|
|
|
|
|
|
|
|
|
280
|
1
|
|
|
1
|
1
|
8
|
my ($self, $file, $page_number, @args) = @_; |
|
281
|
|
|
|
|
|
|
# dest() will process it again, but we need hash for button settings |
|
282
|
1
|
|
|
|
|
12
|
my %opts = PDF::Builder::NamedDestination->list2hash(@args); |
|
283
|
|
|
|
|
|
|
|
|
284
|
1
|
|
|
|
|
4
|
$self->{'Subtype'} = PDFName('Link'); |
|
285
|
1
|
|
|
|
|
5
|
$self->{'A'} = PDFDict(); |
|
286
|
1
|
|
|
|
|
4
|
$self->{'A'}->{'S'} = PDFName('GoToR'); |
|
287
|
1
|
|
|
|
|
4
|
$self->{'A'}->{'F'} = PDFString($file, 'u'); |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# if an integer $page_number, /D [page_num fit] |
|
290
|
1
|
50
|
|
|
|
10
|
if ($page_number =~ /^\d+$/) { |
|
291
|
1
|
|
|
|
|
3
|
$page_number--; # wants it numbered starting at 0 |
|
292
|
1
|
|
|
|
|
8
|
$self->{'A'}->{'D'} = |
|
293
|
|
|
|
|
|
|
PDF::Builder::NamedDestination->dest($page_number, %opts); |
|
294
|
|
|
|
|
|
|
# fit info opts |
|
295
|
|
|
|
|
|
|
} else { |
|
296
|
|
|
|
|
|
|
# string 'page_number' is a Named Destination, /D (foo) |
|
297
|
|
|
|
|
|
|
# any prefix of '#' or '/' will be stripped off |
|
298
|
0
|
0
|
|
|
|
0
|
if ($page_number =~ /^[#\/](.+)$/) { |
|
299
|
0
|
|
|
|
|
0
|
$page_number = "$1"; # if all numeric, make sure it's a string |
|
300
|
|
|
|
|
|
|
} |
|
301
|
0
|
|
|
|
|
0
|
$self->{'A'}->{'D'} = PDFString("$page_number", 'n'); |
|
302
|
|
|
|
|
|
|
} |
|
303
|
|
|
|
|
|
|
|
|
304
|
1
|
50
|
|
|
|
5
|
$self->rect(@{$opts{'rect'}}) if defined $opts{'rect'}; |
|
|
0
|
|
|
|
|
0
|
|
|
305
|
1
|
50
|
|
|
|
4
|
$self->border(@{$opts{'border'}}) if defined $opts{'border'}; |
|
|
0
|
|
|
|
|
0
|
|
|
306
|
1
|
50
|
|
|
|
4
|
$self->Color(@{$opts{'color'}}) if defined $opts{'color'}; |
|
|
0
|
|
|
|
|
0
|
|
|
307
|
|
|
|
|
|
|
|
|
308
|
1
|
|
|
|
|
4
|
return $self; |
|
309
|
|
|
|
|
|
|
} |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=head3 uri, url |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
$annotation->uri($url, %opts) |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=over |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Defines the annotation as a launch-url with url C<$url> and |
|
318
|
|
|
|
|
|
|
options %opts (common parameters). |
|
319
|
|
|
|
|
|
|
This page is usually brought up in a browser, and may be remote. This |
|
320
|
|
|
|
|
|
|
depends on your operating system configuration. |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
B<Alternate name:> C<url> |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
Originally this method was named C<url>, but PDF::API2 changed it to |
|
325
|
|
|
|
|
|
|
C<uri> to correspond to the B<URI> PDF command used. For compatibility, it has |
|
326
|
|
|
|
|
|
|
been changed to C<uri>, with C<url> still available as an alias. |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=back |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=cut |
|
331
|
|
|
|
|
|
|
|
|
332
|
0
|
|
|
0
|
1
|
0
|
sub url { return uri(@_); } ## no critic |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub uri { |
|
335
|
1
|
|
|
1
|
1
|
8
|
my ($self, $url, %opts) = @_; |
|
336
|
|
|
|
|
|
|
# copy dashed names over to preferred non-dashed names |
|
337
|
|
|
|
|
|
|
# there are no other options, unlike goto() and pdf(), so no call dest() |
|
338
|
1
|
|
|
|
|
5
|
%opts = dashed2nondashed(%opts); |
|
339
|
|
|
|
|
|
|
|
|
340
|
1
|
|
|
|
|
4
|
$self->{'Subtype'} = PDFName('Link'); |
|
341
|
1
|
|
|
|
|
3
|
$self->{'A'} = PDFDict(); |
|
342
|
|
|
|
|
|
|
# note that the following code produces /A << /S /URI /URI (url) >> |
|
343
|
1
|
|
|
|
|
4
|
$self->{'A'}->{'S'} = PDFName('URI'); |
|
344
|
1
|
|
|
|
|
4
|
$self->{'A'}->{'URI'} = PDFString($url, 'u'); |
|
345
|
|
|
|
|
|
|
|
|
346
|
1
|
50
|
|
|
|
4
|
$self->rect(@{$opts{'rect'}}) if defined $opts{'rect'}; |
|
|
0
|
|
|
|
|
0
|
|
|
347
|
1
|
50
|
|
|
|
5
|
$self->Color(@{$opts{'color'}}) if defined $opts{'color'}; |
|
|
0
|
|
|
|
|
0
|
|
|
348
|
1
|
50
|
|
|
|
4
|
$self->border(@{$opts{'border'}}) if defined $opts{'border'}; |
|
|
0
|
|
|
|
|
0
|
|
|
349
|
|
|
|
|
|
|
|
|
350
|
1
|
|
|
|
|
3
|
return $self; |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=head3 launch, file |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
$annotation->launch($file, %opts) |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=over |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
Defines the annotation as a launch-file with filepath C<$file> (a local file, |
|
360
|
|
|
|
|
|
|
often an executable or script/batch file) |
|
361
|
|
|
|
|
|
|
and options %opts (common parameters). |
|
362
|
|
|
|
|
|
|
I<How> the file is "launched" or displayed depends on the operating system, |
|
363
|
|
|
|
|
|
|
type of file, and local configuration or mapping. Common applications are to |
|
364
|
|
|
|
|
|
|
bring up a text editor to display a file, or start a photo viewer. |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
B<Alternate name:> C<file> |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
Originally this method was named C<file>, but PDF::API2 changed it to |
|
369
|
|
|
|
|
|
|
C<launch> to correspond to the B<Launch> PDF command used. For compatibility, |
|
370
|
|
|
|
|
|
|
it has been changed to C<launch>, with C<file> |
|
371
|
|
|
|
|
|
|
still available as an alias. |
|
372
|
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
=back |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=cut |
|
376
|
|
|
|
|
|
|
|
|
377
|
0
|
|
|
0
|
1
|
0
|
sub file { return launch(@_); } ## no critic |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
sub launch { |
|
380
|
1
|
|
|
1
|
1
|
9
|
my ($self, $file, %opts) = @_; |
|
381
|
|
|
|
|
|
|
# copy dashed names over to preferred non-dashed names |
|
382
|
1
|
|
|
|
|
6
|
%opts = dashed2nondashed(%opts); |
|
383
|
|
|
|
|
|
|
|
|
384
|
1
|
|
|
|
|
4
|
$self->{'Subtype'} = PDFName('Link'); |
|
385
|
1
|
|
|
|
|
5
|
$self->{'A'} = PDFDict(); |
|
386
|
1
|
|
|
|
|
4
|
$self->{'A'}->{'S'} = PDFName('Launch'); |
|
387
|
1
|
|
|
|
|
4
|
$self->{'A'}->{'F'} = PDFString($file, 'f'); |
|
388
|
|
|
|
|
|
|
|
|
389
|
1
|
50
|
|
|
|
5
|
$self->rect(@{$opts{'rect'}}) if defined $opts{'rect'}; |
|
|
0
|
|
|
|
|
0
|
|
|
390
|
1
|
50
|
|
|
|
5
|
$self->Color(@{$opts{'color'}}) if defined $opts{'color'}; |
|
|
0
|
|
|
|
|
0
|
|
|
391
|
1
|
50
|
|
|
|
4
|
$self->border(@{$opts{'border'}}) if defined $opts{'border'}; |
|
|
0
|
|
|
|
|
0
|
|
|
392
|
|
|
|
|
|
|
|
|
393
|
1
|
|
|
|
|
4
|
return $self; |
|
394
|
|
|
|
|
|
|
} |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=head3 text |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
$annotation->text($text, %opts) |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
=over |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
Defines the annotation as a text note with content string C<$text> and |
|
403
|
|
|
|
|
|
|
options %opts (common parameters, text, open: see descriptions below). |
|
404
|
|
|
|
|
|
|
The C<$text> may include newlines \n for multiple lines. Note that the option |
|
405
|
|
|
|
|
|
|
'border' is ignored, since an I<icon> is used. |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
The option C<text> is the popup's label string, not to be confused with the |
|
408
|
|
|
|
|
|
|
main C<$text>. |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
The icon appears in the upper left corner of the C<rect> selection rectangle, |
|
411
|
|
|
|
|
|
|
and its active clickable area is fixed by the icon (it is I<not> equal to the |
|
412
|
|
|
|
|
|
|
rectangle). The icon size is fixed, and its fill color set by C<color>. |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
Additional options: |
|
415
|
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=back |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=over |
|
419
|
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=item icon => name_string |
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=item icon => reference |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
Specify the B<icon> to be used. The default is Reader-specific (usually |
|
425
|
|
|
|
|
|
|
C<Note>), and others may be |
|
426
|
|
|
|
|
|
|
defined by the Reader. C<Comment>, C<Key>, C<Help>, C<NewParagraph>, |
|
427
|
|
|
|
|
|
|
C<Paragraph>, and C<Insert> are also supposed to |
|
428
|
|
|
|
|
|
|
be available on all PDF Readers. Note that the name I<case> must exactly match. |
|
429
|
|
|
|
|
|
|
The icon is of fixed size. |
|
430
|
|
|
|
|
|
|
Any I<AP> dictionary entry will override the icon setting. |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
A I<reference> to an icon may be passed instead of a name. |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
=item opacity => I<value> |
|
435
|
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
Define the opacity (non-transparency, opaqueness) of the icon. This value |
|
437
|
|
|
|
|
|
|
ranges from 0.0 (transparent) to 1.0 (fully opaque), and applies to both |
|
438
|
|
|
|
|
|
|
the outline and the fill color. The default is 1.0. |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=back |
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
=cut |
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
# the icon size appears to be fixed. the last font size used does not affect it |
|
445
|
|
|
|
|
|
|
# and enabling icon_appearance() for it doesn't seem to do anything |
|
446
|
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
sub text { |
|
448
|
2
|
|
|
2
|
1
|
22
|
my ($self, $text, %opts) = @_; |
|
449
|
|
|
|
|
|
|
# copy dashed names over to preferred non-dashed names |
|
450
|
2
|
|
|
|
|
9
|
%opts = dashed2nondashed(%opts); |
|
451
|
|
|
|
|
|
|
|
|
452
|
2
|
|
|
|
|
9
|
$self->{'Subtype'} = PDFName('Text'); |
|
453
|
2
|
|
|
|
|
9
|
$self->content($text); |
|
454
|
|
|
|
|
|
|
|
|
455
|
2
|
50
|
|
|
|
8
|
$self->rect(@{$opts{'rect'}}) if defined $opts{'rect'}; |
|
|
2
|
|
|
|
|
11
|
|
|
456
|
2
|
50
|
|
|
|
10
|
$self->Color(@{$opts{'color'}}) if defined $opts{'color'}; |
|
|
0
|
|
|
|
|
0
|
|
|
457
|
|
|
|
|
|
|
#$self->border($opts{'border'}) if defined $opts{'border'}; # ignored |
|
458
|
2
|
50
|
|
|
|
6
|
$self->open($opts{'open'}) if defined $opts{'open'}; |
|
459
|
|
|
|
|
|
|
# popup label (title) |
|
460
|
|
|
|
|
|
|
# have seen /T as (xFEFF UTF-16 chars) |
|
461
|
2
|
50
|
|
|
|
7
|
$self->{'T'} = PDFString($opts{'text'}, 'p') if exists $opts{'text'}; |
|
462
|
|
|
|
|
|
|
# icon opacity? |
|
463
|
2
|
50
|
|
|
|
7
|
if (defined $opts{'opacity'}) { |
|
464
|
0
|
|
|
|
|
0
|
$self->{'CA'} = PDFNum($opts{'opacity'}); |
|
465
|
|
|
|
|
|
|
} |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
# Icon Name will be ignored if there is an AP. |
|
468
|
2
|
|
|
|
|
6
|
my $icon; # perlcritic doesn't want 2 lines combined |
|
469
|
2
|
50
|
|
|
|
5
|
$icon = $opts{'icon'} if exists $opts{'icon'}; |
|
470
|
2
|
50
|
33
|
|
|
9
|
$self->{'Name'} = PDFName($icon) if $icon && !ref($icon); # icon name |
|
471
|
|
|
|
|
|
|
# Set the icon appearance |
|
472
|
2
|
50
|
|
|
|
6
|
$self->icon_appearance($icon, %opts) if $icon; |
|
473
|
|
|
|
|
|
|
|
|
474
|
2
|
|
|
|
|
8
|
return $self; |
|
475
|
|
|
|
|
|
|
} |
|
476
|
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
=head3 markup |
|
478
|
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
$annotation->markup($text, $PointList, $highlight, %opts) |
|
480
|
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=over |
|
482
|
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
Defines the annotation as a text note with content string C<$text> and |
|
484
|
|
|
|
|
|
|
options %opts (color, text, open, opacity: see descriptions below). |
|
485
|
|
|
|
|
|
|
The C<$text> may include newlines \n for multiple lines. |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
C<text> is the popup's label string, not to be confused with the main C<$text>. |
|
488
|
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
There is no icon. Instead, the annotated text marked by C<$PointList> is |
|
490
|
|
|
|
|
|
|
highlighted in one of four ways specified by C<$highlight>. |
|
491
|
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=back |
|
493
|
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=over |
|
495
|
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=item $PointList => [ 8n numbers ] |
|
497
|
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
One or more sets of numeric coordinates are given, defining the quadrilateral |
|
499
|
|
|
|
|
|
|
(usually a rectangle) around the text to be highlighted and selectable |
|
500
|
|
|
|
|
|
|
(clickable, to bring up the annotation text). These |
|
501
|
|
|
|
|
|
|
are four sets of C<x,y> coordinates, given (for Left-to-Right text) as the |
|
502
|
|
|
|
|
|
|
upper bound Upper Left to Upper Right and then the lower bound Lower Left to |
|
503
|
|
|
|
|
|
|
Lower Right. B<Note that this is different from what is (erroneously) |
|
504
|
|
|
|
|
|
|
documented in some PDF specifications!> It is important that the coordinates |
|
505
|
|
|
|
|
|
|
be given in this order. |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
Multiple sets of quadrilateral corners may be given, such as for highlighted |
|
508
|
|
|
|
|
|
|
text that wraps around to new line(s). The minimum is one set (8 numbers). |
|
509
|
|
|
|
|
|
|
Any I<AP> dictionary entry will override the C<$PointList> setting. Finally, |
|
510
|
|
|
|
|
|
|
the "Rect" selection rectangle is created I<just outside> the convex bounding |
|
511
|
|
|
|
|
|
|
box defined by C<$PointList>. |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
=item $highlight => 'string' |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
The following highlighting effects are permitted. The C<string> must be |
|
516
|
|
|
|
|
|
|
spelled and capitalized I<exactly> as given: |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
=over |
|
519
|
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=item Highlight |
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
The effect of a translucent "highlighter" marker. |
|
523
|
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
=item Squiggly |
|
525
|
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
The effect is an underline written in a "squiggly" manner. |
|
527
|
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
=item StrikeOut |
|
529
|
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
The text is struck-through with a straight line. |
|
531
|
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
=item Underline |
|
533
|
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
The text is marked by a straight underline. |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
=back |
|
537
|
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
=item color => I<array of values> |
|
539
|
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
If C<color> is not given (an array of numbers in the range 0.0-1.0), a |
|
541
|
|
|
|
|
|
|
medium gray should be used by default. |
|
542
|
|
|
|
|
|
|
Named colors are not supported at this time. |
|
543
|
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
=item opacity => I<value> |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
Define the opacity (non-transparency, opaqueness) of the icon. This value |
|
547
|
|
|
|
|
|
|
ranges from 0.0 (transparent) to 1.0 (fully opaque), and applies to both |
|
548
|
|
|
|
|
|
|
the outline and the fill color. The default is 1.0. |
|
549
|
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
=back |
|
551
|
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
=cut |
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
sub markup { |
|
555
|
0
|
|
|
0
|
1
|
0
|
my ($self, $text, $PointList, $highlight, %opts) = @_; |
|
556
|
|
|
|
|
|
|
# copy dashed names over to preferred non-dashed names |
|
557
|
0
|
|
|
|
|
0
|
%opts = dashed2nondashed(%opts); |
|
558
|
|
|
|
|
|
|
|
|
559
|
0
|
|
|
|
|
0
|
my @pointList = @{ $PointList }; |
|
|
0
|
|
|
|
|
0
|
|
|
560
|
0
|
0
|
0
|
|
|
0
|
if ((scalar @pointList) == 0 || (scalar @pointList)%8) { |
|
561
|
0
|
|
|
|
|
0
|
die "markup point list does not have 8*N entries!\n"; |
|
562
|
|
|
|
|
|
|
} |
|
563
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName($highlight); |
|
564
|
0
|
|
|
|
|
0
|
delete $self->{'Border'}; |
|
565
|
0
|
|
|
|
|
0
|
$self->{'QuadPoints'} = PDFArray(map {PDFNum($_)} @pointList); |
|
|
0
|
|
|
|
|
0
|
|
|
566
|
0
|
|
|
|
|
0
|
$self->content($text); |
|
567
|
|
|
|
|
|
|
|
|
568
|
0
|
|
|
|
|
0
|
my $minX = min($pointList[0], $pointList[2], $pointList[4], $pointList[6]); |
|
569
|
0
|
|
|
|
|
0
|
my $maxX = max($pointList[0], $pointList[2], $pointList[4], $pointList[6]); |
|
570
|
0
|
|
|
|
|
0
|
my $minY = min($pointList[1], $pointList[3], $pointList[5], $pointList[7]); |
|
571
|
0
|
|
|
|
|
0
|
my $maxY = max($pointList[1], $pointList[3], $pointList[5], $pointList[7]); |
|
572
|
0
|
|
|
|
|
0
|
$self->rect($minX-.5,$minY-.5, $maxX+.5,$maxY+.5); |
|
573
|
|
|
|
|
|
|
|
|
574
|
0
|
0
|
|
|
|
0
|
$self->open($opts{'open'}) if defined $opts{'open'}; |
|
575
|
0
|
0
|
|
|
|
0
|
if (defined $opts{'color'}) { |
|
576
|
0
|
|
|
|
|
0
|
$self->Color(@{$opts{'color'}}); |
|
|
0
|
|
|
|
|
0
|
|
|
577
|
|
|
|
|
|
|
} else { |
|
578
|
0
|
|
|
|
|
0
|
$self->Color([]); |
|
579
|
|
|
|
|
|
|
} |
|
580
|
|
|
|
|
|
|
# popup label (title) |
|
581
|
|
|
|
|
|
|
# have seen /T as (xFEFF UTF-16 chars) |
|
582
|
0
|
0
|
|
|
|
0
|
$self->{'T'} = PDFString($opts{'text'}, 'p') if exists $opts{'text'}; |
|
583
|
|
|
|
|
|
|
# opacity? |
|
584
|
0
|
0
|
|
|
|
0
|
if (defined $opts{'opacity'}) { |
|
585
|
0
|
|
|
|
|
0
|
$self->{'CA'} = PDFNum($opts{'opacity'}); |
|
586
|
|
|
|
|
|
|
} |
|
587
|
|
|
|
|
|
|
|
|
588
|
0
|
|
|
|
|
0
|
return $self; |
|
589
|
|
|
|
|
|
|
} |
|
590
|
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
=head3 movie |
|
592
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
$annotation->movie($file, $contentType, %opts) |
|
594
|
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
=over |
|
596
|
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
Defines the annotation as a movie from C<$file> with |
|
598
|
|
|
|
|
|
|
content (MIME) type C<$contentType> and |
|
599
|
|
|
|
|
|
|
options %opts (common parameters, text: see descriptions below). |
|
600
|
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
The C<rect> rectangle B<also serves as the area where the movie is played>, so |
|
602
|
|
|
|
|
|
|
it should be of usable size and aspect ratio. It does not use a separate popup |
|
603
|
|
|
|
|
|
|
player. It is known to play .avi and .wav files -- others have not been tested. |
|
604
|
|
|
|
|
|
|
Using Adobe Reader, it will not play .mpg files (unsupported type). More work |
|
605
|
|
|
|
|
|
|
is probably needed on this annotation method. |
|
606
|
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
=back |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
=cut |
|
610
|
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
sub movie { |
|
612
|
0
|
|
|
0
|
1
|
0
|
my ($self, $file, $contentType, %opts) = @_; |
|
613
|
|
|
|
|
|
|
# copy dashed names over to preferred non-dashed names |
|
614
|
0
|
|
|
|
|
0
|
%opts = dashed2nondashed(%opts); |
|
615
|
|
|
|
|
|
|
|
|
616
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName('Movie'); # subtype = movie (req) |
|
617
|
0
|
|
|
|
|
0
|
$self->{'A'} = PDFBool(1); # play using default activation parms |
|
618
|
0
|
|
|
|
|
0
|
$self->{'Movie'} = PDFDict(); |
|
619
|
|
|
|
|
|
|
#$self->{'Movie'}->{'S'} = PDFName($contentType); |
|
620
|
0
|
|
|
|
|
0
|
$self->{'Movie'}->{'F'} = PDFString($file, 'f'); |
|
621
|
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
# PDF::API2 2.034 changes don't seem to work |
|
623
|
|
|
|
|
|
|
# $self->{'Movie'}->{'F'} = PDFString($file, 'f'); line above removed |
|
624
|
|
|
|
|
|
|
#$self->{'Movie'}->{'F'} = PDFDict(); |
|
625
|
|
|
|
|
|
|
#$self->{' apipdf'}->new_obj($self->{'Movie'}->{'F'}); |
|
626
|
|
|
|
|
|
|
#my $f = $self->{'Movie'}->{'F'}; |
|
627
|
|
|
|
|
|
|
#$f->{'Type'} = PDFName('EmbeddedFile'); |
|
628
|
|
|
|
|
|
|
#$f->{'Subtype'} = PDFName($contentType); |
|
629
|
|
|
|
|
|
|
#$f->{' streamfile'} = $file; |
|
630
|
|
|
|
|
|
|
|
|
631
|
0
|
0
|
|
|
|
0
|
$self->rect(@{$opts{'rect'}}) if defined $opts{'rect'}; |
|
|
0
|
|
|
|
|
0
|
|
|
632
|
0
|
0
|
|
|
|
0
|
$self->border(@{$opts{'border'}}) if defined $opts{'border'}; |
|
|
0
|
|
|
|
|
0
|
|
|
633
|
0
|
0
|
|
|
|
0
|
$self->Color(@{$opts{'color'}}) if defined $opts{'color'}; |
|
|
0
|
|
|
|
|
0
|
|
|
634
|
|
|
|
|
|
|
# popup label (title) DOESN'T SEEM TO SHOW UP ANYWHERE |
|
635
|
|
|
|
|
|
|
# self->A->T and self->T also fail to display |
|
636
|
0
|
0
|
|
|
|
0
|
$self->{'Movie'}->{'T'} = PDFString($opts{'text'}, 'p') if exists $opts{'text'}; |
|
637
|
|
|
|
|
|
|
|
|
638
|
0
|
|
|
|
|
0
|
return $self; |
|
639
|
|
|
|
|
|
|
} |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
=head3 file_attachment |
|
642
|
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
$annotation->file_attachment($file, %opts) |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=over |
|
646
|
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
Defines the annotation as a file attachment with file $file and options %opts |
|
648
|
|
|
|
|
|
|
(common parameters: see descriptions below). Note that C<color> applies to |
|
649
|
|
|
|
|
|
|
the icon fill color, not to a selectable area outline. The icon is resized |
|
650
|
|
|
|
|
|
|
(including aspect ratio changes) based on the selectable rectangle given by |
|
651
|
|
|
|
|
|
|
C<rect>, so watch your rectangle dimensions! |
|
652
|
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
The file, along with its name, is I<embedded> in the PDF document and may be |
|
654
|
|
|
|
|
|
|
extracted for viewing with the appropriate viewer. |
|
655
|
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
This differs from the C<file> method in that C<file> looks for and launches |
|
657
|
|
|
|
|
|
|
a file I<already> on the Reader's machine, while C<file_attachment> embeds the |
|
658
|
|
|
|
|
|
|
file in the PDF, and makes it available on the Reader's machine for actions |
|
659
|
|
|
|
|
|
|
of the user's choosing. |
|
660
|
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
B<Note 1:> some Readers may only permit an "open" action, and may also restrict |
|
662
|
|
|
|
|
|
|
file types (extensions) that will be handled. This may be configurable with |
|
663
|
|
|
|
|
|
|
your Reader's security settings. |
|
664
|
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
B<Note 2:> the displayed file name (pop-up during mouse rollover of the target |
|
666
|
|
|
|
|
|
|
rectangle) is given with the I<path> trimmed off (file name only). If you want |
|
667
|
|
|
|
|
|
|
the displayed name to exactly match the path that was passed to the call, |
|
668
|
|
|
|
|
|
|
including the path, give the C<notrimpath> option. |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
Options: |
|
671
|
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
=back |
|
673
|
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
=over |
|
675
|
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
=item icon => name_string |
|
677
|
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
=item icon => reference |
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
Specify the B<icon> to be used. The default is Reader-specific (usually |
|
681
|
|
|
|
|
|
|
C<PushPin>), and others may be |
|
682
|
|
|
|
|
|
|
defined by the Reader. C<Paperclip>, C<Graph>, and C<Tag> are also supposed to |
|
683
|
|
|
|
|
|
|
be available on all PDF Readers. Note that the name I<case> must exactly match. |
|
684
|
|
|
|
|
|
|
C<None> is a custom invisible icon defined by PDF::Builder. |
|
685
|
|
|
|
|
|
|
The icon is stretched/squashed to fill the defined target rectangle, so take |
|
686
|
|
|
|
|
|
|
care when defining C<rect> dimensions. |
|
687
|
|
|
|
|
|
|
Any I<AP> dictionary entry will override the icon setting. |
|
688
|
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
A I<reference> to an icon may be passed instead of a name. |
|
690
|
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
=item opacity => I<value> |
|
692
|
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
Define the opacity (non-transparency, opaqueness) of the icon. This value |
|
694
|
|
|
|
|
|
|
ranges from 0.0 (transparent) to 1.0 (fully opaque), and applies to both |
|
695
|
|
|
|
|
|
|
the outline and the fill color. The default is 1.0. |
|
696
|
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
=item notrimpath => 1 |
|
698
|
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
If given, show the entire path and file name on mouse rollover, rather than |
|
700
|
|
|
|
|
|
|
just the file name. |
|
701
|
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
=item text => string |
|
703
|
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
A text label for the popup (on mouseover) that contains the file name. |
|
705
|
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
=back |
|
707
|
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
Note that while PDF permits different specifications (paths) to DOS/Windows, |
|
709
|
|
|
|
|
|
|
Mac, and Unix (including Linux) versions of a file, and different format copies |
|
710
|
|
|
|
|
|
|
to be embedded, at this time PDF::Builder only permits a single file (format of |
|
711
|
|
|
|
|
|
|
your choice) to be embedded. If there is user demand for multiple file formats |
|
712
|
|
|
|
|
|
|
to be referenced and/or embedded, we could look into providing this, I<although |
|
713
|
|
|
|
|
|
|
separate OS version paths B<may> be considered obsolescent!>. |
|
714
|
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
=cut |
|
716
|
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
# TBD it is possible to specify different files for DOS, Mac, Unix |
|
718
|
|
|
|
|
|
|
# (see PDF 1.7 7.11.4.2). This might solve problem of different line |
|
719
|
|
|
|
|
|
|
# ends, at the cost of 3 copies of each file. |
|
720
|
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
sub file_attachment { |
|
722
|
0
|
|
|
0
|
1
|
0
|
my ($self, $file, %opts) = @_; |
|
723
|
|
|
|
|
|
|
# copy dashed names over to preferred non-dashed names |
|
724
|
0
|
|
|
|
|
0
|
%opts = dashed2nondashed(%opts); |
|
725
|
|
|
|
|
|
|
|
|
726
|
0
|
|
|
|
|
0
|
my $icon; # defaults to Reader's default (usually PushPin) |
|
727
|
0
|
0
|
|
|
|
0
|
$icon = $opts{'icon'} if exists $opts{'icon'}; |
|
728
|
|
|
|
|
|
|
|
|
729
|
0
|
0
|
|
|
|
0
|
$self->rect(@{$opts{'rect'}}) if defined $opts{'rect'}; |
|
|
0
|
|
|
|
|
0
|
|
|
730
|
|
|
|
|
|
|
# descriptive text on mouse rollover |
|
731
|
0
|
0
|
|
|
|
0
|
$self->{'T'} = PDFString($opts{'text'}, 'p') if exists $opts{'text'}; |
|
732
|
|
|
|
|
|
|
# icon opacity? |
|
733
|
0
|
0
|
|
|
|
0
|
if (defined $opts{'opacity'}) { |
|
734
|
0
|
|
|
|
|
0
|
$self->{'CA'} = PDFNum($opts{'opacity'}); |
|
735
|
|
|
|
|
|
|
} |
|
736
|
|
|
|
|
|
|
|
|
737
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName('FileAttachment'); |
|
738
|
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
# 9 0 obj << |
|
740
|
|
|
|
|
|
|
# /Type /Annot |
|
741
|
|
|
|
|
|
|
# /Subtype /FileAttachment |
|
742
|
|
|
|
|
|
|
# /Name /PushPin |
|
743
|
|
|
|
|
|
|
# /C [ 1 1 0 ] |
|
744
|
|
|
|
|
|
|
# /Contents (test.txt) |
|
745
|
|
|
|
|
|
|
# /FS << |
|
746
|
|
|
|
|
|
|
# /Type /F |
|
747
|
|
|
|
|
|
|
# /EF << /F 10 0 R >> |
|
748
|
|
|
|
|
|
|
# /F (test.txt) |
|
749
|
|
|
|
|
|
|
# >> |
|
750
|
|
|
|
|
|
|
# /Rect [ 100 100 200 200 ] |
|
751
|
|
|
|
|
|
|
# /Border [ 0 0 1 ] |
|
752
|
|
|
|
|
|
|
# >> endobj |
|
753
|
|
|
|
|
|
|
# |
|
754
|
|
|
|
|
|
|
# 10 0 obj << |
|
755
|
|
|
|
|
|
|
# /Type /EmbeddedFile |
|
756
|
|
|
|
|
|
|
# /Length ... |
|
757
|
|
|
|
|
|
|
# >> stream |
|
758
|
|
|
|
|
|
|
# ... |
|
759
|
|
|
|
|
|
|
# endstream endobj |
|
760
|
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
# text label on pop-up for mouse rollover |
|
762
|
0
|
|
|
|
|
0
|
my $cName = $file; |
|
763
|
|
|
|
|
|
|
# trim off any path, leaving just the file name. less confusing that way |
|
764
|
0
|
0
|
|
|
|
0
|
if (!defined $opts{'notrimpath'}) { |
|
765
|
0
|
0
|
|
|
|
0
|
if ($cName =~ m#([^/\\]+)$#) { $cName = $1; } |
|
|
0
|
|
|
|
|
0
|
|
|
766
|
|
|
|
|
|
|
} |
|
767
|
0
|
|
|
|
|
0
|
$self->{'Contents'} = PDFString($cName, 's'); |
|
768
|
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
# Icon Name will be ignored if there is an AP. |
|
770
|
0
|
0
|
0
|
|
|
0
|
$self->{'Name'} = PDFName($icon) if $icon && !ref($icon); # icon name |
|
771
|
|
|
|
|
|
|
#$self->{'F'} = PDFNum(0b0); # flags default to 0 |
|
772
|
0
|
0
|
|
|
|
0
|
$self->Color(@{ $opts{'color'} }) if defined $opts{'color'}; |
|
|
0
|
|
|
|
|
0
|
|
|
773
|
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
# The File Specification. |
|
775
|
0
|
|
|
|
|
0
|
$self->{'FS'} = PDFDict(); |
|
776
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'F'} = PDFString($file, 'f'); |
|
777
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'Type'} = PDFName('Filespec'); |
|
778
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'EF'} = PDFDict($file); |
|
779
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'EF'}->{'F'} = PDFDict($file); |
|
780
|
0
|
|
|
|
|
0
|
$self->{' apipdf'}->new_obj($self->{'FS'}->{'EF'}->{'F'}); |
|
781
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'EF'}->{'F'}->{'Type'} = PDFName('EmbeddedFile'); |
|
782
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'EF'}->{'F'}->{' streamfile'} = $file; |
|
783
|
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
# Set the icon appearance |
|
785
|
0
|
0
|
|
|
|
0
|
$self->icon_appearance($icon, %opts) if $icon; |
|
786
|
|
|
|
|
|
|
|
|
787
|
0
|
|
|
|
|
0
|
return $self; |
|
788
|
|
|
|
|
|
|
} |
|
789
|
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
# TBD additional annotation types without icons |
|
791
|
|
|
|
|
|
|
# free text, line, square, circle, polygon (1.5), polyline (1.5), highlight, |
|
792
|
|
|
|
|
|
|
# underline, squiggly, strikeout, caret (1.5), ink, popup, sound, widget, |
|
793
|
|
|
|
|
|
|
# screen (1.5), printermark, trapnet, watermark (1.6), 3D (1.6), redact (1.7) |
|
794
|
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
# TBD additional annotation types with icons |
|
796
|
|
|
|
|
|
|
# stamp |
|
797
|
|
|
|
|
|
|
# icons: Approved, Experimental, NotApproved, Asis, Expired, |
|
798
|
|
|
|
|
|
|
# NotForPublicRelease, Confidential, Final, Sold, Departmental, |
|
799
|
|
|
|
|
|
|
# ForComment, TopSecret, Draft (def.), ForPublicRelease |
|
800
|
|
|
|
|
|
|
# sound |
|
801
|
|
|
|
|
|
|
# icons: Speaker (def.), Mic |
|
802
|
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
# =============== end of annotation types ======================== |
|
804
|
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
=head2 Internal routines and common options |
|
806
|
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
The common options may be called separately (applied against $annotation before |
|
808
|
|
|
|
|
|
|
calling the action routine), or passed as options to the call. |
|
809
|
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
=head3 rect |
|
811
|
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
$annotation->rect($llx,$lly, $urx,$ury) |
|
813
|
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
=over |
|
815
|
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
Sets the rectangle (active click area) of the annotation, given by 'rect' |
|
817
|
|
|
|
|
|
|
option. This is any pair of diagonally opposite corners of the rectangle. |
|
818
|
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
The default clickable area is the icon itself. |
|
820
|
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
Defining option. I<Note that this "option" is actually B<required>.> |
|
822
|
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
I<This call may be replaced by a hash element 'rect'=E<gt> in many calls |
|
824
|
|
|
|
|
|
|
(see Common parameters).> |
|
825
|
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
=back |
|
827
|
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
=over |
|
829
|
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
=item rect => [LLx, LLy, URx, URy] |
|
831
|
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
Set annotation rectangle I<as an option> at C<[LLx,LLy]> to C<[URx,URy]> |
|
833
|
|
|
|
|
|
|
(lower left and upper right coordinates). |
|
834
|
|
|
|
|
|
|
LL to UR is customary, but any diagonal is allowed. |
|
835
|
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
=back |
|
837
|
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
=cut |
|
839
|
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
sub rect { |
|
841
|
2
|
|
|
2
|
1
|
5
|
my ($self, @r) = @_; |
|
842
|
|
|
|
|
|
|
|
|
843
|
2
|
50
|
|
|
|
9
|
die "Insufficient parameters to annotation->rect() " unless scalar @r == 4; |
|
844
|
2
|
|
|
|
|
8
|
$self->{'Rect'} = PDFArray( map { PDFNum($_) } $r[0],$r[1],$r[2],$r[3]); |
|
|
8
|
|
|
|
|
18
|
|
|
845
|
2
|
|
|
|
|
5
|
return $self; |
|
846
|
|
|
|
|
|
|
} |
|
847
|
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
=head3 border |
|
849
|
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
$annotation->border(@b) |
|
851
|
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
=over |
|
853
|
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
Sets the border-style of the annotation, if applicable, as given by the |
|
855
|
|
|
|
|
|
|
border option. There are three entries in the array: |
|
856
|
|
|
|
|
|
|
horizontal and vertical corner radii, and border width. |
|
857
|
|
|
|
|
|
|
An optional fourth entry (described below) may be used for a dashed or dotted |
|
858
|
|
|
|
|
|
|
line. |
|
859
|
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
A border is used in annotations where text or some other material is put down, |
|
861
|
|
|
|
|
|
|
and a clickable rectangle is defined over it (rect). A border is not shown |
|
862
|
|
|
|
|
|
|
when an B<icon> is being used to mark the clickable area. |
|
863
|
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
A I<PDF Reader> normally defaults to [0 0 1] (solid line of width 1, with |
|
865
|
|
|
|
|
|
|
sharp corners) if no border (C</Border>) is specified. Keeping compatibility |
|
866
|
|
|
|
|
|
|
with PDF::API2's longstanding practice, PDF::Builder defaults to no visible |
|
867
|
|
|
|
|
|
|
border C<[0 0 0]> (solid line of width 0, and thus invisible). |
|
868
|
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
Defining option: |
|
870
|
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
=back |
|
872
|
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
=over |
|
874
|
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
=item border => [CRh, CRv, W] |
|
876
|
|
|
|
|
|
|
|
|
877
|
|
|
|
|
|
|
=item border => [CRh, CRv, W, [on, off...]] |
|
878
|
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
Note that the square brackets [ and ] are literally I<there>, indicating a |
|
880
|
|
|
|
|
|
|
vector or array of values. They do B<not> indicate optional values! |
|
881
|
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
Set annotation B<border style> of horizontal and vertical corner radii C<CRh> |
|
883
|
|
|
|
|
|
|
and C<CRv> (value 0 for squared corners) and width C<W> (value 0 for no border). |
|
884
|
|
|
|
|
|
|
The PDF::Builder default is no border (while a I<PDF Reader> typically defaults |
|
885
|
|
|
|
|
|
|
to no border ([0 0 0]), if no /Border entry is given). |
|
886
|
|
|
|
|
|
|
Optionally, a dash pattern array may be given (C<on> length, C<off> length, |
|
887
|
|
|
|
|
|
|
as one or more I<pairs>). The default is a solid line. |
|
888
|
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
The border vector seems to ignore the first two settings (corner radii), but |
|
890
|
|
|
|
|
|
|
the line thickness works, on basic Readers. |
|
891
|
|
|
|
|
|
|
The corner radii I<may> work on some other Readers. |
|
892
|
|
|
|
|
|
|
|
|
893
|
|
|
|
|
|
|
=back |
|
894
|
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
I<This call may be replaced by a hash element 'border'=E<gt> in many calls |
|
896
|
|
|
|
|
|
|
(see Common parameters).> |
|
897
|
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
=cut |
|
899
|
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
sub border { |
|
901
|
0
|
|
|
0
|
1
|
0
|
my ($self, @b) = @_; |
|
902
|
|
|
|
|
|
|
|
|
903
|
0
|
0
|
|
|
|
0
|
if (scalar @b == 3) { |
|
|
|
0
|
|
|
|
|
|
|
904
|
0
|
|
|
|
|
0
|
$self->{'Border'} = PDFArray( map { PDFNum($_) } $b[0],$b[1],$b[2]); |
|
|
0
|
|
|
|
|
0
|
|
|
905
|
|
|
|
|
|
|
} elsif (scalar @b == 4) { |
|
906
|
|
|
|
|
|
|
# b[3] is an anonymous array |
|
907
|
0
|
|
|
|
|
0
|
my @first = map { PDFNum($_) } $b[0], $b[1], $b[2]; |
|
|
0
|
|
|
|
|
0
|
|
|
908
|
0
|
|
|
|
|
0
|
$self->{'Border'} = PDFArray( @first, PDFArray( map { PDFNum($_) } @{$b[3]} )); |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
909
|
|
|
|
|
|
|
} else { |
|
910
|
0
|
|
|
|
|
0
|
die "annotation->border() style requires 3 or 4 parameters "; |
|
911
|
|
|
|
|
|
|
} |
|
912
|
0
|
|
|
|
|
0
|
return $self; |
|
913
|
|
|
|
|
|
|
} |
|
914
|
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
=head3 Color |
|
916
|
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
$annotation->Color(@color) |
|
918
|
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
=over |
|
920
|
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
Set the icon's fill color I<or> the click area's border color. The color is |
|
922
|
|
|
|
|
|
|
an array of 1, 3, or 4 numbers, each |
|
923
|
|
|
|
|
|
|
in the range 0.0 to 1.0. If 1 number is given, it is the grayscale value (0 = |
|
924
|
|
|
|
|
|
|
black to 1 = white). If 3 numbers are given, it is an RGB color value. If 4 |
|
925
|
|
|
|
|
|
|
numbers are given, it is a CMYK color value. Currently, named colors (strings) |
|
926
|
|
|
|
|
|
|
are not handled. |
|
927
|
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
For link and url annotations, this is the color of the rectangle border |
|
929
|
|
|
|
|
|
|
(border given with a width of at least 1). |
|
930
|
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
If an invalid array length or numeric value is given, a medium gray ( [0.5] ) |
|
932
|
|
|
|
|
|
|
value is used, without any message. If no color is given, the usual fill color |
|
933
|
|
|
|
|
|
|
is black. |
|
934
|
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
Defining option: |
|
936
|
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
Named colors (e.g., 'black') are not supported at this time. |
|
938
|
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
=back |
|
940
|
|
|
|
|
|
|
|
|
941
|
|
|
|
|
|
|
=over |
|
942
|
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
=item color => [ ] or not 1, 3, or 4 numbers 0.0-1.0 |
|
944
|
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
A medium gray (0.5 value) will be used if an invalid color is given. |
|
946
|
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
=item color => [ g ] |
|
948
|
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
If I<g> is between 0.0 (black) and 1.0 (white), the fill color will be gray. |
|
950
|
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
=item color => [ r, g, b ] |
|
952
|
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
If I<r> (red), I<g> (green), and I<b> (blue) are all between 0.0 and 1.0, the |
|
954
|
|
|
|
|
|
|
fill color will be the defined RGB hue. [ 0, 0, 0 ] is black, [ 1, 1, 0 ] is |
|
955
|
|
|
|
|
|
|
yellow, and [ 1, 1, 1 ] is white. |
|
956
|
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
=item color => [ c, m, y, k ] |
|
958
|
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
If I<c> (red), I<m> (magenta), I<y> (yellow), and I<k> (black) are all between |
|
960
|
|
|
|
|
|
|
0.0 and 1.0, the fill color will be the defined CMYK hue. [ 0, 0, 0, 0 ] is |
|
961
|
|
|
|
|
|
|
white, [ 1, 0, 1, 0 ] is green, and [ 1, 1, 1, 1 ] is black. |
|
962
|
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
=back |
|
964
|
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
I<This call may be replaced by a hash element 'color'=E<gt> in many calls |
|
966
|
|
|
|
|
|
|
(see Common parameters).> |
|
967
|
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
=cut |
|
969
|
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
sub Color { |
|
971
|
0
|
|
|
0
|
1
|
0
|
my ($self, @color) = @_; |
|
972
|
|
|
|
|
|
|
|
|
973
|
0
|
0
|
0
|
|
|
0
|
if (scalar @color == 1 && |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
974
|
|
|
|
|
|
|
$color[0] >= 0 && $color[0] <= 1.0) { |
|
975
|
0
|
|
|
|
|
0
|
$self->{'C'} = PDFArray(map { PDFNum($_) } $color[0]); |
|
|
0
|
|
|
|
|
0
|
|
|
976
|
|
|
|
|
|
|
} elsif (scalar @color == 3 && |
|
977
|
|
|
|
|
|
|
$color[0] >= 0 && $color[0] <= 1.0 && |
|
978
|
|
|
|
|
|
|
$color[1] >= 0 && $color[1] <= 1.0 && |
|
979
|
|
|
|
|
|
|
$color[2] >= 0 && $color[2] <= 1.0) { |
|
980
|
0
|
|
|
|
|
0
|
$self->{'C'} = PDFArray(map { PDFNum($_) } $color[0], $color[1], $color[2]); |
|
|
0
|
|
|
|
|
0
|
|
|
981
|
|
|
|
|
|
|
} elsif (scalar @color == 4 && |
|
982
|
|
|
|
|
|
|
$color[0] >= 0 && $color[0] <= 1.0 && |
|
983
|
|
|
|
|
|
|
$color[1] >= 0 && $color[1] <= 1.0 && |
|
984
|
|
|
|
|
|
|
$color[2] >= 0 && $color[2] <= 1.0 && |
|
985
|
|
|
|
|
|
|
$color[3] >= 0 && $color[3] <= 1.0) { |
|
986
|
0
|
|
|
|
|
0
|
$self->{'C'} = PDFArray(map { PDFNum($_) } $color[0], $color[1], $color[2], $color[3]); |
|
|
0
|
|
|
|
|
0
|
|
|
987
|
|
|
|
|
|
|
} else { |
|
988
|
|
|
|
|
|
|
# invalid color entry. just set to medium gray without message |
|
989
|
0
|
|
|
|
|
0
|
$self->{'C'} = PDFArray(map { PDFNum($_) } 0.5 ); |
|
|
0
|
|
|
|
|
0
|
|
|
990
|
|
|
|
|
|
|
} |
|
991
|
|
|
|
|
|
|
|
|
992
|
0
|
|
|
|
|
0
|
return $self; |
|
993
|
|
|
|
|
|
|
} |
|
994
|
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
=head3 content |
|
996
|
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
$annotation->content(@lines) |
|
998
|
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
=over |
|
1000
|
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
Sets the text-content of the C<text()> annotation. |
|
1002
|
|
|
|
|
|
|
This is a text string or array of strings. |
|
1003
|
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
=back |
|
1005
|
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
=cut |
|
1007
|
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
sub content { |
|
1009
|
2
|
|
|
2
|
1
|
6
|
my ($self, @lines) = @_; |
|
1010
|
2
|
|
|
|
|
7
|
my $text = join("\n", @lines); |
|
1011
|
|
|
|
|
|
|
|
|
1012
|
2
|
|
|
|
|
6
|
$self->{'Contents'} = PDFString($text, 's'); |
|
1013
|
2
|
|
|
|
|
6
|
return $self; |
|
1014
|
|
|
|
|
|
|
} |
|
1015
|
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
# unused internal routine? TBD |
|
1017
|
|
|
|
|
|
|
sub name { |
|
1018
|
0
|
|
|
0
|
0
|
0
|
my ($self, $name) = @_; |
|
1019
|
0
|
|
|
|
|
0
|
$self->{'Name'} = PDFName($name); |
|
1020
|
0
|
|
|
|
|
0
|
return $self; |
|
1021
|
|
|
|
|
|
|
} |
|
1022
|
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
=head3 open |
|
1024
|
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
$annotation->open($bool) |
|
1026
|
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
=over |
|
1028
|
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
Display the C<text()> annotation either open or closed, if applicable. |
|
1030
|
|
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
|
Both are editable; the "open" form brings up the page with the entry area |
|
1032
|
|
|
|
|
|
|
already open for editing, while "closed" has to be clicked on to edit it. |
|
1033
|
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
Defining option: |
|
1035
|
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
=back |
|
1037
|
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
=over |
|
1039
|
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
=item open => boolean |
|
1041
|
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
If true (1), the annotation will be marked as initially "open". |
|
1043
|
|
|
|
|
|
|
If false (0), or the option is not given, the annotation is initially "closed". |
|
1044
|
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
=back |
|
1046
|
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
=cut |
|
1048
|
|
|
|
|
|
|
|
|
1049
|
|
|
|
|
|
|
sub open { ## no critic |
|
1050
|
0
|
|
|
0
|
1
|
0
|
my ($self, $bool) = @_; |
|
1051
|
0
|
0
|
|
|
|
0
|
$self->{'Open'} = PDFBool($bool? 1: 0); |
|
1052
|
0
|
|
|
|
|
0
|
return $self; |
|
1053
|
|
|
|
|
|
|
} |
|
1054
|
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
=head3 text string |
|
1056
|
|
|
|
|
|
|
|
|
1057
|
|
|
|
|
|
|
'text' => string |
|
1058
|
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
=over |
|
1060
|
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
Specify an optional B<text label> for annotation. This text or comment only |
|
1062
|
|
|
|
|
|
|
shows up I<as a title> in the pop-up containing the file or text. |
|
1063
|
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
=back |
|
1065
|
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
=cut |
|
1067
|
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
sub icon_appearance { |
|
1069
|
0
|
|
|
0
|
0
|
0
|
my ($self, $icon, %opts) = @_; |
|
1070
|
|
|
|
|
|
|
# $icon is a string with name of icon (confirmed not empty) or a reference. |
|
1071
|
|
|
|
|
|
|
# if a string (text), has already defined /Name. "None" and ref handle here. |
|
1072
|
|
|
|
|
|
|
# options of interest: rect (to define size of icon) |
|
1073
|
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
# copy dashed names over to preferred non-dashed names |
|
1075
|
0
|
0
|
0
|
|
|
0
|
if (defined $opts{'-rect'} && !defined $opts{'rect'}) { $opts{'rect'} = delete($opts{'-rect'}); } |
|
|
0
|
|
|
|
|
0
|
|
|
1076
|
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
# text also permits icon and custom icon, including None |
|
1078
|
|
|
|
|
|
|
#return unless $self->{'Subtype'}->val() eq 'FileAttachment'; |
|
1079
|
|
|
|
|
|
|
|
|
1080
|
0
|
|
|
|
|
0
|
my @r; # perlcritic doesn't want 2 lines combined |
|
1081
|
0
|
0
|
|
|
|
0
|
@r = @{$opts{'rect'}} if defined $opts{'rect'}; |
|
|
0
|
|
|
|
|
0
|
|
|
1082
|
|
|
|
|
|
|
# number of parameters should be 4, checked above (rect method) |
|
1083
|
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
# Handle custom icon type 'None' and icon reference. |
|
1085
|
0
|
0
|
|
|
|
0
|
if ($icon eq 'None') { |
|
|
|
0
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
# It is not clear what viewers will do, so provide an |
|
1087
|
|
|
|
|
|
|
# appearance dict with no graphics content. |
|
1088
|
|
|
|
|
|
|
|
|
1089
|
|
|
|
|
|
|
# 9 0 obj << |
|
1090
|
|
|
|
|
|
|
# ... |
|
1091
|
|
|
|
|
|
|
# /AP << /D 11 0 R /N 11 0 R /R 11 0 R >> |
|
1092
|
|
|
|
|
|
|
# ... |
|
1093
|
|
|
|
|
|
|
# >> |
|
1094
|
|
|
|
|
|
|
# 11 0 obj << |
|
1095
|
|
|
|
|
|
|
# /BBox [ 0 0 100 100 ] |
|
1096
|
|
|
|
|
|
|
# /FormType 1 |
|
1097
|
|
|
|
|
|
|
# /Length 6 |
|
1098
|
|
|
|
|
|
|
# /Matrix [ 1 0 0 1 0 0 ] |
|
1099
|
|
|
|
|
|
|
# /Resources << |
|
1100
|
|
|
|
|
|
|
# /ProcSet [ /PDF ] |
|
1101
|
|
|
|
|
|
|
# >> |
|
1102
|
|
|
|
|
|
|
# >> stream |
|
1103
|
|
|
|
|
|
|
# 0 0 m |
|
1104
|
|
|
|
|
|
|
# endstream endobj |
|
1105
|
|
|
|
|
|
|
|
|
1106
|
0
|
|
|
|
|
0
|
$self->{'AP'} = PDFDict(); |
|
1107
|
0
|
|
|
|
|
0
|
my $d = PDFDict(); |
|
1108
|
0
|
|
|
|
|
0
|
$self->{' apipdf'}->new_obj($d); |
|
1109
|
0
|
|
|
|
|
0
|
$d->{'FormType'} = PDFNum(1); |
|
1110
|
0
|
|
|
|
|
0
|
$d->{'Matrix'} = PDFArray(map { PDFNum($_) } 1, 0, 0, 1, 0, 0); |
|
|
0
|
|
|
|
|
0
|
|
|
1111
|
0
|
|
|
|
|
0
|
$d->{'Resources'} = PDFDict(); |
|
1112
|
0
|
|
|
|
|
0
|
$d->{'Resources'}->{'ProcSet'} = PDFArray( map { PDFName($_) } qw(PDF)); |
|
|
0
|
|
|
|
|
0
|
|
|
1113
|
0
|
|
|
|
|
0
|
$d->{'BBox'} = PDFArray( map { PDFNum($_) } 0, 0, $r[2]-$r[0], $r[3]-$r[1] ); |
|
|
0
|
|
|
|
|
0
|
|
|
1114
|
0
|
|
|
|
|
0
|
$d->{' stream'} = "0 0 m"; |
|
1115
|
0
|
|
|
|
|
0
|
$self->{'AP'}->{'N'} = $d; # normal appearance |
|
1116
|
|
|
|
|
|
|
# Should default to N, but be sure. |
|
1117
|
0
|
|
|
|
|
0
|
$self->{'AP'}->{'R'} = $d; # Rollover |
|
1118
|
0
|
|
|
|
|
0
|
$self->{'AP'}->{'D'} = $d; # Down |
|
1119
|
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
# Handle custom icon. |
|
1121
|
|
|
|
|
|
|
} elsif (ref $icon) { |
|
1122
|
|
|
|
|
|
|
# Provide an appearance dict with the image. |
|
1123
|
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
# 9 0 obj << |
|
1125
|
|
|
|
|
|
|
# ... |
|
1126
|
|
|
|
|
|
|
# /AP << /D 11 0 R /N 11 0 R /R 11 0 R >> |
|
1127
|
|
|
|
|
|
|
# ... |
|
1128
|
|
|
|
|
|
|
# >> |
|
1129
|
|
|
|
|
|
|
# 11 0 obj << |
|
1130
|
|
|
|
|
|
|
# /BBox [ 0 0 1 1 ] |
|
1131
|
|
|
|
|
|
|
# /FormType 1 |
|
1132
|
|
|
|
|
|
|
# /Length 13 |
|
1133
|
|
|
|
|
|
|
# /Matrix [ 1 0 0 1 0 0 ] |
|
1134
|
|
|
|
|
|
|
# /Resources << |
|
1135
|
|
|
|
|
|
|
# /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] |
|
1136
|
|
|
|
|
|
|
# /XObject << /PxCBA 7 0 R >> |
|
1137
|
|
|
|
|
|
|
# >> |
|
1138
|
|
|
|
|
|
|
# >> stream |
|
1139
|
|
|
|
|
|
|
# q /PxCBA Do Q |
|
1140
|
|
|
|
|
|
|
# endstream endobj |
|
1141
|
|
|
|
|
|
|
|
|
1142
|
0
|
|
|
|
|
0
|
$self->{'AP'} = PDFDict(); |
|
1143
|
0
|
|
|
|
|
0
|
my $d = PDFDict(); |
|
1144
|
0
|
|
|
|
|
0
|
$self->{' apipdf'}->new_obj($d); |
|
1145
|
0
|
|
|
|
|
0
|
$d->{'FormType'} = PDFNum(1); |
|
1146
|
0
|
|
|
|
|
0
|
$d->{'Matrix'} = PDFArray(map { PDFNum($_) } 1, 0, 0, 1, 0, 0); |
|
|
0
|
|
|
|
|
0
|
|
|
1147
|
0
|
|
|
|
|
0
|
$d->{'Resources'} = PDFDict(); |
|
1148
|
0
|
|
|
|
|
0
|
$d->{'Resources'}->{'ProcSet'} = PDFArray(map { PDFName($_) } qw(PDF Text ImageB ImageC ImageI)); |
|
|
0
|
|
|
|
|
0
|
|
|
1149
|
0
|
|
|
|
|
0
|
$d->{'Resources'}->{'XObject'} = PDFDict(); |
|
1150
|
0
|
|
|
|
|
0
|
my $im = $icon->{'Name'}->val(); |
|
1151
|
0
|
|
|
|
|
0
|
$d->{'Resources'}->{'XObject'}->{$im} = $icon; |
|
1152
|
|
|
|
|
|
|
# Note that the image is scaled to one unit in user space. |
|
1153
|
0
|
|
|
|
|
0
|
$d->{'BBox'} = PDFArray(map { PDFNum($_) } 0, 0, 1, 1); |
|
|
0
|
|
|
|
|
0
|
|
|
1154
|
0
|
|
|
|
|
0
|
$d->{' stream'} = "q /$im Do Q"; |
|
1155
|
0
|
|
|
|
|
0
|
$self->{'AP'}->{'N'} = $d; # normal appearance |
|
1156
|
|
|
|
|
|
|
|
|
1157
|
0
|
|
|
|
|
0
|
if (0) { |
|
1158
|
|
|
|
|
|
|
# Testing... Provide an alternative for R and D. |
|
1159
|
|
|
|
|
|
|
# Works only with Adobe Reader. |
|
1160
|
|
|
|
|
|
|
$d = PDFDict(); |
|
1161
|
|
|
|
|
|
|
$self->{' apipdf'}->new_obj($d); |
|
1162
|
|
|
|
|
|
|
$d->{'Type'} = PDFName('XObject'); |
|
1163
|
|
|
|
|
|
|
$d->{'Subtype'} = PDFName('Form'); |
|
1164
|
|
|
|
|
|
|
$d->{'FormType'} = PDFNum(1); |
|
1165
|
|
|
|
|
|
|
$d->{'Matrix'} = PDFArray(map { PDFNum($_) } 1, 0, 0, 1, 0, 0); |
|
1166
|
|
|
|
|
|
|
$d->{'Resources'} = PDFDict(); |
|
1167
|
|
|
|
|
|
|
$d->{'Resources'}->{'ProcSet'} = PDFArray(map { PDFName($_) } qw(PDF)); |
|
1168
|
|
|
|
|
|
|
$d->{'BBox'} = PDFArray(map { PDFNum($_) } 0, 0, $r[2]-$r[0], $r[3]-$r[1]); |
|
1169
|
|
|
|
|
|
|
$d->{' stream'} = |
|
1170
|
|
|
|
|
|
|
join( " ", |
|
1171
|
|
|
|
|
|
|
# black outline |
|
1172
|
|
|
|
|
|
|
0, 0, 'm', |
|
1173
|
|
|
|
|
|
|
0, $r[2]-$r[0], 'l', |
|
1174
|
|
|
|
|
|
|
$r[2]-$r[0], $r[3]-$r[1], 'l', |
|
1175
|
|
|
|
|
|
|
$r[2]-$r[0], 0, 'l', |
|
1176
|
|
|
|
|
|
|
's', |
|
1177
|
|
|
|
|
|
|
); |
|
1178
|
|
|
|
|
|
|
} |
|
1179
|
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
# Should default to N, but be sure. |
|
1181
|
0
|
|
|
|
|
0
|
$self->{'AP'}->{'R'} = $d; # Rollover |
|
1182
|
0
|
|
|
|
|
0
|
$self->{'AP'}->{'D'} = $d; # Down |
|
1183
|
|
|
|
|
|
|
} |
|
1184
|
|
|
|
|
|
|
|
|
1185
|
0
|
|
|
|
|
0
|
return $self; |
|
1186
|
|
|
|
|
|
|
} |
|
1187
|
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
# strip off any leading - from all options (hash keys) |
|
1189
|
|
|
|
|
|
|
sub dashed2nondashed { |
|
1190
|
4
|
|
|
4
|
0
|
12
|
my @opts = @_; |
|
1191
|
4
|
|
|
|
|
17
|
for (my $i=0; $i<@opts; $i+=2) { |
|
1192
|
2
|
50
|
|
|
|
27
|
if ($opts[$i] =~ /^-(.*)$/) { |
|
1193
|
0
|
|
|
|
|
0
|
$opts[$i] = $1; |
|
1194
|
|
|
|
|
|
|
} |
|
1195
|
|
|
|
|
|
|
} |
|
1196
|
4
|
|
|
|
|
15
|
return @opts; |
|
1197
|
|
|
|
|
|
|
} |
|
1198
|
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
1; |