File Coverage

blib/lib/PDF/Builder/Basic/PDF/Objind.pm
Criterion Covered Total %
statement 64 79 81.0
branch 24 34 70.5
condition 11 17 64.7
subroutine 15 19 78.9
pod 12 13 92.3
total 126 162 77.7


line stmt bran cond sub pod time code
1             #=======================================================================
2             #
3             # THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW:
4             #
5             # Copyright Martin Hosken
6             #
7             # No warranty or expression of effectiveness, least of all regarding
8             # anyone's safety, is implied in this software or documentation.
9             #
10             # This specific module is licensed under the Perl Artistic License.
11             # Effective 28 January 2021, the original author and copyright holder,
12             # Martin Hosken, has given permission to use and redistribute this module
13             # under the MIT license.
14             #
15             #=======================================================================
16             package PDF::Builder::Basic::PDF::Objind;
17              
18 41     41   347 use strict;
  41         80  
  41         1225  
19 41     41   253 use warnings;
  41         103  
  41         1067  
20 41     41   245 use Scalar::Util 'isweak';
  41         96  
  41         3572  
21              
22             our $VERSION = '3.025'; # VERSION
23             our $LAST_UPDATE = '3.024'; # manually update whenever code is changed
24              
25             =head1 NAME
26              
27             PDF::Builder::Basic::PDF::Objind - PDF indirect object reference. Also acts as an
28             abstract superclass for all elements in a PDF file.
29              
30             =head1 INSTANCE VARIABLES
31              
32             Instance variables differ from content variables in that they all start with
33             a space.
34              
35             =over
36              
37             =item ' parent'
38              
39             For an object which is a reference to an object in some source, this holds the
40             reference to the source object, so that should the reference have to be
41             de-referenced, then we know where to go and get the info.
42              
43             =item ' objnum' (R)
44              
45             The object number in the source (only for object references)
46              
47             =item ' objgen' (R)
48              
49             The object generation in the source
50              
51             There are other instance variables which are used by the parent for file control.
52              
53             =item ' isfree'
54              
55             This marks whether the object is in the free list and available for re-use as
56             another object elsewhere in the file.
57              
58             =item ' nextfree'
59              
60             Holds a direct reference to the next free object in the free list.
61              
62             =back
63              
64             =head1 METHODS
65              
66             =over
67              
68             =cut
69              
70 41     41   273 use Scalar::Util qw(blessed reftype weaken);
  41         95  
  41         2753  
71              
72 41     41   294 use vars qw($uidc @inst %inst);
  41         114  
  41         13103  
