Add-On Named destinations
Informations
Author:Jan SlabonLicense: FPDF
Description
This extension allows to use and define named destinations in a PDF document.If the $link parameter of
SetLink()
is prefixed with a "#", it will be registered
as a named destination.If a $link parameter of
Link()
, Cell()
, Write()
, ... is
prefixed with a "#", it will be treated as a named destination target.
Source
<?php
require_once('fpdf.php');
class PDF_NamedDestinations extends FPDF
{
protected $namedDestinations = array();
protected $n_namedDestinations;
function __construct($orientation='P', $unit='mm', $size='A4')
{
if(!defined('FPDF::VERSION'))
$this->Error('Unsupported FPDF version');
parent::__construct($orientation, $unit, $size);
}
function SetLink($link, $y = 0, $page = -1)
{
if (strpos($link, '#') !== 0) {
parent::SetLink($link);
} else {
// Set destination of internal link
if ($y == -1)
$y = $this->y;
if ($page == -1)
$page = $this->page;
$this->namedDestinations[substr($link, 1)] = array($page, $y);
}
}
function _putnamedDestinations()
{
if ($this->DefOrientation == 'P') {
$hPt = $this->DefPageSize[1] * $this->k;
} else {
$hPt = $this->DefPageSize[0] * $this->k;
}
$names = array();
foreach ($this->namedDestinations as $name => $namedDestinations) {
$h = isset($this->PageInfo[$namedDestinations[0]]['size']) ? $this->PageInfo[$namedDestinations[0]]['size'][1] : $hPt;
$this->_newobj();
$this->_put(sprintf('[%d 0 R /XYZ 0 %.2F null]', $this->PageInfo[$namedDestinations[0]]['n'], $h - $namedDestinations[1] * $this->k));
$this->_put('endobj');
$names[$name] = $this->n;
}
ksort($names, SORT_STRING);
$this->_newobj();
$this->n_namedDestinations = $this->n;
$this->_put('<<');
$s = array();
foreach ($names as $name => $n)
$s[] = $this->_textstring((string)$name) . ' ' . $n . ' 0 R';
$this->_put('/Names [' . implode(' ', $s) . ']');
$this->_put('>>');
$this->_put('endobj');
}
function _putresources()
{
parent::_putresources();
if(!empty($this->namedDestinations))
$this->_putnamedDestinations();
}
function _putcatalog()
{
parent::_putcatalog();
if(!empty($this->namedDestinations))
$this->_put('/Names <</Dests '.$this->n_namedDestinations.' 0 R>>');
}
protected function _putlinks($n)
{
foreach($this->PageLinks[$n] as $pl)
{
$this->_newobj();
$rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0]+$pl[2], $pl[1]-$pl[3]);
$s = '<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
if(is_string($pl[4])) {
if (strpos($pl[4], '#') === 0) {
$s .= '/A <</S /GoTo /D ' . $this->_textstring(substr($pl[4], 1)) . '>>>>';
} else {
$s .= '/A <</S /URI /URI ' . $this->_textstring($pl[4]) . '>>>>';
}
} else {
$l = $this->links[$pl[4]];
if(isset($this->PageInfo[$l[0]]['size']))
$h = $this->PageInfo[$l[0]]['size'][1];
else
$h = ($this->DefOrientation=='P') ? $this->DefPageSize[1]*$this->k : $this->DefPageSize[0]*$this->k;
$s .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>', $this->PageInfo[$l[0]]['n'], $h-$l[1]*$this->k);
}
$this->_put($s);
$this->_put('endobj');
}
}
}
Example
<?php
require_once('named_destinations.php');
$pdf = new PDF_NamedDestinations();
$pdf->AddPage();
$pdf->SetFont('Arial', '', 14);
$pdf->SetLink('#page-1');
$pdf->Write(10, 'Link to page 2', '#page-2');
$pdf->AddPage();
$pdf->SetLink('#page-2');
$pdf->Write(10, 'Link to page 1', '#page-1');
$pdf->Output();
?>