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 )