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 )