| 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; |