73             $uidc = "pdfuid000";
74              
75             # protected keys during emptying and copying, etc.
76             @inst = qw(parent objnum objgen isfree nextfree uid realised);
77             $inst{" $_"} = 1 for @inst;
78              
79             =item PDF::Builder::Basic::PDF::Objind->new()
80              
81             Creates a new indirect object
82              
83             =cut
84              
85             sub new {
86 2160     2160 1 4346 my ($class) = @_;
87              
88 2160   33     9400 return bless {}, ref $class || $class;
89             }
90              
91             =item $UID = $r->uid()
92              
93             Returns a Unique id for this object, creating one if it didn't have one before
94              
95             =cut
96              
97             sub uid {
98 32574 100   32574 1 80614 $_[0]->{' uid'} || ($_[0]->{' uid'} = $uidc++);
99 32574         87809 return $_[0]->{' uid'};
100             }
101              
102             =item $r->release()
103              
104             Releases ALL of the memory used by this indirect object, and all of
105             its component/child objects. This method is called automatically by
106             'Crelease>' (so you don't have to
107             call it yourself).
108              
109             B it is important that this method get called at some point
110             prior to the actual destruction of the object. Internally, PDF files
111             have an enormous amount of cross-references and this causes circular
112             references within our own internal data structures. Calling
113             'C' forces these circular references to be cleaned up and
114             the entire internal data structure purged.
115              
116             =cut
117              
118             # Maintainer's Question: Couldn't this be handled by a DESTROY method
119             # instead of requiring an explicit call to release()?
120             sub release {
121 16518     16518 1 26421 my ($self) = @_;
122              
123 16518         32050 my @tofree = grep { !isweak $_ } values %$self;
  51092         108406  
124 16518         29829 %$self = ();
125              
126             # PDFs with highly-interconnected page trees or outlines can hit Perl's
127             # recursion limit pretty easily, so disable the warning for this specific
128             # loop.
129 41     41   309 no warnings 'recursion'; ## no critic
  41         135  
  41         40903  
130              
131 16518         32593 while (my $item = shift @tofree) {
132             # common case: value is not reference
133 54487   100     121693 my $ref = ref($item) || next;
134              
135 15021 100 100     63221 if (blessed($item) and $item->can('release')) {
    100 33        
    50          
136 13971         25506 $item->release();
137             } elsif ($ref eq 'ARRAY') {
138 1030         3728 push @tofree, @$item;
139             } elsif (defined(reftype($ref)) and reftype($ref) eq 'HASH') {
140 0         0 release($item);
141             }
142             }
143 16518         44946 return;
144             }
145              
146             =item $value = $r->val()
147              
148             Returns the value of this object or reads the object and then returns
149             its value.
150              
151             Note that all direct subclasses *must* make their own versions of this
152             subroutine otherwise we could be in for a very deep loop!
153              
154             =cut
155              
156             sub val {
157 0     0 1 0 my ($self) = @_;
158              
159             # this original code is very confusing. is this a
160             # recursive call to this val(), or another? what is
161             # supposed to be returned when self->realised is True?
162             # perlcritic doesn't like this...
163             #$self->{' parent'}->read_obj(@_)->val()
164             # unless $self->{' realised'}; ## no critic
165              
166 0 0       0 if ($self->{' realised'}) {
167 0         0 return $self->{' realised'}; # return undef in any cases?
168             } else {
169 0         0 return $self->{' parent'}->read_obj(@_)->val();
170             }
171             }
172              
173             =item $r->realise()
174              
175             Makes sure that the object is fully read in, etc.
176              
177             =cut
178              
179             sub realise {
180 2752     2752 1 4135 my $self = shift();
181              
182 2752 100       9665 return $self if $self->{' realised'};
183 118 100       486 return $self->{' parent'}->read_obj($self, @_) if $self->{' objnum'};
184 32         118 return $self;
185             }
186              
187             =item $v = $r->outobjdeep($fh, $pdf)
188              
189             If you really want to output this object, then you need to read it first.
190             This also means that all direct subclasses must subclass this method, or they
191             will loop forever!
192              
193             =cut
194              
195             sub outobjdeep {
196 0     0 1 0 my ($self, $fh, $pdf) = @_;
197              
198             # this original code is very confusing. is this a
199             # recursive call to this outobjdeep(), or another? what is
200             # supposed to be returned when self->realised is True?
201             # perlcritic doesn't like the lack of explicit return...
202             #$self->{' parent'}->read_obj($self)->outobjdeep($fh, $pdf)
203             # unless $self->{' realised'}; ## no critic
204              
205 0 0       0 if ($self->{' realised'}) {
206 0         0 return $self->{' realised'}; # return undef in any cases?
207             } else {
208 0         0 return $self->{' parent'}->read_obj($self)->outobjdeep($fh, $pdf);
209             }
210             }
211              
212             =item $r->outobj($fh, $pdf)
213              
214             If this is a full object then outputs a reference to the object, otherwise calls
215             outobjdeep to output the contents of the object at this point.
216              
217             =cut
218              
219             sub outobj {
220 15404     15404 1 25260 my ($self, $fh, $pdf) = @_;
221              
222 15404 100       26684 if (defined $pdf->{' objects'}{$self->uid()}) {
223 1263         2149 $fh->printf("%d %d R", @{$pdf->{' objects'}{$self->uid()}}[0..1]);
  1263         2418  
224             } else {
225 14141         30083 $self->outobjdeep($fh, $pdf);
226             }
227 15404         33586 return;
228             }
229              
230             =item $s = $r->elements()
231              
232             Abstract superclass function filler. Returns self here but should return
233             something more useful if an array.
234              
235             The old name of this method, C, has been B and will
236             be removed in the future.
237              
238             =cut
239              
240 0     0 0 0 sub elementsof { return elements(@_); }
241              
242             sub elements {
243 3     3 1 8 my ($self) = @_;
244              
245 3 50       11 if ($self->{' realised'}) {
246 3         30 return $self;
247             } else {
248 0         0 return $self->{' parent'}->read_obj($self)->elements();
249             }
250             }
251              
252             =item $s = $r->empty()
253              
254             Empties all content from this object to free up memory or to be read to pass
255             the object into the free list. Simplistically undefs all instance variables
256             other than object number and generation.
257              
258             =cut
259              
260             sub empty {
261 0     0 1 0 my ($self) = @_;
262              
263 0         0 for my $k (keys %$self) {
264 0 0       0 undef $self->{$k} unless $inst{$k};
265             }
266              
267 0         0 return $self;
268             }
269              
270             =item $o = $r->merge($objind)
271              
272             This merges content information into an object reference placeholder.
273             This occurs when an object reference is read before the object definition
274             and the information in the read data needs to be merged into the object
275             placeholder.
276              
277             =cut
278              
279             sub merge {
280 90     90 1 196 my ($self, $other) = @_;
281              
282 90         457 for my $k (keys %$other) {
283 430 100       873 next if $inst{$k};
284 340         663 $self->{$k} = $other->{$k};
285              
286             # This doesn't seem like the right place to do this, but I haven't
287             # yet found all of the places where Parent is being set
288 340 100       787 weaken $self->{$k} if $k eq 'Parent';
289             }
290 90         225 $self->{' realised'} = 1;
291 90         251 return bless $self, ref($other);
292             }
293              
294             =item $r->is_obj($pdf)
295              
296             Returns whether this object is a full object with its own object number or
297             whether it is purely a sub-object. C<$pdf> indicates which output file we are
298             concerned that the object is an object in.
299              
300             =cut
301              
302             sub is_obj {
303 4731     4731 1 10720 return defined $_[1]->{' objects'}{$_[0]->uid()};
304             }
305              
306             =item $r->copy($pdf, $res)
307              
308             Returns a new copy of this object. The object is assumed to be some kind
309             of associative array and the copy is a deep copy for elements which are
310             not PDF objects, according to C<$pdf>, and shallow copy for those that are.
311             Notice that calling C on an object forces at least a one level
312             copy even if it is a PDF object. The returned object loses its PDF
313             object status though.
314              
315             If C<$res> is defined then the copy goes into that object rather than creating a
316             new one. It is up to the caller to bless C<$res>, etc. Notice that elements from
317             C<$self> are not copied into C<$res> if there is already an entry for them
318             existing in C<$res>.
319              
320             =cut
321              
322             sub copy {
323 3129     3129 1 5563 my ($self, $pdf, $res) = @_;
324              
325 3129 50       5672 unless (defined $res) {
326 3129         4813 $res = {};
327 3129         5369 bless $res, ref($self);
328             }
329 3129         7683 foreach my $k (keys %$self) {
330 9412 100       17641 next if $inst{$k};
331 3140 50       5678 next if defined $res->{$k};
332 3140 100 66     9630 if (blessed($self->{$k}) and $self->{$k}->can('is_obj') and not $self->{$k}->is_obj($pdf)) {
      66        
333 208         730 $res->{$k} = $self->{$k}->copy($pdf);
334             } else {
335 2932         7034 $res->{$k} = $self->{$k};
336             }
337             }
338 3129         8194 return $res;
339             }
340              
341             =back
342              
343             =cut
344              
345             1;