Skip to content

Commit

Permalink
Add support for Layers, Links and Destinations
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolaasuni committed Aug 22, 2024
1 parent 8b2b158 commit a612b13
Show file tree
Hide file tree
Showing 5 changed files with 272 additions and 77 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.0.71
8.0.72
70 changes: 63 additions & 7 deletions examples/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,8 @@

$page09 = $pdf->page->add();

$dest_barcode_page = $pdf->setNamedDestination('barcode');

$pdf->graph->setPageWidth($page09['width']);
$pdf->graph->setPageHeight($page09['height']);

Expand Down Expand Up @@ -1011,6 +1013,9 @@

$page11 = $pdf->page->add();

// Add an internal link to this page
$page11_link = $pdf->addInternalLink();

$pdf->graph->setPageWidth($page11['width']);
$pdf->graph->setPageHeight($page11['height']);

Expand Down Expand Up @@ -1067,23 +1072,19 @@
'color' => 'red',
],
);

$pdf->page->addContent($txt2);

// get the coordinates of the box containing the last added text string.
$bbox = $pdf->getLastBBox();

$aoid = $pdf->setAnnotation(
$aoid1 = $pdf->setLink(
$bbox['x'],
$bbox['y'],
$bbox['w'],
$bbox['h'],
'https://tcpdf.org',
[
'subtype' => 'Link',
]
);
$pdf->page->addAnnotRef($aoid);
$pdf->page->addAnnotRef($aoid1);

// -----------------------------------------------

Expand Down Expand Up @@ -1446,7 +1447,7 @@
$timg = $pdf->image->add('../vendor/tecnickcom/tc-lib-pdf-image/test/images/200x100_RGB.png');
$pdf->addXObjectImageID($tid, $timg);

$xcnz .= $pdf->image->getSetImage($timg, 10, 10, 80, 80, 80);
$xcnz = $pdf->image->getSetImage($timg, 10, 10, 80, 80, 80);
$pdf->addXObjectContent($tid, $xcnz);

$pdf->exitXObjectTemplate();
Expand All @@ -1465,6 +1466,61 @@

// ----------

// Layers

$pageV01 = $pdf->page->add();

$pdf->page->addContent($bfont4['out']);

$txtV1 = 'LAYERS: You can limit the visibility of PDF objects to screen or printer by using the newLayer() method.
Check the print preview of this document to display the alternative text.';
$txtboxV1 = $pdf->getTextCell($txtV1, 15, 15, 150, valign: 'T', halign: 'L');
$pdf->page->addContent($txtboxV1);

$lyr01 = $pdf->newLayer('screen', [], false, true, false);
$pdf->page->addContent($lyr01);
$txtV2 = 'This line is for display on screen only.';
$txtboxV2 = $pdf->getTextCell($txtV2, 15, 45, 150, valign: 'T', halign: 'L');
$pdf->page->addContent($txtboxV2);
$pdf->page->addContent($pdf->closeLayer());


$lyr02 = $pdf->newLayer('print', [], true, false, false);
$pdf->page->addContent($lyr02);
$txtV3 = 'This line is for print only.';
$txtboxV3 = $pdf->getTextCell($txtV3, 15, 55, 150, valign: 'T', halign: 'L');
$pdf->page->addContent($txtboxV3);
$pdf->page->addContent($pdf->closeLayer());

// Links

$txtlnk1 = $pdf->getTextCell("Link to page 11", 15, 70, 150, valign: 'T', halign: 'L');
$pdf->page->addContent($txtlnk1);
$bbox = $pdf->getLastBBox();
$lnk1 = $pdf->setLink(
$bbox['x'],
$bbox['y'],
$bbox['w'],
$bbox['h'],
$page11_link,
);
$pdf->page->addAnnotRef($lnk1);

$txtlnk2 = $pdf->getTextCell("Link dest to barcode page", 15, 80, 150, valign: 'T', halign: 'L');
$pdf->page->addContent($txtlnk2);
$bbox = $pdf->getLastBBox();
$lnk2 = $pdf->setLink(
$bbox['x'],
$bbox['y'],
$bbox['w'],
$bbox['h'],
$dest_barcode_page,
);
$pdf->page->addAnnotRef($lnk2);

// ----------


// =============================================================

// ----------
Expand Down
2 changes: 1 addition & 1 deletion src/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ abstract class Base
/**
* TCPDF version.
*/
protected string $version = '8.0.71';
protected string $version = '8.0.72';

/**
* Time is seconds since EPOCH when the document was created.
Expand Down
142 changes: 74 additions & 68 deletions src/Output.php
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@
* 'prev': int,
* 's': string,
* 't': string,
* 'u': int,
* 'u': string,
* 'x': float,
* 'y': float,
* }
Expand Down Expand Up @@ -449,11 +449,12 @@ abstract class Output extends \Com\Tecnick\Pdf\MetaInfo
*
* @var array<int, array{
* 'layer': string,
* 'lock': bool,
* 'name': string,
* 'objid': int,
* 'intent': string,
* 'print': bool,
* 'view': bool,
* 'lock': bool,
* 'objid': int,
* }>
*/
protected array $pdflayer = [];
Expand All @@ -476,14 +477,23 @@ abstract class Output extends \Com\Tecnick\Pdf\MetaInfo
* Destinations.
*
* @var array<string, array{
* 'f': bool,
* 'p': int,
* 'x': float,
* 'y': float,
* }>
*/
protected array $dests = [];

/**
* Links.
*
* @var array<string, array{
* 'p': int,
* 'y': float,
* }>
*/
protected array $links = [];

/**
* Radio Button Groups.
*
Expand All @@ -496,17 +506,6 @@ abstract class Output extends \Com\Tecnick\Pdf\MetaInfo
*/
protected array $radiobuttonGroups = [];

/**
* Links.
*
* @var array<int, array{
* 'f': bool,
* 'p': int,
* 'y': float,
* }>
*/
protected array $links = [];

/**
* Javascript block to add.
*/
Expand Down Expand Up @@ -945,15 +944,24 @@ protected function getOutOCG(): string
$oid = ++$this->pon;
$this->pdflayer[$key]['objid'] = $oid;
$out .= $oid . ' 0 obj' . "\n";
$out .= '<< /Type /OCG /Name ' . $this->getOutTextString($layer['name'], $oid, true)
. ' /Usage <<';

$out .= '<< /Type /OCG'
. ' /Name ' . $this->getOutTextString($layer['name'], $oid, true);

if (!empty($layer['intent'])) {
$out .= ' /Intent [' . $layer['intent'] . ']';
}

$out .= ' /Usage <<';
if (isset($layer['print']) && ($layer['print'] !== null)) {
$out .= ' /Print <</PrintState /' . $this->getOnOff($layer['print']) . '>>';
$out .= ' /Print << /PrintState /' . $this->getOnOff($layer['print']) . ' >>';
}
$out .= ' /View << /ViewState /' . $this->getOnOff($layer['view']) . ' >>';
// Other (not-implemented) possible /Usage entries:
// CreatorInfo, Language, Export, Zoom, User, PageElement.
$out .= ' >>'; // close /Usage

$out .= ' /View <</ViewState /' . $this->getOnOff($layer['view']) . '>>'
. ' >>'
. ' >>' . "\n"
$out .= ' >>' . "\n"
. 'endobj' . "\n";
}

