xref: /plugin/dw2pdf/vendor/setasign/fpdi/src/Tcpdf/Fpdi.php (revision dc4d9dc689082c963d5c1d9ee679553326788c6e)
1*dc4d9dc6SAnna Dabrowska<?php
2*dc4d9dc6SAnna Dabrowska
3*dc4d9dc6SAnna Dabrowskanamespace setasign\Fpdi\Tcpdf;
4*dc4d9dc6SAnna Dabrowska
5*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\FpdiTrait;
6*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException;
7*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\Filter\AsciiHex;
8*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\PdfParserException;
9*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\Type\PdfHexString;
10*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
11*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\Type\PdfNull;
12*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\Type\PdfNumeric;
13*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\Type\PdfStream;
14*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\Type\PdfString;
15*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\Type\PdfType;
16*dc4d9dc6SAnna Dabrowskause setasign\Fpdi\PdfParser\Type\PdfTypeException;
17*dc4d9dc6SAnna Dabrowska
18*dc4d9dc6SAnna Dabrowska/**
19*dc4d9dc6SAnna Dabrowska * Class Fpdi
20*dc4d9dc6SAnna Dabrowska *
21*dc4d9dc6SAnna Dabrowska * This class let you import pages of existing PDF documents into a reusable structure for TCPDF.
22*dc4d9dc6SAnna Dabrowska *
23*dc4d9dc6SAnna Dabrowska * @package setasign\Fpdi
24*dc4d9dc6SAnna Dabrowska */
25*dc4d9dc6SAnna Dabrowskaclass Fpdi extends \TCPDF
26*dc4d9dc6SAnna Dabrowska{
27*dc4d9dc6SAnna Dabrowska    use FpdiTrait {
28*dc4d9dc6SAnna Dabrowska        writePdfType as fpdiWritePdfType;
29*dc4d9dc6SAnna Dabrowska        useImportedPage as fpdiUseImportedPage;
30*dc4d9dc6SAnna Dabrowska    }
31*dc4d9dc6SAnna Dabrowska
32*dc4d9dc6SAnna Dabrowska    /**
33*dc4d9dc6SAnna Dabrowska     * FPDI version
34*dc4d9dc6SAnna Dabrowska     *
35*dc4d9dc6SAnna Dabrowska     * @string
36*dc4d9dc6SAnna Dabrowska     */
37*dc4d9dc6SAnna Dabrowska    const VERSION = '2.3.1';
38*dc4d9dc6SAnna Dabrowska
39*dc4d9dc6SAnna Dabrowska    /**
40*dc4d9dc6SAnna Dabrowska     * A counter for template ids.
41*dc4d9dc6SAnna Dabrowska     *
42*dc4d9dc6SAnna Dabrowska     * @var int
43*dc4d9dc6SAnna Dabrowska     */
44*dc4d9dc6SAnna Dabrowska    protected $templateId = 0;
45*dc4d9dc6SAnna Dabrowska
46*dc4d9dc6SAnna Dabrowska    /**
47*dc4d9dc6SAnna Dabrowska     * The currently used object number.
48*dc4d9dc6SAnna Dabrowska     *
49*dc4d9dc6SAnna Dabrowska     * @var int
50*dc4d9dc6SAnna Dabrowska     */
51*dc4d9dc6SAnna Dabrowska    protected $currentObjectNumber;
52*dc4d9dc6SAnna Dabrowska
53*dc4d9dc6SAnna Dabrowska    protected function _enddoc()
54*dc4d9dc6SAnna Dabrowska    {
55*dc4d9dc6SAnna Dabrowska        parent::_enddoc();
56*dc4d9dc6SAnna Dabrowska        $this->cleanUp();
57*dc4d9dc6SAnna Dabrowska    }
58*dc4d9dc6SAnna Dabrowska
59*dc4d9dc6SAnna Dabrowska    /**
60*dc4d9dc6SAnna Dabrowska     * Get the next template id.
61*dc4d9dc6SAnna Dabrowska     *
62*dc4d9dc6SAnna Dabrowska     * @return int
63*dc4d9dc6SAnna Dabrowska     */
64*dc4d9dc6SAnna Dabrowska    protected function getNextTemplateId()
65*dc4d9dc6SAnna Dabrowska    {
66*dc4d9dc6SAnna Dabrowska        return $this->templateId++;
67*dc4d9dc6SAnna Dabrowska    }
68*dc4d9dc6SAnna Dabrowska
69*dc4d9dc6SAnna Dabrowska    /**
70*dc4d9dc6SAnna Dabrowska     * Draws an imported page onto the page or another template.
71*dc4d9dc6SAnna Dabrowska     *
72*dc4d9dc6SAnna Dabrowska     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
73*dc4d9dc6SAnna Dabrowska     * aspect ratio.
74*dc4d9dc6SAnna Dabrowska     *
75*dc4d9dc6SAnna Dabrowska     * @param mixed $tpl The template id
76*dc4d9dc6SAnna Dabrowska     * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
77*dc4d9dc6SAnna Dabrowska     *                           with the keys "x", "y", "width", "height", "adjustPageSize".
78*dc4d9dc6SAnna Dabrowska     * @param float|int $y The ordinate of upper-left corner.
79*dc4d9dc6SAnna Dabrowska     * @param float|int|null $width The width.
80*dc4d9dc6SAnna Dabrowska     * @param float|int|null $height The height.
81*dc4d9dc6SAnna Dabrowska     * @param bool $adjustPageSize
82*dc4d9dc6SAnna Dabrowska     * @return array The size
83*dc4d9dc6SAnna Dabrowska     * @see FpdiTrait::getTemplateSize()
84*dc4d9dc6SAnna Dabrowska     */
85*dc4d9dc6SAnna Dabrowska    public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
86*dc4d9dc6SAnna Dabrowska    {
87*dc4d9dc6SAnna Dabrowska        return $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize);
88*dc4d9dc6SAnna Dabrowska    }
89*dc4d9dc6SAnna Dabrowska
90*dc4d9dc6SAnna Dabrowska    /**
91*dc4d9dc6SAnna Dabrowska     * Draws an imported page onto the page.
92*dc4d9dc6SAnna Dabrowska     *
93*dc4d9dc6SAnna Dabrowska     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
94*dc4d9dc6SAnna Dabrowska     * aspect ratio.
95*dc4d9dc6SAnna Dabrowska     *
96*dc4d9dc6SAnna Dabrowska     * @param mixed $pageId The page id
97*dc4d9dc6SAnna Dabrowska     * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
98*dc4d9dc6SAnna Dabrowska     *                           with the keys "x", "y", "width", "height", "adjustPageSize".
99*dc4d9dc6SAnna Dabrowska     * @param float|int $y The ordinate of upper-left corner.
100*dc4d9dc6SAnna Dabrowska     * @param float|int|null $width The width.
101*dc4d9dc6SAnna Dabrowska     * @param float|int|null $height The height.
102*dc4d9dc6SAnna Dabrowska     * @param bool $adjustPageSize
103*dc4d9dc6SAnna Dabrowska     * @return array The size.
104*dc4d9dc6SAnna Dabrowska     * @see Fpdi::getTemplateSize()
105*dc4d9dc6SAnna Dabrowska     */
106*dc4d9dc6SAnna Dabrowska    public function useImportedPage($pageId, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
107*dc4d9dc6SAnna Dabrowska    {
108*dc4d9dc6SAnna Dabrowska        $size = $this->fpdiUseImportedPage($pageId, $x, $y, $width, $height, $adjustPageSize);
109*dc4d9dc6SAnna Dabrowska        if ($this->inxobj) {
110*dc4d9dc6SAnna Dabrowska            $importedPage = $this->importedPages[$pageId];
111*dc4d9dc6SAnna Dabrowska            $this->xobjects[$this->xobjid]['importedPages'][$importedPage['id']] = $pageId;
112*dc4d9dc6SAnna Dabrowska        }
113*dc4d9dc6SAnna Dabrowska
114*dc4d9dc6SAnna Dabrowska        return $size;
115*dc4d9dc6SAnna Dabrowska    }
116*dc4d9dc6SAnna Dabrowska
117*dc4d9dc6SAnna Dabrowska    /**
118*dc4d9dc6SAnna Dabrowska     * Get the size of an imported page.
119*dc4d9dc6SAnna Dabrowska     *
120*dc4d9dc6SAnna Dabrowska     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
121*dc4d9dc6SAnna Dabrowska     * aspect ratio.
122*dc4d9dc6SAnna Dabrowska     *
123*dc4d9dc6SAnna Dabrowska     * @param mixed $tpl The template id
124*dc4d9dc6SAnna Dabrowska     * @param float|int|null $width The width.
125*dc4d9dc6SAnna Dabrowska     * @param float|int|null $height The height.
126*dc4d9dc6SAnna Dabrowska     * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P)
127*dc4d9dc6SAnna Dabrowska     */
128*dc4d9dc6SAnna Dabrowska    public function getTemplateSize($tpl, $width = null, $height = null)
129*dc4d9dc6SAnna Dabrowska    {
130*dc4d9dc6SAnna Dabrowska        return $this->getImportedPageSize($tpl, $width, $height);
131*dc4d9dc6SAnna Dabrowska    }
132*dc4d9dc6SAnna Dabrowska
133*dc4d9dc6SAnna Dabrowska    /**
134*dc4d9dc6SAnna Dabrowska     * @inheritdoc
135*dc4d9dc6SAnna Dabrowska     */
136*dc4d9dc6SAnna Dabrowska    protected function _getxobjectdict()
137*dc4d9dc6SAnna Dabrowska    {
138*dc4d9dc6SAnna Dabrowska        $out = parent::_getxobjectdict();
139*dc4d9dc6SAnna Dabrowska
140*dc4d9dc6SAnna Dabrowska        foreach ($this->importedPages as $key => $pageData) {
141*dc4d9dc6SAnna Dabrowska            $out .= '/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R ';
142*dc4d9dc6SAnna Dabrowska        }
143*dc4d9dc6SAnna Dabrowska
144*dc4d9dc6SAnna Dabrowska        return $out;
145*dc4d9dc6SAnna Dabrowska    }
146*dc4d9dc6SAnna Dabrowska
147*dc4d9dc6SAnna Dabrowska    /**
148*dc4d9dc6SAnna Dabrowska     * @inheritdoc
149*dc4d9dc6SAnna Dabrowska     * @throws CrossReferenceException
150*dc4d9dc6SAnna Dabrowska     * @throws PdfParserException
151*dc4d9dc6SAnna Dabrowska     */
152*dc4d9dc6SAnna Dabrowska    protected function _putxobjects()
153*dc4d9dc6SAnna Dabrowska    {
154*dc4d9dc6SAnna Dabrowska        foreach ($this->importedPages as $key => $pageData) {
155*dc4d9dc6SAnna Dabrowska            $this->currentObjectNumber = $this->_newobj();
156*dc4d9dc6SAnna Dabrowska            $this->importedPages[$key]['objectNumber'] = $this->currentObjectNumber;
157*dc4d9dc6SAnna Dabrowska            $this->currentReaderId = $pageData['readerId'];
158*dc4d9dc6SAnna Dabrowska            $this->writePdfType($pageData['stream']);
159*dc4d9dc6SAnna Dabrowska            $this->_put('endobj');
160*dc4d9dc6SAnna Dabrowska        }
161*dc4d9dc6SAnna Dabrowska
162*dc4d9dc6SAnna Dabrowska        foreach (\array_keys($this->readers) as $readerId) {
163*dc4d9dc6SAnna Dabrowska            $parser = $this->getPdfReader($readerId)->getParser();
164*dc4d9dc6SAnna Dabrowska            $this->currentReaderId = $readerId;
165*dc4d9dc6SAnna Dabrowska
166*dc4d9dc6SAnna Dabrowska            while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) {
167*dc4d9dc6SAnna Dabrowska                try {
168*dc4d9dc6SAnna Dabrowska                    $object = $parser->getIndirectObject($objectNumber);
169*dc4d9dc6SAnna Dabrowska
170*dc4d9dc6SAnna Dabrowska                } catch (CrossReferenceException $e) {
171*dc4d9dc6SAnna Dabrowska                    if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) {
172*dc4d9dc6SAnna Dabrowska                        $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull());
173*dc4d9dc6SAnna Dabrowska                    } else {
174*dc4d9dc6SAnna Dabrowska                        throw $e;
175*dc4d9dc6SAnna Dabrowska                    }
176*dc4d9dc6SAnna Dabrowska                }
177*dc4d9dc6SAnna Dabrowska
178*dc4d9dc6SAnna Dabrowska                $this->writePdfType($object);
179*dc4d9dc6SAnna Dabrowska            }
180*dc4d9dc6SAnna Dabrowska        }
181*dc4d9dc6SAnna Dabrowska
182*dc4d9dc6SAnna Dabrowska        // let's prepare resources for imported pages in templates
183*dc4d9dc6SAnna Dabrowska        foreach ($this->xobjects as $xObjectId => $data) {
184*dc4d9dc6SAnna Dabrowska            if (!isset($data['importedPages'])) {
185*dc4d9dc6SAnna Dabrowska                continue;
186*dc4d9dc6SAnna Dabrowska            }
187*dc4d9dc6SAnna Dabrowska
188*dc4d9dc6SAnna Dabrowska            foreach ($data['importedPages'] as $id => $pageKey) {
189*dc4d9dc6SAnna Dabrowska                $page = $this->importedPages[$pageKey];
190*dc4d9dc6SAnna Dabrowska                $this->xobjects[$xObjectId]['xobjects'][$id] = ['n' => $page['objectNumber']];
191*dc4d9dc6SAnna Dabrowska            }
192*dc4d9dc6SAnna Dabrowska        }
193*dc4d9dc6SAnna Dabrowska
194*dc4d9dc6SAnna Dabrowska
195*dc4d9dc6SAnna Dabrowska        parent::_putxobjects();
196*dc4d9dc6SAnna Dabrowska        $this->currentObjectNumber = null;
197*dc4d9dc6SAnna Dabrowska    }
198*dc4d9dc6SAnna Dabrowska
199*dc4d9dc6SAnna Dabrowska    /**
200*dc4d9dc6SAnna Dabrowska     * Append content to the buffer of TCPDF.
201*dc4d9dc6SAnna Dabrowska     *
202*dc4d9dc6SAnna Dabrowska     * @param string $s
203*dc4d9dc6SAnna Dabrowska     * @param bool $newLine
204*dc4d9dc6SAnna Dabrowska     */
205*dc4d9dc6SAnna Dabrowska    protected function _put($s, $newLine = true)
206*dc4d9dc6SAnna Dabrowska    {
207*dc4d9dc6SAnna Dabrowska        if ($newLine) {
208*dc4d9dc6SAnna Dabrowska            $this->setBuffer($s . "\n");
209*dc4d9dc6SAnna Dabrowska        } else {
210*dc4d9dc6SAnna Dabrowska            $this->setBuffer($s);
211*dc4d9dc6SAnna Dabrowska        }
212*dc4d9dc6SAnna Dabrowska    }
213*dc4d9dc6SAnna Dabrowska
214*dc4d9dc6SAnna Dabrowska    /**
215*dc4d9dc6SAnna Dabrowska     * Begin a new object and return the object number.
216*dc4d9dc6SAnna Dabrowska     *
217*dc4d9dc6SAnna Dabrowska     * @param int|string $objid Object ID (leave empty to get a new ID).
218*dc4d9dc6SAnna Dabrowska     * @return int object number
219*dc4d9dc6SAnna Dabrowska     */
220*dc4d9dc6SAnna Dabrowska    protected function _newobj($objid = '')
221*dc4d9dc6SAnna Dabrowska    {
222*dc4d9dc6SAnna Dabrowska        $this->_out($this->_getobj($objid));
223*dc4d9dc6SAnna Dabrowska        return $this->n;
224*dc4d9dc6SAnna Dabrowska    }
225*dc4d9dc6SAnna Dabrowska
226*dc4d9dc6SAnna Dabrowska    /**
227*dc4d9dc6SAnna Dabrowska     * Writes a PdfType object to the resulting buffer.
228*dc4d9dc6SAnna Dabrowska     *
229*dc4d9dc6SAnna Dabrowska     * @param PdfType $value
230*dc4d9dc6SAnna Dabrowska     * @throws PdfTypeException
231*dc4d9dc6SAnna Dabrowska     */
232*dc4d9dc6SAnna Dabrowska    protected function writePdfType(PdfType $value)
233*dc4d9dc6SAnna Dabrowska    {
234*dc4d9dc6SAnna Dabrowska        if (!$this->encrypted) {
235*dc4d9dc6SAnna Dabrowska            $this->fpdiWritePdfType($value);
236*dc4d9dc6SAnna Dabrowska            return;
237*dc4d9dc6SAnna Dabrowska        }
238*dc4d9dc6SAnna Dabrowska
239*dc4d9dc6SAnna Dabrowska        if ($value instanceof PdfString) {
240*dc4d9dc6SAnna Dabrowska            $string = PdfString::unescape($value->value);
241*dc4d9dc6SAnna Dabrowska            $string = $this->_encrypt_data($this->currentObjectNumber, $string);
242*dc4d9dc6SAnna Dabrowska            $value->value = \TCPDF_STATIC::_escape($string);
243*dc4d9dc6SAnna Dabrowska
244*dc4d9dc6SAnna Dabrowska        } elseif ($value instanceof PdfHexString) {
245*dc4d9dc6SAnna Dabrowska            $filter = new AsciiHex();
246*dc4d9dc6SAnna Dabrowska            $string = $filter->decode($value->value);
247*dc4d9dc6SAnna Dabrowska            $string = $this->_encrypt_data($this->currentObjectNumber, $string);
248*dc4d9dc6SAnna Dabrowska            $value->value = $filter->encode($string, true);
249*dc4d9dc6SAnna Dabrowska
250*dc4d9dc6SAnna Dabrowska        } elseif ($value instanceof PdfStream) {
251*dc4d9dc6SAnna Dabrowska            $stream = $value->getStream();
252*dc4d9dc6SAnna Dabrowska            $stream = $this->_encrypt_data($this->currentObjectNumber, $stream);
253*dc4d9dc6SAnna Dabrowska            $dictionary = $value->value;
254*dc4d9dc6SAnna Dabrowska            $dictionary->value['Length'] = PdfNumeric::create(\strlen($stream));
255*dc4d9dc6SAnna Dabrowska            $value = PdfStream::create($dictionary, $stream);
256*dc4d9dc6SAnna Dabrowska
257*dc4d9dc6SAnna Dabrowska        } elseif ($value instanceof PdfIndirectObject) {
258*dc4d9dc6SAnna Dabrowska            /**
259*dc4d9dc6SAnna Dabrowska             * @var $value PdfIndirectObject
260*dc4d9dc6SAnna Dabrowska             */
261*dc4d9dc6SAnna Dabrowska            $this->currentObjectNumber = $this->objectMap[$this->currentReaderId][$value->objectNumber];
262*dc4d9dc6SAnna Dabrowska        }
263*dc4d9dc6SAnna Dabrowska
264*dc4d9dc6SAnna Dabrowska        $this->fpdiWritePdfType($value);
265*dc4d9dc6SAnna Dabrowska    }
266*dc4d9dc6SAnna Dabrowska}