line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package PDF::Builder::Annotation; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
1628
|
use base 'PDF::Builder::Basic::PDF::Dict'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
313
|
|
4
|
|
|
|
|
|
|
|
5
|
2
|
|
|
2
|
|
14
|
use strict; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
48
|
|
6
|
2
|
|
|
2
|
|
10
|
use warnings; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
181
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '3.023'; # VERSION |
9
|
|
|
|
|
|
|
our $LAST_UPDATE = '3.022'; # manually update whenever code is changed |
10
|
|
|
|
|
|
|
|
11
|
2
|
|
|
2
|
|
14
|
use PDF::Builder::Basic::PDF::Utils; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
259
|
|
12
|
2
|
|
|
2
|
|
15
|
use List::Util qw(min max); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
7579
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
PDF::Builder::Annotation - Add annotations to a PDF |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 METHODS |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Note that the handling of annotations can vary from Reader to Reader. The |
21
|
|
|
|
|
|
|
available icon set may be larger or smaller than given here, and some Readers |
22
|
|
|
|
|
|
|
activate an annotation on a single mouse click, while others require a double |
23
|
|
|
|
|
|
|
click. Not all features provided here may be available on all PDF Readers. |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=over |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=item $annotation = PDF::Builder::Annotation->new() |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
Returns an annotation object (called from $page->annotation()). |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
It is normally I necessary to explicitly call this method (see examples). |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=cut |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# %options removed, as there are currently none |
36
|
|
|
|
|
|
|
sub new { |
37
|
2
|
|
|
2
|
1
|
12
|
my ($class) = @_; |
38
|
|
|
|
|
|
|
|
39
|
2
|
|
|
|
|
26
|
my $self = $class->SUPER::new(); |
40
|
2
|
|
|
|
|
15
|
$self->{'Type'} = PDFName('Annot'); |
41
|
2
|
|
|
|
|
10
|
$self->{'Border'} = PDFArray(PDFNum(0), PDFNum(0), PDFNum(1)); |
42
|
|
|
|
|
|
|
|
43
|
2
|
|
|
|
|
11
|
return $self; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
#sub outobjdeep { |
47
|
|
|
|
|
|
|
# my ($self, @options) = @_; |
48
|
|
|
|
|
|
|
# |
49
|
|
|
|
|
|
|
# foreach my $k (qw[ api apipdf apipage ]) { |
50
|
|
|
|
|
|
|
# $self->{" $k"} = undef; |
51
|
|
|
|
|
|
|
# delete($self->{" $k"}); |
52
|
|
|
|
|
|
|
# } |
53
|
|
|
|
|
|
|
# return $self->SUPER::outobjdeep(@options); |
54
|
|
|
|
|
|
|
#} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# ============== start of annotation types ======================= |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
# note that %options is given as the only format in most cases, as -rect |
59
|
|
|
|
|
|
|
# is a mandatory "option" |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=back |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=head2 Annotation types |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=over |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=item $annotation->link($page, %options) |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=item $annotation->link($page) |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Defines the annotation as a launch-page with page C<$page> (within I |
72
|
|
|
|
|
|
|
document) and options %options (-rect, -border, -color, I: see |
73
|
|
|
|
|
|
|
descriptions below). |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
B that C<$page> is I a simple page number, but is a page structure |
76
|
|
|
|
|
|
|
such as C<$pdf-Eopenpage(page_number)>. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=cut |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub link { ## no critic |
81
|
0
|
|
|
0
|
1
|
0
|
my ($self, $page, %options) = @_; |
82
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName('Link'); |
84
|
0
|
0
|
|
|
|
0
|
if (ref($page)) { |
85
|
0
|
|
|
|
|
0
|
$self->{'A'} = PDFDict(); |
86
|
0
|
|
|
|
|
0
|
$self->{'A'}->{'S'} = PDFName('GoTo'); |
87
|
|
|
|
|
|
|
} |
88
|
0
|
|
|
|
|
0
|
$self->dest($page, %options); |
89
|
0
|
0
|
|
|
|
0
|
$self->rect(@{$options{'-rect'}}) if defined $options{'-rect'}; |
|
0
|
|
|
|
|
0
|
|
90
|
0
|
0
|
|
|
|
0
|
$self->border(@{$options{'-border'}}) if defined $options{'-border'}; |
|
0
|
|
|
|
|
0
|
|
91
|
0
|
0
|
|
|
|
0
|
$self->Color(@{$options{'-color'}}) if defined $options{'-color'}; |
|
0
|
|
|
|
|
0
|
|
92
|
|
|
|
|
|
|
|
93
|
0
|
|
|
|
|
0
|
return $self; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=item $annotation->pdf_file($pdffile, $page_number, %options) |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Defines the annotation as a PDF-file with filepath C<$pdffile>, on page |
99
|
|
|
|
|
|
|
C<$page_number>, and options %options (-rect, -border, -color, I: see |
100
|
|
|
|
|
|
|
descriptions below). This differs from the C call in that the target |
101
|
|
|
|
|
|
|
is found in a different PDF file, not the current document. |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
C<$page_number> is the physical page number, starting at 1: 1, 2,... |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=cut |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# Note: renamed from pdfile() to pdf_file(). |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub pdf_file { |
110
|
0
|
|
|
0
|
1
|
0
|
my ($self, $url, $page_number, %options) = @_; |
111
|
|
|
|
|
|
|
# note that although "url" is used, it may be a local file |
112
|
|
|
|
|
|
|
|
113
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName('Link'); |
114
|
0
|
|
|
|
|
0
|
$self->{'A'} = PDFDict(); |
115
|
0
|
|
|
|
|
0
|
$self->{'A'}->{'S'} = PDFName('GoToR'); |
116
|
0
|
|
|
|
|
0
|
$self->{'A'}->{'F'} = PDFString($url, 'u'); |
117
|
|
|
|
|
|
|
|
118
|
0
|
|
|
|
|
0
|
$page_number--; # wants it numbered starting at 0 |
119
|
0
|
|
|
|
|
0
|
$self->dest(PDFNum($page_number), %options); |
120
|
0
|
0
|
|
|
|
0
|
$self->rect(@{$options{'-rect'}}) if defined $options{'-rect'}; |
|
0
|
|
|
|
|
0
|
|
121
|
0
|
0
|
|
|
|
0
|
$self->border(@{$options{'-border'}}) if defined $options{'-border'}; |
|
0
|
|
|
|
|
0
|
|
122
|
0
|
0
|
|
|
|
0
|
$self->Color(@{$options{'-color'}}) if defined $options{'-color'}; |
|
0
|
|
|
|
|
0
|
|
123
|
|
|
|
|
|
|
|
124
|
0
|
|
|
|
|
0
|
return $self; |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=item $annotation->file($file, %options) |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Defines the annotation as a launch-file with filepath C<$file> (a local file) |
130
|
|
|
|
|
|
|
and options %options (-rect, -border, -color: see descriptions below). |
131
|
|
|
|
|
|
|
I the file is displayed depends on the operating system, type of file, |
132
|
|
|
|
|
|
|
and local configuration or mapping. |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=cut |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub file { |
137
|
0
|
|
|
0
|
1
|
0
|
my ($self, $file, %options) = @_; |
138
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName('Link'); |
140
|
0
|
|
|
|
|
0
|
$self->{'A'} = PDFDict(); |
141
|
0
|
|
|
|
|
0
|
$self->{'A'}->{'S'} = PDFName('Launch'); |
142
|
0
|
|
|
|
|
0
|
$self->{'A'}->{'F'} = PDFString($file, 'f'); |
143
|
0
|
0
|
|
|
|
0
|
$self->rect(@{$options{'-rect'}}) if defined $options{'-rect'}; |
|
0
|
|
|
|
|
0
|
|
144
|
0
|
0
|
|
|
|
0
|
$self->border(@{$options{'-border'}}) if defined $options{'-border'}; |
|
0
|
|
|
|
|
0
|
|
145
|
0
|
0
|
|
|
|
0
|
$self->Color(@{$options{'-color'}}) if defined $options{'-color'}; |
|
0
|
|
|
|
|
0
|
|
146
|
|
|
|
|
|
|
|
147
|
0
|
|
|
|
|
0
|
return $self; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=item $annotation->url($url, %options) |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Defines the annotation as a launch-url with url C<$url> and |
153
|
|
|
|
|
|
|
options %options (-rect, -border, -color: see descriptions below). |
154
|
|
|
|
|
|
|
This page is usually brought up in a browser, and may be remote. |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=cut |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub url { |
159
|
0
|
|
|
0
|
1
|
0
|
my ($self, $url, %options) = @_; |
160
|
|
|
|
|
|
|
|
161
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName('Link'); |
162
|
0
|
|
|
|
|
0
|
$self->{'A'} = PDFDict(); |
163
|
0
|
|
|
|
|
0
|
$self->{'A'}->{'S'} = PDFName('URI'); |
164
|
0
|
|
|
|
|
0
|
$self->{'A'}->{'URI'} = PDFString($url, 'u'); |
165
|
0
|
0
|
|
|
|
0
|
$self->rect(@{$options{'-rect'}}) if defined $options{'-rect'}; |
|
0
|
|
|
|
|
0
|
|
166
|
0
|
0
|
|
|
|
0
|
$self->border(@{$options{'-border'}}) if defined $options{'-border'}; |
|
0
|
|
|
|
|
0
|
|
167
|
0
|
0
|
|
|
|
0
|
$self->Color(@{$options{'-color'}}) if defined $options{'-color'}; |
|
0
|
|
|
|
|
0
|
|
168
|
|
|
|
|
|
|
|
169
|
0
|
|
|
|
|
0
|
return $self; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=item $annotation->text($text, %options) |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Defines the annotation as a text note with content string C<$text> and |
175
|
|
|
|
|
|
|
options %options (-rect, -color, -text, -open: see descriptions below). |
176
|
|
|
|
|
|
|
The C<$text> may include newlines \n for multiple lines. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
C<-text> is the popup's label string, not to be confused with the main C<$text>. |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
The icon appears in the upper left corner of the C<-rect> selection rectangle, |
181
|
|
|
|
|
|
|
and its active clickable area is fixed by the icon (it is I equal to the |
182
|
|
|
|
|
|
|
rectangle). The icon size is fixed, and its fill color set by C<-color>. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Additional options: |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=over |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=item -icon => name_string |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=item -icon => reference |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Specify the B to be used. The default is Reader-specific (usually |
193
|
|
|
|
|
|
|
C), and others may be |
194
|
|
|
|
|
|
|
defined by the Reader. C, C, C, C, |
195
|
|
|
|
|
|
|
C, and C are also supposed to |
196
|
|
|
|
|
|
|
be available on all PDF Readers. Note that the name I must exactly match. |
197
|
|
|
|
|
|
|
The icon is of fixed size. |
198
|
|
|
|
|
|
|
Any I dictionary entry will override the -icon setting. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
A I to an icon may be passed instead of a name. |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=item -opacity => I |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Define the opacity (non-transparency, opaqueness) of the icon. This value |
205
|
|
|
|
|
|
|
ranges from 0.0 (transparent) to 1.0 (fully opaque), and applies to both |
206
|
|
|
|
|
|
|
the outline and the fill color. The default is 1.0. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=back |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=cut |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# the icon size appears to be fixed. the last font size used does not affect it |
213
|
|
|
|
|
|
|
# and enabling icon_appearance() for it doesn't seem to do anything |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub text { |
216
|
2
|
|
|
2
|
1
|
25
|
my ($self, $text, %options) = @_; |
217
|
|
|
|
|
|
|
|
218
|
2
|
|
|
|
|
7
|
$self->{'Subtype'} = PDFName('Text'); |
219
|
2
|
|
|
|
|
11
|
$self->content($text); |
220
|
|
|
|
|
|
|
|
221
|
2
|
50
|
|
|
|
8
|
$self->rect(@{$options{'-rect'}}) if defined $options{'-rect'}; |
|
2
|
|
|
|
|
13
|
|
222
|
2
|
50
|
|
|
|
7
|
$self->open($options{'-open'}) if defined $options{'-open'}; |
223
|
2
|
50
|
|
|
|
9
|
$self->Color(@{$options{'-color'}}) if defined $options{'-color'}; |
|
0
|
|
|
|
|
0
|
|
224
|
|
|
|
|
|
|
# popup label (title) |
225
|
|
|
|
|
|
|
# have seen /T as (xFEFF UTF-16 chars) |
226
|
2
|
50
|
|
|
|
8
|
$self->{'T'} = PDFString($options{'-text'}, 'p') if exists $options{'-text'}; |
227
|
|
|
|
|
|
|
# icon opacity? |
228
|
2
|
50
|
|
|
|
6
|
if (defined $options{'-opacity'}) { |
229
|
0
|
|
|
|
|
0
|
$self->{'CA'} = PDFNum($options{'-opacity'}); |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# Icon Name will be ignored if there is an AP. |
233
|
2
|
|
|
|
|
5
|
my $icon; # perlcritic doesn't want 2 lines combined |
234
|
2
|
50
|
|
|
|
7
|
$icon = $options{'-icon'} if exists $options{'-icon'}; |
235
|
2
|
50
|
33
|
|
|
8
|
$self->{'Name'} = PDFName($icon) if $icon && !ref($icon); # icon name |
236
|
|
|
|
|
|
|
# Set the icon appearance |
237
|
2
|
50
|
|
|
|
4
|
$self->icon_appearance($icon, %options) if $icon; |
238
|
|
|
|
|
|
|
|
239
|
2
|
|
|
|
|
8
|
return $self; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=item $annotation->markup($text, $PointList, $highlight, %options) |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Defines the annotation as a text note with content string C<$text> and |
245
|
|
|
|
|
|
|
options %options (-rect, -color, -text, -open: see descriptions below). |
246
|
|
|
|
|
|
|
The C<$text> may include newlines \n for multiple lines. |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
C<-text> is the popup's label string, not to be confused with the main C<$text>. |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
There is no icon. Instead, the annotated text marked by C<$PointList> is |
251
|
|
|
|
|
|
|
highlighted in one of four ways specified by C<$highlight>. |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=over |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=item $PointList => [ 8n numbers ] |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
One or more sets of numeric coordinates are given, defining the quadrilateral |
258
|
|
|
|
|
|
|
(usually a rectangle) around the text to be highlighted and selectable |
259
|
|
|
|
|
|
|
(clickable, to bring up the annotation text). These |
260
|
|
|
|
|
|
|
are four sets of C coordinates, given (for Left-to-Right text) as the |
261
|
|
|
|
|
|
|
upper bound Upper Left to Upper Right and then the lower bound Lower Left to |
262
|
|
|
|
|
|
|
Lower Right. B
|
263
|
|
|
|
|
|
|
documented in the PDF specification!> It is important that the coordinates be |
264
|
|
|
|
|
|
|
given in this order. |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
Multiple sets of quadrilateral corners may be given, such as for highlighted |
267
|
|
|
|
|
|
|
text that wraps around to new line(s). The minimum is one set (8 numbers). |
268
|
|
|
|
|
|
|
Any I dictionary entry will override the C<$PointList> setting. Finally, |
269
|
|
|
|
|
|
|
the "Rect" selection rectangle is created I the convex bounding |
270
|
|
|
|
|
|
|
box defined by C<$PointList>. |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=item $highlight => 'string' |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
The following highlighting effects are permitted. The C must be |
275
|
|
|
|
|
|
|
spelled and capitalized I as given: |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=over |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=item Highlight |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
The effect of a translucent "highlighter" marker. |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=item Squiggly |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
The effect is an underline written in a "squiggly" manner. |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=item StrikeOut |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
The text is struck-through with a straight line. |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=item Underline |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
The text is marked by a straight underline. |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=back |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=item -color => I |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
If C<-color> is not given (an array of numbers in the range 0.0-1.0), a |
300
|
|
|
|
|
|
|
medium gray should be used by default. |
301
|
|
|
|
|
|
|
Named colors are not supported at this time. |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=item -opacity => I |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
Define the opacity (non-transparency, opaqueness) of the icon. This value |
306
|
|
|
|
|
|
|
ranges from 0.0 (transparent) to 1.0 (fully opaque), and applies to both |
307
|
|
|
|
|
|
|
the outline and the fill color. The default is 1.0. |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=back |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=cut |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
sub markup { |
314
|
0
|
|
|
0
|
1
|
0
|
my ($self, $text, $PointList, $highlight, %options) = @_; |
315
|
|
|
|
|
|
|
|
316
|
0
|
|
|
|
|
0
|
my @pointList = @{ $PointList }; |
|
0
|
|
|
|
|
0
|
|
317
|
0
|
0
|
0
|
|
|
0
|
if ((scalar @pointList) == 0 || (scalar @pointList)%8) { |
318
|
0
|
|
|
|
|
0
|
die "markup point list does not have 8*N entries!\n"; |
319
|
|
|
|
|
|
|
} |
320
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName($highlight); |
321
|
0
|
|
|
|
|
0
|
delete $self->{'Border'}; |
322
|
0
|
|
|
|
|
0
|
$self->{'QuadPoints'} = PDFArray(map {PDFNum($_)} @pointList); |
|
0
|
|
|
|
|
0
|
|
323
|
0
|
|
|
|
|
0
|
$self->content($text); |
324
|
|
|
|
|
|
|
|
325
|
0
|
|
|
|
|
0
|
my $minX = min($pointList[0], $pointList[2], $pointList[4], $pointList[6]); |
326
|
0
|
|
|
|
|
0
|
my $maxX = max($pointList[0], $pointList[2], $pointList[4], $pointList[6]); |
327
|
0
|
|
|
|
|
0
|
my $minY = min($pointList[1], $pointList[3], $pointList[5], $pointList[7]); |
328
|
0
|
|
|
|
|
0
|
my $maxY = max($pointList[1], $pointList[3], $pointList[5], $pointList[7]); |
329
|
0
|
|
|
|
|
0
|
$self->rect($minX-.5,$minY-.5, $maxX+.5,$maxY+.5); |
330
|
|
|
|
|
|
|
|
331
|
0
|
0
|
|
|
|
0
|
$self->open($options{'-open'}) if defined $options{'-open'}; |
332
|
0
|
0
|
|
|
|
0
|
if (defined $options{'-color'}) { |
333
|
0
|
|
|
|
|
0
|
$self->Color(@{$options{'-color'}}); |
|
0
|
|
|
|
|
0
|
|
334
|
|
|
|
|
|
|
} else { |
335
|
0
|
|
|
|
|
0
|
$self->Color([]); |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
# popup label (title) |
338
|
|
|
|
|
|
|
# have seen /T as (xFEFF UTF-16 chars) |
339
|
0
|
0
|
|
|
|
0
|
$self->{'T'} = PDFString($options{'-text'}, 'p') if exists $options{'-text'}; |
340
|
|
|
|
|
|
|
# opacity? |
341
|
0
|
0
|
|
|
|
0
|
if (defined $options{'-opacity'}) { |
342
|
0
|
|
|
|
|
0
|
$self->{'CA'} = PDFNum($options{'-opacity'}); |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
0
|
|
|
|
|
0
|
return $self; |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=item $annotation->movie($file, $contentType, %options) |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
Defines the annotation as a movie from C<$file> with |
351
|
|
|
|
|
|
|
content (MIME) type C<$contentType> and |
352
|
|
|
|
|
|
|
options %options (-rect, -border, -color: see descriptions below). |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
The C<-rect> rectangle also serves as the area where the movie is played, so it |
355
|
|
|
|
|
|
|
should be of usable size and aspect ratio. It does not use a separate popup |
356
|
|
|
|
|
|
|
player. It is known to play .avi and .wav files -- others have not been tested. |
357
|
|
|
|
|
|
|
Using Adobe Reader, it will not play .mpg files (unsupported type). More work |
358
|
|
|
|
|
|
|
is probably needed on this annotation method. |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=cut |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
sub movie { |
363
|
0
|
|
|
0
|
1
|
0
|
my ($self, $file, $contentType, %options) = @_; |
364
|
|
|
|
|
|
|
|
365
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName('Movie'); # subtype = movie (req) |
366
|
0
|
|
|
|
|
0
|
$self->{'A'} = PDFBool(1); # play using default activation parms |
367
|
0
|
|
|
|
|
0
|
$self->{'Movie'} = PDFDict(); |
368
|
|
|
|
|
|
|
#$self->{'Movie'}->{'S'} = PDFName($contentType); |
369
|
0
|
|
|
|
|
0
|
$self->{'Movie'}->{'F'} = PDFString($file, 'f'); |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
# PDF::API2 2.034 changes don't seem to work |
372
|
|
|
|
|
|
|
# $self->{'Movie'}->{'F'} = PDFString($file, 'f'); line above removed |
373
|
|
|
|
|
|
|
#$self->{'Movie'}->{'F'} = PDFDict(); |
374
|
|
|
|
|
|
|
#$self->{' apipdf'}->new_obj($self->{'Movie'}->{'F'}); |
375
|
|
|
|
|
|
|
#my $f = $self->{'Movie'}->{'F'}; |
376
|
|
|
|
|
|
|
#$f->{'Type'} = PDFName('EmbeddedFile'); |
377
|
|
|
|
|
|
|
#$f->{'Subtype'} = PDFName($contentType); |
378
|
|
|
|
|
|
|
#$f->{' streamfile'} = $file; |
379
|
|
|
|
|
|
|
|
380
|
0
|
0
|
|
|
|
0
|
$self->rect(@{$options{'-rect'}}) if defined $options{'-rect'}; |
|
0
|
|
|
|
|
0
|
|
381
|
0
|
0
|
|
|
|
0
|
$self->border(@{$options{'-border'}}) if defined $options{'-border'}; |
|
0
|
|
|
|
|
0
|
|
382
|
0
|
0
|
|
|
|
0
|
$self->Color(@{$options{'-color'}}) if defined $options{'-color'}; |
|
0
|
|
|
|
|
0
|
|
383
|
|
|
|
|
|
|
# popup label (title) DOESN'T SEEM TO SHOW UP ANYWHERE |
384
|
|
|
|
|
|
|
# self->A->T and self->T also fail to display |
385
|
0
|
0
|
|
|
|
0
|
$self->{'Movie'}->{'T'} = PDFString($options{'-text'}, 'p') if exists $options{'-text'}; |
386
|
|
|
|
|
|
|
|
387
|
0
|
|
|
|
|
0
|
return $self; |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=item $annotation->file_attachment($file, %options) |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
Defines the annotation as a file attachment with file $file and options %options |
393
|
|
|
|
|
|
|
(-rect, -color: see descriptions below). Note that C<-color> applies to |
394
|
|
|
|
|
|
|
the icon fill color, not to a selectable area outline. The icon is resized |
395
|
|
|
|
|
|
|
(including aspect ratio changes) based on the selectable rectangle given by |
396
|
|
|
|
|
|
|
C<-rect>, so watch your rectangle dimensions! |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
The file, along with its name, is I in the PDF document and may be |
399
|
|
|
|
|
|
|
extracted for viewing with the appropriate viewer. |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
This differs from the C method in that C looks for and launches |
402
|
|
|
|
|
|
|
a file I on the Reader's machine, while C embeds the |
403
|
|
|
|
|
|
|
file in the PDF, and makes it available on the Reader's machine for actions |
404
|
|
|
|
|
|
|
of the user's choosing. |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
B some Readers may only permit an "open" action, and may also restrict |
407
|
|
|
|
|
|
|
file types (extensions) that will be handled. This may be configurable with |
408
|
|
|
|
|
|
|
your Reader's security settings. |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
B the displayed file name (pop-up during mouse rollover of the target |
411
|
|
|
|
|
|
|
rectangle) is given with the I trimmed off (file name only). If you want |
412
|
|
|
|
|
|
|
the displayed name to exactly match the path that was passed to the call, |
413
|
|
|
|
|
|
|
including the path, give the C<-notrimpath> option. |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
Options: |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=over |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
=item -icon => name_string |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
=item -icon => reference |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
Specify the B to be used. The default is Reader-specific (usually |
424
|
|
|
|
|
|
|
C), and others may be |
425
|
|
|
|
|
|
|
defined by the Reader. C, C, and C are also supposed to |
426
|
|
|
|
|
|
|
be available on all PDF Readers. Note that the name I must exactly match. |
427
|
|
|
|
|
|
|
C is a custom invisible icon defined by PDF::Builder. |
428
|
|
|
|
|
|
|
The icon is stretched/squashed to fill the defined target rectangle, so take |
429
|
|
|
|
|
|
|
care when defining C<-rect> dimensions. |
430
|
|
|
|
|
|
|
Any I dictionary entry will override the -icon setting. |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
A I to an icon may be passed instead of a name. |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
=item -opacity => I |
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
|
|
|
|
|
|
|
=item -notrimpath => 1 |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
If given, show the entire path and file name on mouse rollover, rather than |
443
|
|
|
|
|
|
|
just the file name. |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
=item -text => string |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
A text label for the popup (on mouseover) that contains the file name. |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
=back |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
Note that while PDF permits different specifications (paths) to DOS/Windows, |
452
|
|
|
|
|
|
|
Mac, and Unix (including Linux) versions of a file, and different format copies |
453
|
|
|
|
|
|
|
to be embedded, at this time PDF::Builder only permits a single file (format of |
454
|
|
|
|
|
|
|
your choice) to be embedded. If there is user demand for multiple file formats |
455
|
|
|
|
|
|
|
to be referenced and/or embedded, we could look into providing this, I
|
456
|
|
|
|
|
|
|
separate OS version paths B be considered obsolescent!>. |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
=cut |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
# TBD it is possible to specify different files for DOS, Mac, Unix |
461
|
|
|
|
|
|
|
# (see PDF 1.7 7.11.4.2). This might solve problem of different line |
462
|
|
|
|
|
|
|
# ends, at the cost of 3 copies of each file. |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
sub file_attachment { |
465
|
0
|
|
|
0
|
1
|
0
|
my ($self, $file, %options) = @_; |
466
|
|
|
|
|
|
|
|
467
|
0
|
|
|
|
|
0
|
my $icon; # defaults to Reader's default (usually PushPin) |
468
|
0
|
0
|
|
|
|
0
|
$icon = $options{'-icon'} if exists $options{'-icon'}; |
469
|
|
|
|
|
|
|
|
470
|
0
|
0
|
|
|
|
0
|
$self->rect(@{$options{'-rect'}}) if defined $options{'-rect'}; |
|
0
|
|
|
|
|
0
|
|
471
|
|
|
|
|
|
|
# descriptive text on mouse rollover |
472
|
0
|
0
|
|
|
|
0
|
$self->{'T'} = PDFString($options{'-text'}, 'p') if exists $options{'-text'}; |
473
|
|
|
|
|
|
|
# icon opacity? |
474
|
0
|
0
|
|
|
|
0
|
if (defined $options{'-opacity'}) { |
475
|
0
|
|
|
|
|
0
|
$self->{'CA'} = PDFNum($options{'-opacity'}); |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
0
|
|
|
|
|
0
|
$self->{'Subtype'} = PDFName('FileAttachment'); |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
# 9 0 obj << |
481
|
|
|
|
|
|
|
# /Type /Annot |
482
|
|
|
|
|
|
|
# /Subtype /FileAttachment |
483
|
|
|
|
|
|
|
# /Name /PushPin |
484
|
|
|
|
|
|
|
# /C [ 1 1 0 ] |
485
|
|
|
|
|
|
|
# /Contents (test.txt) |
486
|
|
|
|
|
|
|
# /FS << |
487
|
|
|
|
|
|
|
# /Type /F |
488
|
|
|
|
|
|
|
# /EF << /F 10 0 R >> |
489
|
|
|
|
|
|
|
# /F (test.txt) |
490
|
|
|
|
|
|
|
# >> |
491
|
|
|
|
|
|
|
# /Rect [ 100 100 200 200 ] |
492
|
|
|
|
|
|
|
# /Border [ 0 0 1 ] |
493
|
|
|
|
|
|
|
# >> endobj |
494
|
|
|
|
|
|
|
# |
495
|
|
|
|
|
|
|
# 10 0 obj << |
496
|
|
|
|
|
|
|
# /Type /EmbeddedFile |
497
|
|
|
|
|
|
|
# /Length ... |
498
|
|
|
|
|
|
|
# >> stream |
499
|
|
|
|
|
|
|
# ... |
500
|
|
|
|
|
|
|
# endstream endobj |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
# text label on pop-up for mouse rollover |
503
|
0
|
|
|
|
|
0
|
my $cName = $file; |
504
|
|
|
|
|
|
|
# trim off any path, leaving just the file name. less confusing that way |
505
|
0
|
0
|
|
|
|
0
|
if (!defined $options{'-notrimpath'}) { |
506
|
0
|
0
|
|
|
|
0
|
if ($cName =~ m#([^/\\]+)$#) { $cName = $1; } |
|
0
|
|
|
|
|
0
|
|
507
|
|
|
|
|
|
|
} |
508
|
0
|
|
|
|
|
0
|
$self->{'Contents'} = PDFString($cName, 's'); |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
# Icon Name will be ignored if there is an AP. |
511
|
0
|
0
|
0
|
|
|
0
|
$self->{'Name'} = PDFName($icon) if $icon && !ref($icon); # icon name |
512
|
|
|
|
|
|
|
#$self->{'F'} = PDFNum(0b0); # flags default to 0 |
513
|
0
|
0
|
|
|
|
0
|
$self->Color(@{ $options{'-color'} }) if defined $options{'-color'}; |
|
0
|
|
|
|
|
0
|
|
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
# The File Specification. |
516
|
0
|
|
|
|
|
0
|
$self->{'FS'} = PDFDict(); |
517
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'F'} = PDFString($file, 'f'); |
518
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'Type'} = PDFName('Filespec'); |
519
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'EF'} = PDFDict($file); |
520
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'EF'}->{'F'} = PDFDict($file); |
521
|
0
|
|
|
|
|
0
|
$self->{' apipdf'}->new_obj($self->{'FS'}->{'EF'}->{'F'}); |
522
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'EF'}->{'F'}->{'Type'} = PDFName('EmbeddedFile'); |
523
|
0
|
|
|
|
|
0
|
$self->{'FS'}->{'EF'}->{'F'}->{' streamfile'} = $file; |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
# Set the icon appearance |
526
|
0
|
0
|
|
|
|
0
|
$self->icon_appearance($icon, %options) if $icon; |
527
|
|
|
|
|
|
|
|
528
|
0
|
|
|
|
|
0
|
return $self; |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
# TBD additional annotation types without icons |
532
|
|
|
|
|
|
|
# free text, line, square, circle, polygon (1.5), polyline (1.5), highlight, |
533
|
|
|
|
|
|
|
# underline, squiggly, strikeout, caret (1.5), ink, popup, sound, widget, |
534
|
|
|
|
|
|
|
# screen (1.5), printermark, trapnet, watermark (1.6), 3D (1.6), redact (1.7) |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
# TBD additional annotation types with icons |
537
|
|
|
|
|
|
|
# stamp |
538
|
|
|
|
|
|
|
# icons: Approved, Experimental, NotApproved, Asis, Expired, |
539
|
|
|
|
|
|
|
# NotForPublicRelease, Confidential, Final, Sold, Departmental, |
540
|
|
|
|
|
|
|
# ForComment, TopSecret, Draft (def.), ForPublicRelease |
541
|
|
|
|
|
|
|
# sound |
542
|
|
|
|
|
|
|
# icons: Speaker (def.), Mic |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
# =============== end of annotation types ======================== |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
=back |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
=head2 Internal routines and common options |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
=over |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
=item $annotation->rect($llx,$lly, $urx,$ury) |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
Sets the rectangle (active click area) of the annotation, given by -rect option. |
555
|
|
|
|
|
|
|
This is any pair of diagonally opposite corners of the rectangle. |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
The default clickable area is the icon itself. |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
Defining option. I.> |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
=over |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
=item -rect => [LLx, LLy, URx, URy] |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
Set annotation rectangle at C<[LLx,LLy]> to C<[URx,URy]> (lower left and |
566
|
|
|
|
|
|
|
upper right coordinates). LL to UR is customary, but any diagonal is allowed. |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
=back |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=cut |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
sub rect { |
573
|
2
|
|
|
2
|
1
|
7
|
my ($self, @r) = @_; |
574
|
|
|
|
|
|
|
|
575
|
2
|
50
|
|
|
|
10
|
die "Insufficient parameters to annotation->rect() " unless scalar @r == 4; |
576
|
2
|
|
|
|
|
9
|
$self->{'Rect'} = PDFArray( map { PDFNum($_) } $r[0],$r[1],$r[2],$r[3]); |
|
8
|
|
|
|
|
18
|
|
577
|
2
|
|
|
|
|
6
|
return $self; |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
=item $annotation->border(@b) |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
Sets the border-style of the annotation, if applicable, as given by the |
583
|
|
|
|
|
|
|
-border option. There are three entries in the array: |
584
|
|
|
|
|
|
|
horizontal and vertical corner radii, and border width. |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
A border is used in annotations where text or some other material is put down, |
587
|
|
|
|
|
|
|
and a clickable rectangle is defined over it (-rect). A border is not used |
588
|
|
|
|
|
|
|
when an icon is being used to mark the clickable area. |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
The default is [0 0 1] (solid line of width 1, with sharp corners). |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
Defining option: |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
=over |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=item -border => [CRh, CRv, W] |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
=item -border => [CRh, CRv, W [, on, off...]] |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
Set annotation B of horizontal and vertical corner radii C |
601
|
|
|
|
|
|
|
and C (value 0 for squared corners) and width C (value 0 for no border). |
602
|
|
|
|
|
|
|
The default is squared corners and a solid line of width 1 ([0 0 1]). |
603
|
|
|
|
|
|
|
Optionally, a dash pattern array may be given (C length, C length, |
604
|
|
|
|
|
|
|
as one or more I). The default is a solid line. |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
The border vector seems to ignore the first two settings (corner radii), but |
607
|
|
|
|
|
|
|
the line thickness works, on basic Readers. |
608
|
|
|
|
|
|
|
The radii I work on some other Readers. |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
=back |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
=cut |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
sub border { |
615
|
0
|
|
|
0
|
1
|
0
|
my ($self, @b) = @_; |
616
|
|
|
|
|
|
|
|
617
|
0
|
0
|
|
|
|
0
|
if (scalar @b == 3) { |
|
|
0
|
|
|
|
|
|
618
|
0
|
|
|
|
|
0
|
$self->{'Border'} = PDFArray( map { PDFNum($_) } $b[0],$b[1],$b[2]); |
|
0
|
|
|
|
|
0
|
|
619
|
|
|
|
|
|
|
} elsif (scalar @b == 4) { |
620
|
|
|
|
|
|
|
# b[3] is an anonymous array |
621
|
0
|
|
|
|
|
0
|
my @first = map { PDFNum($_) } $b[0], $b[1], $b[2]; |
|
0
|
|
|
|
|
0
|
|
622
|
0
|
|
|
|
|
0
|
$self->{'Border'} = PDFArray( @first, PDFArray( map { PDFNum($_) } @{$b[3]} )); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
623
|
|
|
|
|
|
|
} else { |
624
|
0
|
|
|
|
|
0
|
die "annotation->border() style requires 3 or 4 parameters "; |
625
|
|
|
|
|
|
|
} |
626
|
0
|
|
|
|
|
0
|
return $self; |
627
|
|
|
|
|
|
|
} |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
=item $annotation->content(@lines) |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
Sets the text-content of the C annotation. |
632
|
|
|
|
|
|
|
This is a text string or array of strings. |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
=cut |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
sub content { |
637
|
2
|
|
|
2
|
1
|
7
|
my ($self, @lines) = @_; |
638
|
2
|
|
|
|
|
7
|
my $text = join("\n", @lines); |
639
|
|
|
|
|
|
|
|
640
|
2
|
|
|
|
|
9
|
$self->{'Contents'} = PDFString($text, 's'); |
641
|
2
|
|
|
|
|
5
|
return $self; |
642
|
|
|
|
|
|
|
} |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
# unused internal routine? TBD |
645
|
|
|
|
|
|
|
sub name { |
646
|
0
|
|
|
0
|
0
|
|
my ($self, $name) = @_; |
647
|
0
|
|
|
|
|
|
$self->{'Name'} = PDFName($name); |
648
|
0
|
|
|
|
|
|
return $self; |
649
|
|
|
|
|
|
|
} |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
=item $annotation->open($bool) |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
Display the C annotation either open or closed, if applicable. |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
Both are editable; the "open" form brings up the page with the entry area |
656
|
|
|
|
|
|
|
already open for editing, while "closed" has to be clicked on to edit it. |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
Defining option: |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
=over |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
=item -open => boolean |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
If true (1), the annotation will be marked as initially "open". |
665
|
|
|
|
|
|
|
If false (0), or the option is not given, the annotation is initially "closed". |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
=back |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=cut |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
sub open { ## no critic |
672
|
0
|
|
|
0
|
1
|
|
my ($self, $bool) = @_; |
673
|
0
|
0
|
|
|
|
|
$self->{'Open'} = PDFBool($bool? 1: 0); |
674
|
0
|
|
|
|
|
|
return $self; |
675
|
|
|
|
|
|
|
} |
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
=item $annotation->dest($page, I) |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
For certain annotation types (C or C), the I |
680
|
|
|
|
|
|
|
specifies how the content of the page C<$page> is to be fit to the window, |
681
|
|
|
|
|
|
|
while preserving its aspect ratio. |
682
|
|
|
|
|
|
|
These fit settings are: |
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
=over |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
=item -fit => 1 |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
Display the page with its contents magnified just enough |
689
|
|
|
|
|
|
|
to fit the entire page within the window both horizontally and vertically. If |
690
|
|
|
|
|
|
|
the required horizontal and vertical magnification factors are different, use |
691
|
|
|
|
|
|
|
the smaller of the two, centering the page within the window in the other |
692
|
|
|
|
|
|
|
dimension. |
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
=item -fith => $top |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
Display the page with the vertical coordinate C<$top> |
697
|
|
|
|
|
|
|
positioned at the top edge of the window and the contents of the page magnified |
698
|
|
|
|
|
|
|
just enough to fit the entire width of the page within the window. |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
=item -fitv => $left |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
Display the page with the horizontal coordinate C<$left> |
703
|
|
|
|
|
|
|
positioned at the left edge of the window and the contents of the page magnified |
704
|
|
|
|
|
|
|
just enough to fit the entire height of the page within the window. |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
=item -fitr => [$left, $bottom, $right, $top] |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
Display the page with its contents magnified just enough |
709
|
|
|
|
|
|
|
to fit the rectangle specified by the coordinates C<$left>, C<$bottom>, |
710
|
|
|
|
|
|
|
C<$right>, and C<$top> entirely within the window both horizontally and |
711
|
|
|
|
|
|
|
vertically. If the required horizontal and vertical magnification factors are |
712
|
|
|
|
|
|
|
different, use the smaller of the two, centering the rectangle within the window |
713
|
|
|
|
|
|
|
in the other dimension. |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
=item -fitb => 1 |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
Display the page with its contents magnified |
718
|
|
|
|
|
|
|
just enough to fit its bounding box entirely within the window both horizontally |
719
|
|
|
|
|
|
|
and vertically. If the required horizontal and vertical magnification factors |
720
|
|
|
|
|
|
|
are different, use the smaller of the two, centering the bounding box within the |
721
|
|
|
|
|
|
|
window in the other dimension. |
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
=item -fitbh => $top |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
Display the page with the vertical coordinate |
726
|
|
|
|
|
|
|
C<$top> positioned at the top edge of the window and the contents of the page |
727
|
|
|
|
|
|
|
magnified just enough to fit the entire width of its bounding box within the |
728
|
|
|
|
|
|
|
window. |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
=item -fitbv => $left |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
Display the page with the horizontal |
733
|
|
|
|
|
|
|
coordinate C<$left> positioned at the left edge of the window and the contents |
734
|
|
|
|
|
|
|
of the page magnified just enough to fit the entire height of its bounding box |
735
|
|
|
|
|
|
|
within the window. |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
=item -xyz => [$left, $top, $zoom] |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
Display the page with the coordinates C<[$left, $top]> |
740
|
|
|
|
|
|
|
positioned at the top-left corner of the window and the contents of the page |
741
|
|
|
|
|
|
|
magnified by the factor C<$zoom>. A zero (0) value for any of the parameters |
742
|
|
|
|
|
|
|
C<$left>, C<$top>, or C<$zoom> specifies that the current value of that |
743
|
|
|
|
|
|
|
parameter is to be retained unchanged. |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
This is the B fit setting, with position (left and top) and zoom |
746
|
|
|
|
|
|
|
the same as the calling page's ([undef, undef, undef]). |
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
=back |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
=item $annotation->dest($name) |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
Connect the Annotation to a "Named Destination" defined elsewhere, including |
753
|
|
|
|
|
|
|
the optional desired I (default: -xyz undef*3). |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
=cut |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
sub dest { |
758
|
0
|
|
|
0
|
1
|
|
my ($self, $page, %position) = @_; |
759
|
|
|
|
|
|
|
|
760
|
0
|
0
|
|
|
|
|
if (ref $page) { |
761
|
0
|
|
0
|
|
|
|
$self->{'A'} ||= PDFDict(); |
762
|
|
|
|
|
|
|
|
763
|
0
|
0
|
|
|
|
|
if (defined $position{'-fit'}) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
764
|
0
|
|
|
|
|
|
$self->{'A'}->{'D'} = PDFArray($page, PDFName('Fit')); |
765
|
|
|
|
|
|
|
} elsif (defined $position{'-fith'}) { |
766
|
0
|
|
|
|
|
|
$self->{'A'}->{'D'} = PDFArray($page, PDFName('FitH'), PDFNum($position{'-fith'})); |
767
|
|
|
|
|
|
|
} elsif (defined $position{'-fitb'}) { |
768
|
0
|
|
|
|
|
|
$self->{'A'}->{'D'} = PDFArray($page, PDFName('FitB')); |
769
|
|
|
|
|
|
|
} elsif (defined $position{'-fitbh'}) { |
770
|
0
|
|
|
|
|
|
$self->{'A'}->{'D'} = PDFArray($page, PDFName('FitBH'), PDFNum($position{'-fitbh'})); |
771
|
|
|
|
|
|
|
} elsif (defined $position{'-fitv'}) { |
772
|
0
|
|
|
|
|
|
$self->{'A'}->{'D'} = PDFArray($page, PDFName('FitV'), PDFNum($position{'-fitv'})); |
773
|
|
|
|
|
|
|
} elsif (defined $position{'-fitbv'}) { |
774
|
0
|
|
|
|
|
|
$self->{'A'}->{'D'} = PDFArray($page, PDFName('FitBV'), PDFNum($position{'-fitbv'})); |
775
|
|
|
|
|
|
|
} elsif (defined $position{'-fitr'}) { |
776
|
0
|
0
|
|
|
|
|
die "Insufficient parameters to -fitr => []) " unless scalar @{$position{'-fitr'}} == 4; |
|
0
|
|
|
|
|
|
|
777
|
0
|
|
|
|
|
|
$self->{'A'}->{'D'} = PDFArray($page, PDFName('FitR'), map {PDFNum($_)} @{$position{'-fitr'}}); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
} elsif (defined $position{'-xyz'}) { |
779
|
0
|
0
|
|
|
|
|
die "Insufficient parameters to -xyz => []) " unless scalar @{$position{'-xyz'}} == 3; |
|
0
|
|
|
|
|
|
|
780
|
0
|
0
|
|
|
|
|
$self->{'A'}->{'D'} = PDFArray($page, PDFName('XYZ'), map {defined $_ ? PDFNum($_) : PDFNull()} @{$position{'-xyz'}}); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
} else { |
782
|
|
|
|
|
|
|
# no "fit" option found. use default. |
783
|
0
|
|
|
|
|
|
$position{'-xyz'} = [undef,undef,undef]; |
784
|
0
|
0
|
|
|
|
|
$self->{'A'}->{'D'} = PDFArray($page, PDFName('XYZ'), map {defined $_ ? PDFNum($_) : PDFNull()} @{$position{'-xyz'}}); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
} |
786
|
|
|
|
|
|
|
} else { |
787
|
0
|
|
|
|
|
|
$self->{'Dest'} = PDFString($page, 'n'); |
788
|
|
|
|
|
|
|
} |
789
|
|
|
|
|
|
|
|
790
|
0
|
|
|
|
|
|
return $self; |
791
|
|
|
|
|
|
|
} |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
=item $annotation->Color(@color) |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
Set the icon's fill color. The color is an array of 1, 3, or 4 numbers, each |
796
|
|
|
|
|
|
|
in the range 0.0 to 1.0. If 1 number is given, it is the grayscale value (0 = |
797
|
|
|
|
|
|
|
black to 1 = white). If 3 numbers are given, it is an RGB color value. If 4 |
798
|
|
|
|
|
|
|
numbers are given, it is a CMYK color value. Currently, named colors (strings) |
799
|
|
|
|
|
|
|
are not handled. |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
For link and url annotations, this is the color of the rectangle border |
802
|
|
|
|
|
|
|
(-border given with a width of at least 1). |
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
If an invalid array length or numeric value is given, a medium gray ( [0.5] ) |
805
|
|
|
|
|
|
|
value is used, without any message. If no color is given, the usual fill color |
806
|
|
|
|
|
|
|
is black. |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
Defining option: |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
Named colors are not supported at this time. |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
=over |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
=item -color => [ ] or not 1, 3, or 4 numbers 0.0-1.0 |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
A medium gray (0.5 value) will be used if an invalid color is given. |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
=item -color => [ g ] |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
If I is between 0.0 (black) and 1.0 (white), the fill color will be gray. |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
=item -color => [ r, g, b ] |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
If I (red), I (green), and I (blue) are all between 0.0 and 1.0, the |
825
|
|
|
|
|
|
|
fill color will be the defined RGB hue. [ 0, 0, 0 ] is black, [ 1, 1, 0 ] is |
826
|
|
|
|
|
|
|
yellow, and [ 1, 1, 1 ] is white. |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
=item -color => [ c, m, y, k ] |
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
If I (red), I (magenta), I (yellow), and I (black) are all between |
831
|
|
|
|
|
|
|
0.0 and 1.0, the fill color will be the defined CMYK hue. [ 0, 0, 0, 0 ] is |
832
|
|
|
|
|
|
|
white, [ 1, 0, 1, 0 ] is green, and [ 1, 1, 1, 1 ] is black. |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
=back |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
=cut |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
sub Color { |
839
|
0
|
|
|
0
|
1
|
|
my ($self, @color) = @_; |
840
|
|
|
|
|
|
|
|
841
|
0
|
0
|
0
|
|
|
|
if (scalar @color == 1 && |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
842
|
|
|
|
|
|
|
$color[0] >= 0 && $color[0] <= 1.0) { |
843
|
0
|
|
|
|
|
|
$self->{'C'} = PDFArray(map { PDFNum($_) } $color[0]); |
|
0
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
} elsif (scalar @color == 3 && |
845
|
|
|
|
|
|
|
$color[0] >= 0 && $color[0] <= 1.0 && |
846
|
|
|
|
|
|
|
$color[1] >= 0 && $color[1] <= 1.0 && |
847
|
|
|
|
|
|
|
$color[2] >= 0 && $color[2] <= 1.0) { |
848
|
0
|
|
|
|
|
|
$self->{'C'} = PDFArray(map { PDFNum($_) } $color[0], $color[1], $color[2]); |
|
0
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
} elsif (scalar @color == 4 && |
850
|
|
|
|
|
|
|
$color[0] >= 0 && $color[0] <= 1.0 && |
851
|
|
|
|
|
|
|
$color[1] >= 0 && $color[1] <= 1.0 && |
852
|
|
|
|
|
|
|
$color[2] >= 0 && $color[2] <= 1.0 && |
853
|
|
|
|
|
|
|
$color[3] >= 0 && $color[3] <= 1.0) { |
854
|
0
|
|
|
|
|
|
$self->{'C'} = PDFArray(map { PDFNum($_) } $color[0], $color[1], $color[2], $color[3]); |
|
0
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
} else { |
856
|
|
|
|
|
|
|
# invalid -color entry. just set to medium gray without message |
857
|
0
|
|
|
|
|
|
$self->{'C'} = PDFArray(map { PDFNum($_) } 0.5 ); |
|
0
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
} |
859
|
|
|
|
|
|
|
|
860
|
0
|
|
|
|
|
|
return $self; |
861
|
|
|
|
|
|
|
} |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
=item -text => string |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
Specify an optional B for annotation. This text or comment only |
866
|
|
|
|
|
|
|
shows up I in the pop-up containing the file or text. |
867
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
=cut |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
sub icon_appearance { |
871
|
0
|
|
|
0
|
0
|
|
my ($self, $icon, %options) = @_; |
872
|
|
|
|
|
|
|
# $icon is a string with name of icon (confirmed not empty) or a reference. |
873
|
|
|
|
|
|
|
# if a string (text), has already defined /Name. "None" and ref handle here. |
874
|
|
|
|
|
|
|
# options of interest: -rect (to define size of icon) |
875
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
# text also permits icon and custom icon, including None |
877
|
|
|
|
|
|
|
#return unless $self->{'Subtype'}->val() eq 'FileAttachment'; |
878
|
|
|
|
|
|
|
|
879
|
0
|
|
|
|
|
|
my @r; # perlcritic doesn't want 2 lines combined |
880
|
0
|
0
|
|
|
|
|
@r = @{$options{'-rect'}} if defined $options{'-rect'}; |
|
0
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
# number of parameters should be 4, checked above (rect method) |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
# Handle custom icon type 'None' and icon reference. |
884
|
0
|
0
|
|
|
|
|
if ($icon eq 'None') { |
|
|
0
|
|
|
|
|
|
885
|
|
|
|
|
|
|
# It is not clear what viewers will do, so provide an |
886
|
|
|
|
|
|
|
# appearance dict with no graphics content. |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
# 9 0 obj << |
889
|
|
|
|
|
|
|
# ... |
890
|
|
|
|
|
|
|
# /AP << /D 11 0 R /N 11 0 R /R 11 0 R >> |
891
|
|
|
|
|
|
|
# ... |
892
|
|
|
|
|
|
|
# >> |
893
|
|
|
|
|
|
|
# 11 0 obj << |
894
|
|
|
|
|
|
|
# /BBox [ 0 0 100 100 ] |
895
|
|
|
|
|
|
|
# /FormType 1 |
896
|
|
|
|
|
|
|
# /Length 6 |
897
|
|
|
|
|
|
|
# /Matrix [ 1 0 0 1 0 0 ] |
898
|
|
|
|
|
|
|
# /Resources << |
899
|
|
|
|
|
|
|
# /ProcSet [ /PDF ] |
900
|
|
|
|
|
|
|
# >> |
901
|
|
|
|
|
|
|
# >> stream |
902
|
|
|
|
|
|
|
# 0 0 m |
903
|
|
|
|
|
|
|
# endstream endobj |
904
|
|
|
|
|
|
|
|
905
|
0
|
|
|
|
|
|
$self->{'AP'} = PDFDict(); |
906
|
0
|
|
|
|
|
|
my $d = PDFDict(); |
907
|
0
|
|
|
|
|
|
$self->{' apipdf'}->new_obj($d); |
908
|
0
|
|
|
|
|
|
$d->{'FormType'} = PDFNum(1); |
909
|
0
|
|
|
|
|
|
$d->{'Matrix'} = PDFArray(map { PDFNum($_) } 1, 0, 0, 1, 0, 0); |
|
0
|
|
|
|
|
|
|
910
|
0
|
|
|
|
|
|
$d->{'Resources'} = PDFDict(); |
911
|
0
|
|
|
|
|
|
$d->{'Resources'}->{'ProcSet'} = PDFArray( map { PDFName($_) } qw(PDF)); |
|
0
|
|
|
|
|
|
|
912
|
0
|
|
|
|
|
|
$d->{'BBox'} = PDFArray( map { PDFNum($_) } 0, 0, $r[2]-$r[0], $r[3]-$r[1] ); |
|
0
|
|
|
|
|
|
|
913
|
0
|
|
|
|
|
|
$d->{' stream'} = "0 0 m"; |
914
|
0
|
|
|
|
|
|
$self->{'AP'}->{'N'} = $d; # normal appearance |
915
|
|
|
|
|
|
|
# Should default to N, but be sure. |
916
|
0
|
|
|
|
|
|
$self->{'AP'}->{'R'} = $d; # Rollover |
917
|
0
|
|
|
|
|
|
$self->{'AP'}->{'D'} = $d; # Down |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
# Handle custom icon. |
920
|
|
|
|
|
|
|
} elsif (ref $icon) { |
921
|
|
|
|
|
|
|
# Provide an appearance dict with the image. |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
# 9 0 obj << |
924
|
|
|
|
|
|
|
# ... |
925
|
|
|
|
|
|
|
# /AP << /D 11 0 R /N 11 0 R /R 11 0 R >> |
926
|
|
|
|
|
|
|
# ... |
927
|
|
|
|
|
|
|
# >> |
928
|
|
|
|
|
|
|
# 11 0 obj << |
929
|
|
|
|
|
|
|
# /BBox [ 0 0 1 1 ] |
930
|
|
|
|
|
|
|
# /FormType 1 |
931
|
|
|
|
|
|
|
# /Length 13 |
932
|
|
|
|
|
|
|
# /Matrix [ 1 0 0 1 0 0 ] |
933
|
|
|
|
|
|
|
# /Resources << |
934
|
|
|
|
|
|
|
# /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] |
935
|
|
|
|
|
|
|
# /XObject << /PxCBA 7 0 R >> |
936
|
|
|
|
|
|
|
# >> |
937
|
|
|
|
|
|
|
# >> stream |
938
|
|
|
|
|
|
|
# q /PxCBA Do Q |
939
|
|
|
|
|
|
|
# endstream endobj |
940
|
|
|
|
|
|
|
|
941
|
0
|
|
|
|
|
|
$self->{'AP'} = PDFDict(); |
942
|
0
|
|
|
|
|
|
my $d = PDFDict(); |
943
|
0
|
|
|
|
|
|
$self->{' apipdf'}->new_obj($d); |
944
|
0
|
|
|
|
|
|
$d->{'FormType'} = PDFNum(1); |
945
|
0
|
|
|
|
|
|
$d->{'Matrix'} = PDFArray(map { PDFNum($_) } 1, 0, 0, 1, 0, 0); |
|
0
|
|
|
|
|
|
|
946
|
0
|
|
|
|
|
|
$d->{'Resources'} = PDFDict(); |
947
|
0
|
|
|
|
|
|
$d->{'Resources'}->{'ProcSet'} = PDFArray(map { PDFName($_) } qw(PDF Text ImageB ImageC ImageI)); |
|
0
|
|
|
|
|
|
|
948
|
0
|
|
|
|
|
|
$d->{'Resources'}->{'XObject'} = PDFDict(); |
949
|
0
|
|
|
|
|
|
my $im = $icon->{'Name'}->val(); |
950
|
0
|
|
|
|
|
|
$d->{'Resources'}->{'XObject'}->{$im} = $icon; |
951
|
|
|
|
|
|
|
# Note that the image is scaled to one unit in user space. |
952
|
0
|
|
|
|
|
|
$d->{'BBox'} = PDFArray(map { PDFNum($_) } 0, 0, 1, 1); |
|
0
|
|
|
|
|
|
|
953
|
0
|
|
|
|
|
|
$d->{' stream'} = "q /$im Do Q"; |
954
|
0
|
|
|
|
|
|
$self->{'AP'}->{'N'} = $d; # normal appearance |
955
|
|
|
|
|
|
|
|
956
|
0
|
|
|
|
|
|
if (0) { |
957
|
|
|
|
|
|
|
# Testing... Provide an alternative for R and D. |
958
|
|
|
|
|
|
|
# Works only with Adobe Reader. |
959
|
|
|
|
|
|
|
$d = PDFDict(); |
960
|
|
|
|
|
|
|
$self->{' apipdf'}->new_obj($d); |
961
|
|
|
|
|
|
|
$d->{'Type'} = PDFName('XObject'); |
962
|
|
|
|
|
|
|
$d->{'Subtype'} = PDFName('Form'); |
963
|
|
|
|
|
|
|
$d->{'FormType'} = PDFNum(1); |
964
|
|
|
|
|
|
|
$d->{'Matrix'} = PDFArray(map { PDFNum($_) } 1, 0, 0, 1, 0, 0); |
965
|
|
|
|
|
|
|
$d->{'Resources'} = PDFDict(); |
966
|
|
|
|
|
|
|
$d->{'Resources'}->{'ProcSet'} = PDFArray(map { PDFName($_) } qw(PDF)); |
967
|
|
|
|
|
|
|
$d->{'BBox'} = PDFArray(map { PDFNum($_) } 0, 0, $r[2]-$r[0], $r[3]-$r[1]); |
968
|
|
|
|
|
|
|
$d->{' stream'} = |
969
|
|
|
|
|
|
|
join( " ", |
970
|
|
|
|
|
|
|
# black outline |
971
|
|
|
|
|
|
|
0, 0, 'm', |
972
|
|
|
|
|
|
|
0, $r[2]-$r[0], 'l', |
973
|
|
|
|
|
|
|
$r[2]-$r[0], $r[3]-$r[1], 'l', |
974
|
|
|
|
|
|
|
$r[2]-$r[0], 0, 'l', |
975
|
|
|
|
|
|
|
's', |
976
|
|
|
|
|
|
|
); |
977
|
|
|
|
|
|
|
} |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
# Should default to N, but be sure. |
980
|
0
|
|
|
|
|
|
$self->{'AP'}->{'R'} = $d; # Rollover |
981
|
0
|
|
|
|
|
|
$self->{'AP'}->{'D'} = $d; # Down |
982
|
|
|
|
|
|
|
} |
983
|
|
|
|
|
|
|
|
984
|
0
|
|
|
|
|
|
return $self; |
985
|
|
|
|
|
|
|
} |
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
=back |
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
=cut |
990
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
1; |