Expand Down Expand Up @@ -1743,12 +1751,18 @@ protected function getOutAnnotationOptSubtypeLink(
int $oid
): string {
$out = '';
if (! empty($annot['txt']) && is_string($annot['txt'])) {
if (! empty($annot['txt'])) {
switch ($annot['txt'][0]) {
case '#': // internal destination
$out .= ' /A << /S /GoTo /D /'
. $this->encrypt->encodeNameObject(substr($annot['txt'], 1)) . '>>';
break;
case '@': // internal link ID
$l = $this->links[$annot['txt']];
$page = $this->page->getPage($l['p']);
$y = $this->toYPoints($l['y'], $page['pheight']);
$out .= sprintf(' /Dest [%u 0 R /XYZ 0 %F null]', $page['n'], $y);
break;
case '%': // embedded PDF file
$filename = basename(substr($annot['txt'], 1));
$out .= ' /A << /S /GoToE /D [0 /Fit] /NewWindow true /T << /R /C /P ' . ($pagenum - 1)
Expand Down Expand Up @@ -1790,15 +1804,8 @@ protected function getOutAnnotationOptSubtypeLink(
. $this->encrypt->escapeDataString($this->unhtmlentities($annot['txt']), $oid)
. ' >>';
}

break;
}
} elseif (! empty($this->links[$annot['txt']])) {
// internal link ID
$l = $this->links[$annot['txt']];
$page = $this->page->getPage($l['p']);
$y = $this->toYPoints($l['y'], $page['height']);
$out .= sprintf(' /Dest [%u 0 R /XYZ 0 %F null]', $page['n'], $y);
}

$hmodes = ['N', 'I', 'O', 'P'];
Expand Down Expand Up @@ -2581,49 +2588,48 @@ protected function getOutBookmarks(): string

if (! empty($outline['u'])) {
// link
if (is_string($outline['u'])) {
switch ($outline['u'][0]) {
case '#':
// internal destination
$out .= ' /Dest /' . $this->encrypt->encodeNameObject(substr($outline['u'], 1));
break;
case '%':
// embedded PDF file
$filename = basename(substr($outline['u'], 1));
$out .= ' /A << /S /GoToE /D [0 /Fit] /NewWindow true /T << /R /C /P '
. ($outline['p'] - 1)
. ' /A ' . $this->embeddedfiles[$filename]['a'] . ' >>'
. ' >>';
break;
case '*':
// embedded generic file
$filename = basename(substr($outline['u'], 1));
$jsa = 'var D=event.target.doc;var MyData=D.dataObjects;'
. 'for (var i in MyData) if (MyData[i].path=="'
. $filename . '")'
. ' D.exportDataObject( { cName : MyData[i].name, nLaunch : 2});';
$out .= ' /A <</S /JavaScript /JS '
. $this->getOutTextString($jsa, $oid, true) . '>>';
break;
default:
// external URI link
$out .= ' /A << /S /URI /URI '
. $this->encrypt->escapeDataString($this->unhtmlentities($outline['u']), $oid)
. ' >>';
break;
}
} elseif (isset($this->links[$outline['u']])) {
// internal link ID
$l = $this->links[$outline['u']];
$page = $this->page->getPage($l['p']);
$y = ($page['height'] - ($l['y'] * $this->kunit));
$out .= sprintf(' /Dest [%u 0 R /XYZ 0 %F null]', $page['n'], $y);
switch ($outline['u'][0]) {
case '#':
// internal destination
$out .= ' /Dest /' . $this->encrypt->encodeNameObject(substr($outline['u'], 1));
break;
case '@':
// internal link ID
$l = $this->links[$outline['u']];
$page = $this->page->getPage($l['p']);
$y = $this->toYPoints($l['y'], $page['pheight']);
$out .= sprintf(' /Dest [%u 0 R /XYZ 0 %F null]', $page['n'], $y);
break;
case '%':
// embedded PDF file
$filename = basename(substr($outline['u'], 1));
$out .= ' /A << /S /GoToE /D [0 /Fit] /NewWindow true /T << /R /C /P '
. ($outline['p'] - 1)
. ' /A ' . $this->embeddedfiles[$filename]['a'] . ' >>'
. ' >>';
break;
case '*':
// embedded generic file
$filename = basename(substr($outline['u'], 1));
$jsa = 'var D=event.target.doc;var MyData=D.dataObjects;'
. 'for (var i in MyData) if (MyData[i].path=="'
. $filename . '")'
. ' D.exportDataObject( { cName : MyData[i].name, nLaunch : 2});';
$out .= ' /A <</S /JavaScript /JS '
. $this->getOutTextString($jsa, $oid, true) . '>>';
break;
default:
// external URI link
$out .= ' /A << /S /URI /URI '
. $this->encrypt->escapeDataString($this->unhtmlentities($outline['u']), $oid)
. ' >>';
break;
}
} else {
// link to a page
$page = $this->page->getPage($outline['p']);
$x = ($outline['x'] * $this->kunit);
$y = ($page['height'] - ($outline['y'] * $this->kunit));
$x = $this->toPoints($outline['x']);
$y = $this->toYPoints($outline['y'], $page['pheight']);
$out .= ' ' . sprintf('/Dest [%u 0 R /XYZ %F %F null]', $page['n'], $x, $y);
}

Expand Down
Loading

0 comments on commit a612b13

Please sign in to comment.