PDF-Builder
view release on metacpan or search on metacpan
lib/PDF/Builder/NamedDestination.pm view on Meta::CPAN
$dest = PDF::Builder::NamedDestination->new($pdf);
$dest->goto($page, 'fit');
Finally, however you created the Named Destination, its action, and its page
fit, you need to tell the system
to insert an entry into the Named Destination directory:
$pdf->named_destination('Dests', "foo", $dest);
This is where you actually I<name> the destination. Consult
L<PDF::Builder/named_destination> and L<PDF::Builder::Docs/Page Fit Options>
for more information.
=back
=cut
sub new {
my $class = shift;
my $pdf = shift;
$pdf = $pdf->{'pdf'} if $pdf->isa('PDF::Builder');
my $self = $class->SUPER::new($pdf);
$pdf->new_obj($self);
if (@_) { # leftover arguments? page_obj + fit + data
my $page = shift;
my %opts = $self->list2hash(@_); # may be empty
$self->{'S'} = PDFName('GoTo'); # default
$self->{'D'} = $self->dest($page, %opts);
}
return $self;
}
# Note: new_api() removed in favor of new():
# new_api($api, ...) replace with new($api->{'pdf'}, ...)
# Appears to be added back in, PDF::API2 2.042
sub new_api {
my ($class, $api2) = @_;
warnings::warnif('deprecated',
'Call to deprecated method new_api, replace with new');
my $destination = $class->new($api2);
return $destination;
}
# returns an anonymous array with page object and page fit info
sub dest {
my ($self, $page, @args) = @_;
# $page is either 1. a page object (from goto)
# 2. a formatted page number (from pdf)
# 3. a named destination string (from pdf)
my %opts = $self->list2hash(@args); # may be empty!
my ($location, @arglist, $ptr);
my %arg_counts = (
# key = location given by user
# [0] = required number of arguments, [1] = name for PDF
'xyz' => [3, 'XYZ' ], # s/b array ref
'fit' => [0, 'Fit' ], # 1 (scalar) ignored
'fith' => [1, 'FitH' ], # s/b scalar
'fitv' => [1, 'FitV' ], # s/b scalar
'fitr' => [4, 'FitR' ], # s/b array ref
'fitb' => [0, 'FitB' ], # 1 (scalar) ignored
'fitbh' => [1, 'FitBH'], # s/b scalar
'fitbv' => [1, 'FitBV'], # s/b scalar
);
# do any of the options contain a fit location, and if so, the right
# number of data values (put into @arglist)?
foreach (keys %arg_counts) {
if (defined $opts{$_}) {
# this fit $_ is given in the options
$location = $_;
if (ref($opts{$_}) eq 'ARRAY') {
# it's an anonymous array with presumably 3 or 4 elements
@arglist = @{$opts{$_}};
} else {
# it's a scalar value
@arglist = ($opts{$_});
}
}
}
if (!defined $location) {
# no fit location given. default to xyz undef undef undef
$location = 'xyz';
@arglist = (undef, undef, undef);
}
if ($location eq 'fit' || $location eq 'fitb') {
# these two locations take no location data, and hash would contain
# a dummy value
@arglist = ();
}
# check number of arguments given for location
if (@arglist > $arg_counts{$location}->[0]) {
carp "Too many items given for '$location' location. Excess discarded.";
splice(@arglist, $arg_counts{$location}->[0]);
} elsif (@arglist < $arg_counts{$location}->[0]) {
croak "Too few items given for '$location' location.";
}
if (ref($page) ne '') {
# it's an object
} elsif ($page =~ /^\d+$/) {
# it's a number
$page = PDFNum($page);
} else {
# is a string, and therefore a Named Destination (?) shouldn't see here
croak "string (Named Destination) passed to dest()";
}
return _array($page, $arg_counts{$location}->[1], @arglist);
}
# internal utilities
sub _array {
my $page = shift();
my $location = shift();
lib/PDF/Builder/NamedDestination.pm view on Meta::CPAN
sub url { return uri(@_); } ## no critic
sub uri {
my ($self, $uri, %opts) = @_;
# currently no options supported
$self->{'S'} = PDFName('URI');
$self->{'URI'} = PDFString($uri, 'u');
return $self;
}
=head3 launch, file
$dest->launch($file)
=over
Defines the destination as launch-file with filepath C<$file> and
page-fit options %opts. The target application is run. Note that this is
B<not> a PDF I<or> a browser file -- it is a usually a local application,
such as a text editor or photo viewer.
There are no options available.
To go to a Named Destination and then immediately launch a local application
is unusual, but possible.
B<Alternate name:> C<file>
Originally this method was C<file>, but PDF::API2 changed the name
to C<launch> to match the PDF command. "file" is retained for compatibility.
=back
=cut
sub file { return launch(@_); } ## no critic
sub launch {
my ($self, $file, %opts) = @_;
# currently no options supported
$self->{'S'} = PDFName('Launch');
$self->{'F'} = PDFString($file, 'u');
return $self;
}
# return an array as a hash, with key leading -'s removed
# assumes possible hash elements already as scalars or arrayrefs
# leading element(s) may be a list, turn it into one name=>[list]
sub list2hash {
my ($self, @args) = @_;
# nothing passed in?
if (!@args) { return @args; }
my %arg_counts = (
# key = location given by user
# value = required number of arguments
'xyz' => 3,
'fit' => 0,
'fith' => 1,
'fitv' => 1,
'fitr' => 4,
'fitb' => 0,
'fitbh' => 1,
'fitbv' => 1,
);
my $location;
# try to match first element as location name
if ($args[0] =~ /^-(.*)$/) {
$args[0] = $1;
}
my $num_args = scalar(@args);
my $match = -1;
my @keylist = keys %arg_counts;
for (my $i=0; $i<@keylist; $i++) {
if ($args[0] eq $keylist[$i]) {
$match = $arg_counts{$keylist[$i]};
# note that if hash element and not list, minimum is 1 data value
last;
}
}
if ($match > -1) {
# first element is a location value, but is it a hash element or a list?
$location = $args[0];
if (ref($args[1]) eq 'ARRAY' || $arg_counts{$location} == 1) {
# location and args supplied as hash element OR
# single value hash element or list, so entire array should be hash
} elsif ($arg_counts{$location} == 3) {
# 3 elements should follow location, so as long as none
# are arrayrefs, we should be good. already checked that is not
# one arrayref for element
my @vals;
for (my $i=0; $i<3; $i++) {
$vals[$i] = $args[$i+1];
if (ref($vals[$i]) eq '') { next; }
croak "list of elements contains non-scalars in list2hash()!";
}
splice(@args, 0, 4);
unshift @args, ($location, \@vals);
} elsif ($arg_counts{$location} == 4) {
# 4 elements should follow location, so as long as none
# are arrayrefs, we should be good. already checked that is not
# one arrayref for element
my @vals;
for (my $i=0; $i<4; $i++) {
$vals[$i] = $args[$i+1];
if (ref($vals[$i]) eq '') { next; }
croak "list of elements contains non-scalars in list2hash()!";
}
splice(@args, 0, 5);
unshift @args, ($location, \@vals);
} elsif ($arg_counts{$location} == 0) {
( run in 2.231 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )