File Coverage

blib/lib/PDF/API3/Compat/API2/Basic/PDF/Objind.pm
Criterion Covered Total %
statement 9 90 10.0
branch 0 44 0.0
condition 0 8 0.0
subroutine 3 18 16.6
pod 12 14 85.7
total 24 174 13.7


line stmt bran cond sub pod time code
1             #=======================================================================
2             # ____ ____ _____ _ ____ ___ ____
3             # | _ \| _ \| ___| _ _ / \ | _ \_ _| |___ \
4             # | |_) | | | | |_ (_) (_) / _ \ | |_) | | __) |
5             # | __/| |_| | _| _ _ / ___ \| __/| | / __/
6             # |_| |____/|_| (_) (_) /_/ \_\_| |___| |_____|
7             #
8             # A Perl Module Chain to faciliate the Creation and Modification
9             # of High-Quality "Portable Document Format (PDF)" Files.
10             #
11             #=======================================================================
12             #
13             # THIS IS A REUSED PERL MODULE, FOR PROPER LICENCING TERMS SEE BELOW:
14             #
15             #
16             # Copyright Martin Hosken
17             #
18             # No warranty or expression of effectiveness, least of all regarding
19             # anyone's safety, is implied in this software or documentation.
20             #
21             # This specific module is licensed under the Perl Artistic License.
22             #
23             #
24             # $Id: Objind.pm,v 2.1 2007/03/10 12:18:36 areibens Exp $
25             #
26             #=======================================================================
27             package PDF::API3::Compat::API2::Basic::PDF::Objind;
28            
29             =head1 NAME
30            
31             PDF::API3::Compat::API2::Basic::PDF::Objind - PDF indirect object reference. Also acts as an abstract
32             superclass for all elements in a PDF file.
33            
34             =head1 INSTANCE VARIABLES
35            
36             Instance variables differ from content variables in that they all start with
37             a space.
38            
39             =over
40            
41             =item parent
42            
43             For an object which is a reference to an object in some source, this holds the
44             reference to the source object, so that should the reference have to be
45             de-referenced, then we know where to go and get the info.
46            
47             =item objnum (R)
48            
49             The object number in the source (only for object references)
50            
51             =item objgen (R)
52            
53             The object generation in the source
54            
55             There are other instance variables which are used by the parent for file control.
56            
57             =item isfree
58            
59             This marks whether the object is in the free list and available for re-use as
60             another object elsewhere in the file.
61            
62             =item nextfree
63            
64             Holds a direct reference to the next free object in the free list.
65            
66             =back
67            
68             =head1 METHODS
69            
70             =cut
71            
72 1     1   5 use strict;
  1         2  
  1         34  
73 1     1   6 use vars qw(@inst %inst $uidc);
  1         1  
  1         65  
74 1     1   6 no warnings qw[ deprecated recursion uninitialized ];
  1         2  
  1         1324  
