CAM-PDF
view release on metacpan or search on metacpan
lib/CAM/PDF.pm view on Meta::CPAN
my $val = $objnode->{value};
if (! ref $val)
{
die "Obj data is not a ref! ($val)";
}
my $stream;
if ($val->{type} eq 'dictionary' && exists $val->{value}->{StreamData})
{
$stream = $val->{value}->{StreamData}->{value};
my $length = length $stream;
my $l = $val->{value}->{Length} || $val->{value}->{L};
my $oldlength = $self->getValue($l);
if ($length != $oldlength)
{
$val->{value}->{Length} = CAM::PDF::Node->new('number', $length, $objnode->{objnum}, $objnode->{gennum});
delete $val->{value}->{L};
}
$val->{value}->{StreamDataDone} = 1;
}
my $str = $self->writeAny($val);
if (defined $stream)
{
$stream = $self->{crypt}->encrypt($self, $stream, $objnode->{objnum}, $objnode->{gennum});
$str .= "\nstream\n" . $stream . 'endstream';
}
return "obj\n$str\nendobj\n";
}
######################################################################
=back
=head2 Document Traversing
=over
=item $doc->traverse($dereference, $node, $callbackfunc, $callbackdata)
Recursive traversal of a PDF data structure.
In many cases, it's useful to apply one action to every node in an
object tree. The routines below all use this traverse() function.
One of the most important parameters is the first: the C<$dereference>
boolean. If true, the traversal follows reference Nodes. If false,
it does not descend into reference Nodes.
Optionally, you can pass in a hashref as a final argument to reduce
redundant traversing across multiple calls. Just pass in an empty
hashref the first time and pass in the same hashref each time. See
C<changeRefKeys()> for an example.
=cut
sub traverse
{
my $self = shift;
my $deref = shift;
my $startnode = shift;
my $func = shift;
my $funcdata = shift;
my $traversed = shift || {};
my @stack = ($startnode);
my $i = 0;
while ($i < @stack)
{
my $objnode = $stack[$i++];
$self->$func($objnode, $funcdata);
my $type = $objnode->{type};
my $val = $objnode->{value};
if ($type eq 'object')
{
# Shrink stack periodically
splice @stack, 0, $i;
$i = 0;
# Mark object done
if ($objnode->{objnum})
{
$traversed->{$objnode->{objnum}} = 1;
}
}
push @stack, $type eq 'dictionary' ? values %{$val}
: $type eq 'array' ? @{$val}
: $type eq 'object' ? $val
: $type eq 'reference'
&& $deref
&& !exists $traversed->{$val} ? $self->dereference($val)
: ();
}
return;
}
# decodeObject and decodeAll differ from each other like this:
#
# decodeObject JUST decodes a single stream directly below the object
# specified by the objnum
#
# decodeAll descends through a whole object tree (following
# references) decoding everything it can find
=item $doc->decodeObject($objectnum)
I<For INTERNAL use>
Remove any filters (like compression, etc) from a data stream
indicated by the object number.
=cut
sub decodeObject
{
my $self = shift;
my $objnum = shift;
my $objnode = $self->dereference($objnum);
$self->decodeOne($objnode->{value}, 1);
return;
}
=item $doc->decodeAll($object)
I<For INTERNAL use>
Remove any filters from any data stream in this object or any object
( run in 1.183 second using v1.01-cache-2.11-cpan-6aa56a78535 )