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   289 use strict;
  41         76  
  41         1005  
19 41     41   175 use warnings;
  41         77  
  41         911  
20 41     41   195 use Scalar::Util 'isweak';
  41         79  
  41         2947  
21              
22             our $VERSION = '3.024'; # 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   221 use Scalar::Util qw(blessed reftype weaken);
  41         133  
  41         2275  
71              
72 41     41   254 use vars qw($uidc @inst %inst);
  41         81  
  41         10925  
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 3775 my ($class) = @_;
87              
88 2160   33     8053 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 67379 $_[0]->{' uid'} || ($_[0]->{' uid'} = $uidc++);
99 32574         74643 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 16544     16544 1 22275 my ($self) = @_;
122              
123 16544         28159 my @tofree = grep { !isweak $_ } values %$self;
  51098         92984  
124 16544         24694 %$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   279 no warnings 'recursion'; ## no critic
  41         119  
  41         33712  
130              
131 16544         27804 while (my $item = shift @tofree) {
132             # common case: value is not reference
133 54537   100     100971 my $ref = ref($item) || next;
134              
135 15051 100 100     53787 if (blessed($item) and $item->can('release')) {
    100 33        
    50          
136 13998         21203 $item->release();
137             } elsif ($ref eq 'ARRAY') {
138 1033         3256 push @tofree, @$item;
139             } elsif (defined(reftype($ref)) and reftype($ref) eq 'HASH') {
140 0         0 release($item);
141             }
142             }
143 16544         37808 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 3509 my $self = shift();
181              
182 2752 100       8563 return $self if $self->{' realised'};
183 118 100       421 return $self->{' parent'}->read_obj($self, @_) if $self->{' objnum'};
184 32         101 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 20847 my ($self, $fh, $pdf) = @_;
221              
222 15404 100       23343 if (defined $pdf->{' objects'}{$self->uid()}) {
223 1263         1869 $fh->printf("%d %d R", @{$pdf->{' objects'}{$self->uid()}}[0..1]);
  1263         2104  
224             } else {
225 14141         25271 $self->outobjdeep($fh, $pdf);
226             }
227 15404         28421 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 7 my ($self) = @_;
244              
245 3 50       8 if ($self->{' realised'}) {
246 3         11 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 156 my ($self, $other) = @_;
281              
282 90         393 for my $k (keys %$other) {
283 430 100       725 next if $inst{$k};
284 340         566 $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       645 weaken $self->{$k} if $k eq 'Parent';
289             }
290 90         183 $self->{' realised'} = 1;
291 90         214 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 9623 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 4646 my ($self, $pdf, $res) = @_;
324              
325 3129 50       4963 unless (defined $res) {
326 3129         3932 $res = {};
327 3129         4569 bless $res, ref($self);
328             }
329 3129         6442 foreach my $k (keys %$self) {
330 9412 100       14529 next if $inst{$k};
331 3140 50       4614 next if defined $res->{$k};
332 3140 100 66     8480 if (blessed($self->{$k}) and $self->{$k}->can('is_obj') and not $self->{$k}->is_obj($pdf)) {
      66        
333 208         734 $res->{$k} = $self->{$k}->copy($pdf);
334             } else {
335 2932         6364 $res->{$k} = $self->{$k};
336             }
337             }
338 3129         7000 return $res;
339             }
340              
341             =back
342              
343             =cut
344              
345             1;