1
package Text::PDF::Pages;
4
use vars qw(@ISA %inst);
5
@ISA = qw(Text::PDF::Dict);
6
# no warnings qw(uninitialized);
11
%inst = map {$_ => 1} qw(Parent Type);
15
Text::PDF::Pages - a PDF pages hierarchical element. Inherits from L<Text::PDF::Dict>
19
A Pages object is the parent to other pages objects or to page objects
24
=head2 Text::PDF::Pages->new($pdfs,$parent)
26
This creates a new Pages object. Notice that $parent here is not the
27
file context for the object but the parent pages object for this
28
pages. If we are using this class to create a root node, then $parent
29
should point to the file context, which is identified by not having a
30
Type of Pages. $pdfs is the file object (or objects) in which to
31
create the new Pages object.
37
my ($class, $pdfs, $parent) = @_;
40
$class = ref $class if ref $class;
41
$self = $class->SUPER::new($pdfs, $parent);
42
$self->{'Type'} = PDFName("Pages");
43
$self->{'Parent'} = $parent if defined $parent;
44
$self->{'Count'} = PDFNum(0);
45
$self->{'Kids'} = Text::PDF::Array->new;
46
$self->{' outto'} = ref $pdfs eq 'ARRAY' ? $pdfs : [$pdfs];
55
my ($self, $pdf) = @_;
56
$self->{' outto'} = [$pdf];
60
=head2 $p->out_obj($isnew)
62
Tells all the files that this thing is destined for that they should output this
63
object come time to output. If this object has no parent, then it must be the
64
root. So set as the root for the files in question and tell it to be output too.
65
If $isnew is set, then call new_obj rather than out_obj to create as a new
72
my ($self, $isnew) = @_;
74
foreach (@{$self->{' outto'}})
77
{ $_->new_obj($self); }
79
{ $_->out_obj($self); }
81
unless (defined $self->{'Parent'})
83
$_->{'Root'}{'Pages'} = $self;
84
$_->out_obj($_->{'Root'});
91
=head2 $p->find_page($pnum)
93
Returns the given page, using the page count values in the pages tree. Pages
100
my ($self, $pnum) = @_;
101
my ($top) = $self->get_top;
103
$top->find_page_recurse(\$pnum);
107
sub find_page_recurse
109
my ($self, $rpnum) = @_;
112
if ($self->{'Count'}->realise->val <= $$rpnum)
114
$$rpnum -= $self->{'Count'}->val;
118
foreach $k ($self->{'Kids'}->realise->elementsof)
120
if ($k->{'Type'}->realise->val eq 'Page')
122
return $k if ($$rpnum == 0);
125
elsif ($res = $k->realise->find_page_recurse($rpnum))
131
=head2 $p->add_page($page, $pnum)
133
Inserts the page before the given $pnum. $pnum can be -ve to count from the END
134
of the document. -1 is after the last page. Likewise $pnum can be greater than the
135
number of pages currently in the document, to append.
137
This method only guarantees to provide a reasonable pages tree if pages are
138
appended or prepended to the document. Pages inserted in the middle of the
139
document may simply be inserted in the appropriate leaf in the pages tree without
140
adding any new branches or leaves. To tidy up such a mess, it is best to call
141
$p->rebuild_tree to rebuild the pages tree into something efficient.
147
my ($self, $page, $pnum) = @_;
148
my ($top) = $self->get_top;
149
my ($ppage, $ppages, $pindex, $ppnum);
151
$pnum = -1 unless (defined $pnum && $pnum <= $top->{'Count'}->val);
153
{ $ppage = $top->find_page($top->{'Count'}->val - 1); }
156
$pnum = $top->{'Count'}->val + $pnum + 1 if ($pnum < 0);
157
$ppage = $top->find_page($pnum);
160
if (defined $ppage->{'Parent'})
161
{ $ppages = $ppage->{'Parent'}->realise; }
165
$ppnum = scalar $ppages->{'Kids'}->realise->elementsof;
171
for ($pindex = 0; $pindex < $ppnum; $pindex++)
172
{ last if ($ppages->{'Kids'}{' val'}[$pindex] eq $ppage); }
173
$pindex = -1 if ($pindex == $ppnum);
176
$ppages->add_page_recurse($page->realise, $pindex);
177
for ($ppages = $page->{'Parent'}; defined $ppages->{'Parent'}; $ppages = $ppages->{'Parent'}->realise)
178
{ $ppages->out_obj->{'Count'}->realise->{'val'}++; }
179
$ppages->out_obj->{'Count'}->realise->{'val'}++;
186
my ($self, $page, $index) = @_;
187
my ($newpages, $ppages, $pindex, $ppnum);
189
if (scalar $self->{'Kids'}->elementsof >= 8 && $self->{'Parent'} && $index < 1)
191
$ppages = $self->{'Parent'}->realise;
192
$newpages = $self->new($self->{' outto'}, $ppages);
195
$ppnum = scalar $ppages->{'Kids'}->realise->elementsof;
196
for ($pindex = 0; $pindex < $ppnum; $pindex++)
197
{ last if ($ppages->{'Kids'}{' val'}[$pindex] eq $self); }
198
$pindex = -1 if ($pindex == $ppnum);
199
$ppages->add_page_recurse($newpages, $pindex);
203
{ $newpages = $self->out_obj; }
206
{ push (@{$newpages->{'Kids'}->realise->{' val'}}, $page); }
208
{ splice (@{$newpages->{'Kids'}{' val'}}, $index, 0, $page); }
209
$page->{'Parent'} = $newpages;
213
=head2 $root_pages = $p->rebuild_tree([@pglist])
215
Rebuilds the pages tree to make a nice balanced tree that conforms to Adobe
216
recommendations. If passed a pglist then the tree is built for that list of
217
pages. No check is made of whether the pglist contains pages.
219
Returns the top of the tree for insertion in the root object.
225
my ($self, @pglist) = @_;
229
=head2 @pglist = $p->get_pages
231
Returns a list of page objects in the document in page order
239
return $self->get_top->get_kids;
243
# only call this on the top level or anything you want pages below
247
my ($pgref, @pglist);
249
foreach $pgref ($self->{'Kids'}->elementsof)
252
if ($pgref->{'Type'}->val =~ m/^Pages$/oi)
253
{ push (@pglist, proc_pages($pgref)); }
255
{ push (@pglist, $pgref); }
260
=head2 $p->find_prop($key)
262
Searches up through the inheritance tree to find a property.
268
my ($self, $prop) = @_;
270
if (defined $self->{$prop})
272
if (ref $self->{$prop} && $self->{$prop}->isa("Text::PDF::Objind"))
273
{ return $self->{$prop}->realise; }
275
{ return $self->{$prop}; }
276
} elsif (defined $self->{'Parent'})
277
{ return $self->{'Parent'}->find_prop($prop); }
280
# defined $_[0]->{$_[1]} && $_[0]->{$_[1]}->realised or
281
# defined $_[0]->{'Parent'} && $_[0]->{'Parent'}->find_prop($_[1]); }
284
=head2 $p->add_font($pdf, $font)
286
Creates or edits the resource dictionary at this level in the hierarchy. If
287
the font is already supported even through the hierarchy, then it is not added.
293
my ($self, $font, $pdf) = @_;
294
my ($name) = $font->{'Name'}->val;
295
my ($dict) = $self->find_prop('Resources');
298
return $self if ($dict ne "" && defined $dict->{'Font'} && defined $dict->{'Font'}{$name});
299
unless (defined $self->{'Resources'})
301
$dict = $dict ne "" ? $dict->copy($pdf) : PDFDict();
302
$self->{'Resources'} = $dict;
305
{ $dict = $self->{'Resources'}; }
306
$dict->{'Font'} = PDFDict() unless defined $self->{'Resources'}{'Font'};
307
$rdict = $dict->{'Font'}->val;
308
$rdict->{$name} = $font unless ($rdict->{$name});
309
if (ref $dict ne 'HASH' && $dict->is_obj($pdf))
310
{ $pdf->out_obj($dict); }
311
if (ref $rdict ne 'HASH' && $rdict->is_obj($pdf))
312
{ $pdf->out_obj($rdict); }
317
=head2 $p->bbox($xmin, $ymin, $xmax, $ymax, [$param])
319
Specifies the bounding box for this and all child pages. If the values are
320
identical to those inherited then no change is made. $param specifies the attribute
321
name so that other 'bounding box'es can be set with this method.
327
my ($self, @bbox) = @_;
328
my ($str) = $bbox[4] || 'MediaBox';
329
my ($inh) = $self->find_prop($str);
335
foreach $e ($inh->elementsof)
336
{ $test &= $e->val == $bbox[$i++]; }
337
return $self if $test && $i == 4;
340
$inh = Text::PDF::Array->new;
341
foreach $e (@bbox[0..3])
342
{ $inh->add_elements(PDFNum($e)); }
343
$self->{$str} = $inh;
348
=head2 $p->proc_set(@entries)
350
Ensures that the current resource contains all the entries in the proc_sets
351
listed. If necessary it creates a local resource dictionary to achieve this.
357
my ($self, @entries) = @_;
358
my (@temp) = @entries;
361
$dict = $self->find_prop('Resource');
362
if ($dict ne "" && defined $dict->{'ProcSet'})
364
foreach $e ($dict->{'ProcSet'}->elementsof)
365
{ @temp = grep($_ ne $e, @temp); }
366
return $self if (scalar @temp == 0);
367
@entries = @temp if defined $self->{'Resources'};
370
unless (defined $self->{'Resources'})
371
{ $self->{'Resources'} = $dict ne "" ? $dict->copy : PDFDict(); }
373
$self->{'Resources'}{'ProcSet'} = PDFArray() unless defined $self->{'ProcSet'};
375
foreach $e (@entries)
376
{ $self->{'Resources'}{'ProcSet'}->add_elements(PDFName($e)); }
383
my ($parent) = $self->{'Parent'} if defined ($self->{'Parent'});
386
$self->{'Parent'} = $parent if defined $parent;
391
{ return $inst{$_[1]} || $_[0]->SUPER::dont_copy($_[1]); }
396
Returns the top of the pages tree
405
for ($p = $self; defined $p->{'Parent'}; $p = $p->{'Parent'})