75            
76             # protected keys during emptying and copying, etc.
77            
78             @inst = qw(parent objnum objgen isfree nextfree uid realised);
79             map {$inst{" $_"} = 1} @inst;
80             $uidc = "pdfuid000";
81            
82            
83             =head2 PDF::API3::Compat::API2::Basic::PDF::Objind->new()
84            
85             Creates a new indirect object
86            
87             =cut
88            
89             sub new
90             {
91 0     0 1   my ($class) = @_;
92 0           my ($self) = {};
93            
94 0   0       bless $self, ref $class || $class;
95             }
96            
97             =head2 uid
98            
99             Returns a Unique id for this object, creating one if it didn't have one before
100            
101             =cut
102            
103             sub uid
104 0 0   0 1   { $_[0]->{' uid'} || ($_[0]->{' uid'} = $uidc++); }
105            
106             =head2 $r->release
107            
108             Releases ALL of the memory used by this indirect object, and all of its
109             component/child objects. This method is called automatically by
110             'Crelease>' (so you don't have to call it yourself).
111            
112             B, that it is important that this method get called at some point prior
113             to the actual destruction of the object. Internally, PDF files have an
114             enormous amount of cross-references and this causes circular references within
115             our own internal data structures. Calling 'C' forces these circular
116             references to be cleaned up and the entire internal data structure purged.
117            
118             B As part of the brute-force cleanup done here, this method
119             will throw a warning message whenever unexpected key values are found within
120             the C object. This is done to help ensure that unexpected
121             and unfreed values are brought to your attention, so you can bug us to keep the
122             module updated properly; otherwise the potential for memory leaks due to
123             dangling circular references will exist.
124            
125             =cut
126            
127             sub __release
128             {
129 0     0     my ($self, $force) = @_;
130 0           my (@tofree);
131            
132 0 0         return($self) unless(ref $self);
133             # delete stuff that we know we can, here
134            
135 0 0         if ($force)
136             {
137 0           foreach my $key (keys %{$self})
  0            
138             {
139 0           push(@tofree,$self->{$key});
140 0           $self->{$key}=undef;
141 0           delete($self->{$key});
142             }
143             }
144             else
145 0           { @tofree = map { delete $self->{$_} } keys %{$self}; }
  0            
  0            
146            
147 0           while (my $item = shift @tofree)
148             {
149 0           my $ref = ref($item);
150 0 0         if (UNIVERSAL::can($item, 'release'))
    0          
    0          
151 0           { $item->release($force); }
152             elsif ($ref eq 'ARRAY')
153 0           { push( @tofree, @{$item} ); }
  0            
154             elsif (UNIVERSAL::isa($ref, 'HASH'))
155 0           { release($item, $force); }
156             }
157            
158             # check that everything has gone - it better had!
159 0           foreach my $key (keys %{$self})
  0            
160             {
161             # warn ref($self) . " still has '$key' key left after release.\n";
162 0           $self->{$key}=undef;
163 0           delete($self->{$key});
164             }
165             }
166            
167             sub release
168             {
169 0     0 1   my ($self) = @_;
170            
171 0           my @tofree = values %$self;
172 0           %$self = ();
173            
174 0           while(my $item = shift @tofree)
175             {
176 0   0       my $ref = ref($item) || next; # common case: value is not reference
177 0 0         if(UNIVERSAL::can($item, 'release'))
    0          
    0          
178             {
179 0           $item->release();
180             }
181             elsif($ref eq 'ARRAY')
182             {
183 0           push @tofree, @$item;
184             }
185             elsif(UNIVERSAL::isa($ref, 'HASH'))
186             {
187 0           release($item);
188             }
189             }
190            
191             }
192            
193             =head2 $r->val
194            
195             Returns the val of this object or reads the object and then returns its value.
196            
197             Note that all direct subclasses *must* make their own versions of this subroutine
198             otherwise we could be in for a very deep loop!
199            
200             =cut
201            
202             sub val
203             {
204 0     0 1   my ($self) = @_;
205            
206 0 0         $self->{' parent'}->read_obj(@_)->val unless ($self->{' realised'});
207             }
208            
209             =head2 $r->realise
210            
211             Makes sure that the object is fully read in, etc.
212            
213             =cut
214            
215             sub realise
216 0 0   0 1   { $_[0]->{' realised'} ? $_[0] : $_[0]->{' parent'}->read_obj(@_); }
217            
218             =head2 $r->outobjdeep($fh, $pdf)
219            
220             If you really want to output this object, then you must need to read it first.
221             This also means that all direct subclasses must subclass this method or loop forever!
222            
223             =cut
224            
225             sub outobjdeep
226             {
227 0     0 1   my ($self, $fh, $pdf, %opts) = @_;
228            
229 0 0         $self->{' parent'}->read_obj($self)->outobjdeep($fh, $pdf,%opts) unless ($self->{' realised'});
230             }
231            
232             sub outxmldeep
233             {
234 0     0 0   my ($self, $fh, $pdf, %opts) = @_;
235            
236 0 0         $self->{' parent'}->read_obj($self)->outxmldeep($fh, $pdf,%opts) unless ($self->{' realised'});
237             }
238            
239            
240             =head2 $r->outobj($fh)
241            
242             If this is a full object then outputs a reference to the object, otherwise calls
243             outobjdeep to output the contents of the object at this point.
244            
245             =cut
246            
247             sub outobj
248             {
249 0     0 1   my ($self, $fh, $pdf, %opts) = @_;
250            
251 0 0         if (defined $pdf->{' objects'}{$self->uid})
252 0           { $fh->printf("%d %d R", @{$pdf->{' objects'}{$self->uid}}[0..1]); }
  0            
253             else
254 0           { $self->outobjdeep($fh, $pdf, %opts); }
255             }
256            
257             sub outxml
258             {
259 0     0 0   my ($self, $fh, $pdf, %opts) = @_;
260            
261 0 0         if (defined $pdf->{' objects'}{$self->uid})
262 0           { $opts{-xmlfh}->printf("", @{$pdf->{' objects'}{$self->uid}}[0..1]); }
  0            
263             else
264 0           { $self->outxmldeep($fh, $pdf, %opts); }
265             }
266            
267            
268             =head2 $r->elementsof
269            
270             Abstract superclass function filler. Returns self here but should return
271             something more useful if an array.
272            
273             =cut
274            
275             sub elementsof
276             {
277 0     0 1   my ($self) = @_;
278            
279 0 0         if ($self->{' realised'})
280 0           { return ($self); }
281             else
282 0           { return $self->{' parent'}->read_obj($self)->elementsof; }
283             }
284            
285            
286             =head2 $r->empty
287            
288             Empties all content from this object to free up memory or to be read to pass
289             the object into the free list. Simplistically undefs all instance variables
290             other than object number and generation.
291            
292             =cut
293            
294             sub empty
295             {
296 0     0 1   my ($self) = @_;
297 0           my ($k);
298            
299 0           for $k (keys %$self)
300 0 0         { undef $self->{$k} unless $inst{$k}; }
301 0           $self;
302             }
303            
304            
305             =head2 $r->merge($objind)
306            
307             This merges content information into an object reference place-holder.
308             This occurs when an object reference is read before the object definition
309             and the information in the read data needs to be merged into the object
310             place-holder
311            
312             =cut
313            
314             sub merge
315             {
316 0     0 1   my ($self, $other) = @_;
317 0           my ($k);
318            
319 0           for $k (keys %$other)
320 0 0         { $self->{$k} = $other->{$k} unless $inst{$k}; }
321 0           $self->{' realised'} = 1;
322 0           bless $self, ref($other);
323             }
324            
325            
326             =head2 $r->is_obj($pdf)
327            
328             Returns whether this object is a full object with its own object number or
329             whether it is purely a sub-object. $pdf indicates which output file we are
330             concerned that the object is an object in.
331            
332             =cut
333            
334             sub is_obj
335 0     0 1   { defined $_[1]->{' objects'}{$_[0]->uid}; }
336            
337            
338             =head2 $r->copy($pdf, $res)
339            
340             Returns a new copy of this object. The object is assumed to be some kind
341             of associative array and the copy is a deep copy for elements which are
342             not PDF objects, according to $pdf, and shallow copy for those that are.
343             Notice that calling C on an object forces at least a one level
344             copy even if it is a PDF object. The returned object loses its PDF
345             object status though.
346            
347             If $res is defined then the copy goes into that object rather than creating a
348             new one. It is up to the caller to bless $res, etc. Notice that elements from
349             $self are not copied into $res if there is already an entry for them existing
350             in $res.
351            
352             =cut
353            
354             sub copy
355             {
356 0     0 1   my ($self, $pdf, $res) = @_;
357 0           my ($k);
358            
359 0 0         unless (defined $res)
360             {
361 0           $res = {};
362 0           bless $res, ref($self);
363             }
364 0           foreach $k (keys %$self)
365             {
366 0 0         next if $inst{$k};
367 0 0         next if defined $res->{$k};
368 0 0 0       if (UNIVERSAL::can($self->{$k}, "is_obj") && !$self->{$k}->is_obj($pdf))
369 0           { $res->{$k} = $self->{$k}->copy($pdf); }
370             else
371 0           { $res->{$k} = $self->{$k}; }
372             }
373 0           $res;
374             }
375            
376             1;
377