Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Tcpdf Fpdi With Links
<?php
use setasign\Fpdi\Tcpdf\Fpdi;
use setasign\Fpdi\PdfReader\PageBoundaries;
use setasign\Fpdi\PdfParser\Type\PdfType;
use setasign\Fpdi\PdfParser\Type\PdfDictionary;
use setasign\Fpdi\PdfParser\Type\PdfArray;
class TcpdfFpdiCustom extends Fpdi {
/**
* @inheritdoc
* @param int $pageNumber
* @param string $box
* @param bool $groupXObject
* @return string
*/
public function importPage($pageNumber, $box = PageBoundaries::CROP_BOX, $groupXObject = true)
{
$pageId = parent::importPage($pageNumber, $box, $groupXObject);
// gather links
$links = [];
$reader = $this->getPdfReader($this->currentReaderId);
$parser = $reader->getParser();
$pageObj = $reader->getPage($pageNumber)->getPageObject();
$annotationsObject = PdfDictionary::get(PdfType::resolve($pageObj, $parser), 'Annots');
$annotations = PdfType::resolve($annotationsObject, $parser);
if($annotations->value) {
foreach($annotations->value as $annotationRef) {
$annotation = PdfType::resolve($annotationRef, $parser);
if(PdfDictionary::get($annotation, 'Type')->value === 'Annot' && PdfDictionary::get($annotation, 'Subtype')->value === 'Link') {
$a = PdfDictionary::get($annotation, 'A');
if($a) {
$link = PdfType::resolve($a, $parser);
if(PdfDictionary::get($link, 'S')->value === 'URI') {
$rectObj = PdfDictionary::get($annotation, 'Rect');
if($rectObj instanceof PdfArray) {
$rect = $rectObj->value;
$links[] = [
$rect[0]->value,
$rect[1]->value,
$rect[2]->value - $rect[0]->value,
$rect[1]->value - $rect[3]->value,
PdfDictionary::get($link, 'URI')->value
];
}
}
}
}
}
}
// save for future
$this->importedPages[$pageId]['links'] = $links;
return $pageId;
}
/**
* @inheritdoc
* @param mixed $tpl
* @param float|int|array $x
* @param float|int $y
* @param float|int|null $width
* @param float|int|null $height
* @param bool $adjustPageSize
* @return array
*/
public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
{
$ret = parent::useTemplate($tpl, $x, $y, $width, $height, $adjustPageSize);
$links = $this->importedPages[$tpl]['links'];
$pxToU = $this->pixelsToUnits(1);
foreach ($links as $link) {
$this->Link(
$link[0] * $pxToU,
$this->getPageHeight() - $link[1] * $pxToU,
$link[2] * $pxToU,
$link[3] * $pxToU,
$link[4]
);
}
$ret;
}
}
@jakubnavratil
Copy link
Author

jakubnavratil commented Sep 1, 2020

Usage: Replace Fpdi constructor with this.

$pdf = new TcpdfFpdiCustom();

Currently copies only external links and not yet battle tested.

@gavin310
Copy link

gavin310 commented Nov 16, 2020

I just used this and it worked great for my external links. Thank you!!

@igorsgm
Copy link

igorsgm commented Apr 13, 2021

If you are looking for a solution supporting both external and internal links (hyperlinks), using TCPDF and FPDI, check this answer here:

https://stackoverflow.com/a/67071744/5397846

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment