Skip Menu |

This queue is for tickets about the PDF-API2 CPAN distribution.

Report information
The Basics
Id: 117942
Status: open
Priority: 0/
Queue: PDF-API2

People
Owner: Nobody in particular
Requestors: jv [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 2.028
Fixed in: (no value)



Subject: Add file attachment annotations
The following patch against 2.028 adds file attachment annotations.
Subject: PDF-API2-2.028-Annotation-attachment.patch
*** PDF/API2/Annotation.pm~ 2016-06-09 00:24:09.000000000 +0200 --- PDF/API2/Annotation.pm 2016-09-18 17:14:50.732315208 +0200 *************** *** 204,209 **** --- 204,254 ---- return($self); } + =item $ant->fileattachment $file, %opts + + Defines the annotation as a file attachment with file $file and + options %opts (-rect, -border, -content (type), -icon (name)). + + =cut + + sub fileattachment { + my ( $self, $file, %opts ) = @_; + + # https://books.google.nl/books?id=1TpDgwNGIK8C&pg=PA97&lpg=PA97&dq=pdf+embeddedfile+fileattachment&source=bl&ots=oGyUXkDBUT&sig=aftnbcBQlkOwcHLPdYxE4pcBIP4&hl=en&sa=X&ved=0ahUKEwjW2vnmjIrPAhXIfxoKHVsACTAQ6AEIQjAF#v=onepage&q=pdf%20embeddedfile%20fileattachment&f=false + # + # /Annots + # [ << /FS << /EF << /F 8 0 R >> /F (attachment.txt) /Type /F >> + # /Subtype /FileAttachment + # /Contents (attachment.txt) + # /Rect [ 18 796 45 823 ] + # >> ] + + my $contentype = delete $opts{-content}; + my $icontype = delete $opts{-icon}; + + $self->{Subtype} = PDFName('FileAttachment'); + if ( is_utf8($file)) { + # URI must be 7-bit ascii + utf8::downgrade($file); + } + $self->{Contents} = PDFStr($file); + $self->{Name} = PDFName( $icontype || 'None'); + + $self->{FS} = PDFDict(); + $self->{FS}->{F} = PDFStr($file); + $self->{FS}->{Type} = PDFName('F'); + $self->{FS}->{EF} = PDFDict($file); + $self->{FS}->{EF}->{F} = PDFDict($file); + $self->{' apipdf'}->new_obj($self->{FS}->{EF}->{F}); + $self->{FS}->{EF}->{F}->{Type} = PDFName('EmbeddedFile'); + $self->{FS}->{EF}->{F}->{SubType} = PDFName($contentype) if $contentype; + $self->{FS}->{EF}->{F}->{' streamfile'}=$file; + + $self->rect(@{$opts{-rect}}) if (defined $opts{-rect}); + $self->border(@{$opts{-border}}) if (defined $opts{-border}); + return($self); + } + =item $ant->rect $llx, $lly, $urx, $ury Sets the rectangle of the annotation.
Merged, thanks. This will be in v2.031.
On Thu Nov 03 19:16:32 2016, SSIMMS wrote: Show quoted text
> Merged, thanks. This will be in v2.031.
... with a couple of changes: - renamed fileattachment to file_attachment - renamed -content to -type
I forgot about this one... I've done a lot of development since and I have attached a much improved version. This version has proper appearance handling, and handles custom icons. Show quoted text
> - renamed fileattachment to file_attachment
"file_attachment" means to me that it is going to file away (action) an attachment. "fileattachment" is a noun, which corresponds better to what it is. At least I think so, but it is probably not worth the discussion.
Subject: fileattachment.pl
sub fileattachment { my ( $self, $file, %opts ) = @_; my $icon = $opts{-icon} || 'PushPin'; my @r = @{ $opts{-rect} } if defined $opts{-rect}; my @b = @{ $opts{-border} } if defined $opts{-border}; $self->{Subtype} = PDFName('FileAttachment'); if ( is_utf8($file)) { # URI must be 7-bit ascii utf8::downgrade($file); } # 9 0 obj << # /Type /Annot # /Subtype /FileAttachment # /Name /PushPin # /C [ 1 1 0 ] # /Contents (test.txt) # /FS << # /Type /F # /EF << /F 10 0 R >> # /F (test.txt) # >> # /Rect [ 100 100 200 200 ] # /Border [ 0 0 1 ] # >> endobj # # 10 0 obj << # /Type /EmbeddedFile # /Length ... # >> stream # ... # endstream endobj $self->{Contents} = PDFStr($file); # Name will be ignored if there is an AP. $self->{Name} = PDFName($icon) unless ref($icon); # $self->{F} = PDFNum(0b0); $self->{C} = PDFArray( map { PDFNum($_) } 1, 1, 0 ); # The File Specification. $self->{FS} = PDFDict(); $self->{FS}->{F} = PDFStr($file); $self->{FS}->{Type} = PDFName('F'); $self->{FS}->{EF} = PDFDict($file); $self->{FS}->{EF}->{F} = PDFDict($file); $self->{' apipdf'}->new_obj($self->{FS}->{EF}->{F}); $self->{FS}->{EF}->{F}->{Type} = PDFName('EmbeddedFile'); $self->{FS}->{EF}->{F}->{' streamfile'} = $file; # Set the annotation rectangle and border. $self->rect(@r) if @r; $self->border(@b) if @b; # Set the appearance. $self->appearance($icon, %opts) if $icon; return($self); } sub appearance { my ( $self, $icon, %opts ) = @_; return unless $self->{Subtype}->val eq 'FileAttachment'; my @r = @{ $opts{-rect}} if defined $opts{-rect}; die "insufficient -rect parameters to annotation->appearance( ) " unless(scalar @r == 4); # Handle custom icon type 'None'. if ( $icon eq 'None' ) { # It is not clear what viewers will do, so provide an # appearance dict with no graphics content. # 9 0 obj << # ... # /AP << /D 11 0 R /N 11 0 R /R 11 0 R >> # ... # >> # 11 0 obj << # /BBox [ 0 0 100 100 ] # /FormType 1 # /Length 6 # /Matrix [ 1 0 0 1 0 0 ] # /Resources << # /ProcSet [ /PDF ] # >> # >> stream # 0 0 m # endstream endobj $self->{AP} = PDFDict(); my $d = PDFDict(); $self->{' apipdf'}->new_obj($d); $d->{FormType} = PDFNum(1); $d->{Matrix} = PDFArray( map { PDFNum($_) } 1, 0, 0, 1, 0, 0 ); $d->{Resources} = PDFDict(); $d->{Resources}->{ProcSet} = PDFArray( map { PDFName($_) } qw(PDF)); $d->{BBox} = PDFArray( map { PDFNum($_) } 0, 0, $r[2]-$r[0], $r[3]-$r[1] ); $d->{' stream'} = "0 0 m"; $self->{AP}->{N} = $d; # normal appearance # Should default to N, but be sure. $self->{AP}->{R} = $d; # Rollover $self->{AP}->{D} = $d; # Down } # Handle custom icon. elsif ( ref $icon ) { # Provide an appearance dict with the image. # 9 0 obj << # ... # /AP << /D 11 0 R /N 11 0 R /R 11 0 R >> # ... # >> # 11 0 obj << # /BBox [ 0 0 1 1 ] # /FormType 1 # /Length 13 # /Matrix [ 1 0 0 1 0 0 ] # /Resources << # /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] # /XObject << /PxCBA 7 0 R >> # >> # >> stream # q /PxCBA Do Q # endstream endobj $self->{AP} = PDFDict(); my $d = PDFDict(); $self->{' apipdf'}->new_obj($d); $d->{FormType} = PDFNum(1); $d->{Matrix} = PDFArray( map { PDFNum($_) } 1, 0, 0, 1, 0, 0 ); $d->{Resources} = PDFDict(); $d->{Resources}->{ProcSet} = PDFArray( map { PDFName($_) } qw(PDF Text ImageB ImageC ImageI)); $d->{Resources}->{XObject} = PDFDict(); my $im = $icon->{Name}->val; $d->{Resources}->{XObject}->{$im} = $icon; # Note that the image is scaled to one unit in user space. $d->{BBox} = PDFArray( map { PDFNum($_) } 0, 0, 1, 1 ); $d->{' stream'} = "q /$im Do Q"; $self->{AP}->{N} = $d; # normal appearance # Should default to N, but be sure. $self->{AP}->{R} = $d; # Rollover $self->{AP}->{D} = $d; # Down } return $self; }
I'm about to do a release, so I've backed out your original patch and my changes, and am switching the status back to "open" so I can review your new patch in more detail later.
Any progress?
Subject: Re: [rt.cpan.org #117942] Add file attachment annotations
Date: Mon, 11 Sep 2017 09:49:57 +0200
To: bug-PDF-API2 [...] rt.cpan.org
From: Johan Vromans <jvromans [...] squirrel.nl>
On Thu, 26 Jan 2017 13:20:37 -0500, "Steve Simms via RT" <bug-PDF-API2@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=117942 > > > I'm about to do a release, so I've backed out your original patch and my > changes, and am switching the status back to "open" so I can review your > new patch in more detail later.
Please find attached the most recent version of the fileattachment method. This one has been in production for some six months and may be considered pretty stable and solid. Regards, Johan

Message body is not shown because sender requested not to inline it.

FYI, (code based on) this is added to PDF::Builder