Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re: PDF::API2 - issues with "delete()" and "title()" methods in Outline.pm

by vr (Curate)
on Sep 03, 2022 at 13:54 UTC ( [id://11146658]=note: print w/replies, xml ) Need Help??


in reply to PDF::API2 - issues with "delete()" and "title()" methods in Outline.pm

Update. PDF::API2 supports incremental PDF modification only, raw file size can only grow, comparing "snapshots" is useless. Modified objects must be marked as such, so they'll be "slapped" after original %%EOF on save. That, mostly, is what patch does (plus a few more things), all "setter" methods should include $self->{' api'}->{'pdf'}->out_obj($self);, and/or similar line if parent/siblings are modified. I stopped patching half way, now I see your particular intent was to change bookmark titles, then patch title setter too, it'll work then. Note PDF::API2::Outline::outline always adds a new descendant to invocant; PDF::API2::outline is different.

Line added to "main" module API2.pm is lazy way to ensure objects are re-blessed, so that e.g. $pdf->outline->first->delete won't boom. Two lines commented-out in patch look harmless but useless to me: parent method never called as setter, deleting ' children' array achieves nothing. + See modified PDF content in OP, object number is skipped, it's just not tidy, I wonder if it always was this way. These latter comments are for maintainer (Steve?) if they are interested.

__________

(PDF::API2... patch and fix and patch again). Below there are patches for 2 files in distribution, and your modified test program which produces four PDF files with expected content I think. I'll add later to this node as to why your tests as designed make no sense and why it's only "demo" patch, I gave up patching further because out of time, only your immediate test files are fixed.

--- C:\berrybrew\strawberry-perl-5.32.1.1-64bit-PDL\perl\site\lib\PDF\ +API2.pm.backup Wed Dec 8 07:53:45 2021 +++ C:\berrybrew\strawberry-perl-5.32.1.1-64bit-PDL\perl\site\lib\PDF\ +API2.pm Sat Sep 3 13:36:58 2022 @@ -824,6 +824,7 @@ bless $obj, 'PDF::API2::Outlines'; $obj->{' api'} = $self; weaken $obj->{' api'}; + $obj->count(); } else { $obj = PDF::API2::Outlines->new($self); --- C:\berrybrew\strawberry-perl-5.32.1.1-64bit-PDL\perl\site\lib\PDF\ +API2\Outline.pm.backup Wed Dec 8 07:53:45 2021 +++ C:\berrybrew\strawberry-perl-5.32.1.1-64bit-PDL\perl\site\lib\PDF\ +API2\Outline.pm Sat Sep 3 16:23:35 2022 @@ -90,25 +90,25 @@ if ($count) { $self->{'Count'} = PDFNum($self->is_open() ? $count : -$count +); } + else { + delete $self->{'Count'} + } return $count; } sub _load_children { my $self = shift(); + $self->{' children'} = []; my $item = $self->{'First'}; - return unless $item; - $item->realise(); - bless $item, __PACKAGE__; - - push @{$self->{' children'}}, $item; - while ($item->next()) { - $item = $item->next(); + + while ($item) { $item->realise(); bless $item, __PACKAGE__; + $item->{' api'} = $self->{' api'}; push @{$self->{' children'}}, $item; + $item = $item->next() } - return $self; } =head3 first @@ -121,8 +121,10 @@ sub first { my $self = shift(); - if (defined $self->{' children'} and defined $self->{' children'} +->[0]) { - $self->{'First'} = $self->{' children'}->[0]; + if (exists $self->{' children'}) { + $self->{'First'} = @{$self->{' children'}} + ? $self->{' children'}[0] + : undef } return $self->{'First'}; } @@ -137,8 +139,10 @@ sub last { my $self = shift(); - if (defined $self->{' children'} and defined $self->{' children'} +->[-1]) { - $self->{'Last'} = $self->{' children'}->[-1]; + if (exists $self->{' children'}) { + $self->{'Last'} = @{$self->{' children'}} + ? $self->{' children'}[-1] + : undef } return $self->{'Last'}; } @@ -154,7 +158,7 @@ sub parent { my $self = shift(); - $self->{'Parent'} = shift() if defined $_[0]; +# $self->{'Parent'} = shift() if defined $_[0]; return $self->{'Parent'}; } @@ -167,8 +171,11 @@ =cut sub prev { - my $self = shift(); - $self->{'Prev'} = shift() if defined $_[0]; + my ($self, $other) = @_; + if ($other) { + $self->{'Prev'} = $other; + $self->{' api'}{'pdf'}->out_obj($self); + } return $self->{'Prev'}; } @@ -181,8 +188,11 @@ =cut sub next { - my $self = shift(); - $self->{'Next'} = shift() if defined $_[0]; + my ($self, $other) = @_; + if ($other) { + $self->{'Next'} = $other; + $self->{' api'}{'pdf'}->out_obj($self); + } return $self->{'Next'}; } @@ -200,7 +210,9 @@ my $self = shift(); my $child = PDF::API2::Outline->new($self->{' api'}, $self); - $self->{' children'} //= []; + + $self->_load_children() unless exists $self->{' children'}; + $child->prev($self->{' children'}->[-1]) if @{$self->{' children' +}}; $self->{' children'}->[-1]->next($child) if @{$self->{' children' +}}; push @{$self->{' children'}}, $child; @@ -208,6 +220,7 @@ $self->{' api'}->{'pdf'}->new_obj($child); } + $self->{' api'}->{'pdf'}->out_obj($self); return $child; } @@ -268,6 +281,7 @@ $item = $item->next(); push @{$self->{' children'}}, $item; } + $self->{' api'}->{'pdf'}->out_obj($self); return $self; } @@ -291,7 +305,8 @@ my $siblings = $self->parent->{' children'}; @$siblings = grep { $_ ne $self } @$siblings; - delete $self->parent->{' children'} unless $self->parent->has_chi +ldren(); +# delete $self->parent->{' children'} unless $self->parent->has_ch +ildren(); + $self->{' api'}->{'pdf'}->out_obj($self->parent); return; }

############

#!/usr/bin/perl use 5.032; use warnings; use strict; use PDF::API2; my ($stringy_bare_pdf, $stringy_outline_pdf); BARE_PDF: { my $pdf = PDF::API2->new(-compress => 0); my $page1 = $pdf->page(); $pdf->save('bare.pdf'); } OUTLINE: { my $pdf = PDF::API2->new(-compress => 0); my $page1 = $pdf->page(); my $outlines = $pdf->outlines(); my $outline = $outlines->outline(); $outline->title('Test Outline 1'); $outline->dest(1); $stringy_outline_pdf = $pdf->to_string(); open my $fh, '>', 'outline.pdf' or die; binmode $fh; print $fh $stringy_outline_pdf; close $fh; } DELETE_OUTLINE: { my $pdf = PDF::API2->from_string($stringy_outline_pdf, -compress = +> 0) or die $!; my $root = $pdf->outlines(); my $outline = $root->first(); $outline->delete(); $pdf->save('outline_deleted.pdf'); } MODIFY_OUTLINE: { my $pdf = PDF::API2->from_string($stringy_outline_pdf, -compress = +> 0) or die $!; my $root = $pdf->outlines(); my $outline = $root->outline(); $outline->title('Test Outline 2'); $outline->dest(1); $pdf->save('outline_modified.pdf'); }

Replies are listed 'Best First'.
Re^2: PDF::API2 - issues with "delete()" and "title()" methods in Outline.pm
by ateague (Monk) on Sep 06, 2022 at 17:05 UTC

    Thank you very much for the clarification and the patches

    So my code to rename and delete the outlines was correct, but at the end of the day, unpatched PDF::API2 version 2.043 does not currently support renaming or completely deleting existing outlines in a PDF.

      Example test relies on incorrect use of PDF::API2::Outline::outline despite its documentation, but code unshown may in fact be correct if bookmark tree is traversed with other (too verbose for example test?) -- i.e. First/Next/Prev/Last -- methods.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11146658]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (8)
As of 2024-04-19 13:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found