diff options
Diffstat (limited to 'vendor/setasign/fpdi/src/FpdfTplTrait.php')
-rw-r--r-- | vendor/setasign/fpdi/src/FpdfTplTrait.php | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/vendor/setasign/fpdi/src/FpdfTplTrait.php b/vendor/setasign/fpdi/src/FpdfTplTrait.php new file mode 100644 index 0000000..d2da97c --- /dev/null +++ b/vendor/setasign/fpdi/src/FpdfTplTrait.php @@ -0,0 +1,470 @@ +<?php + +/** + * This file is part of FPDI + * + * @package setasign\Fpdi + * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com) + * @license http://opensource.org/licenses/mit-license The MIT License + */ + +namespace setasign\Fpdi; + +/** + * Trait FpdfTplTrait + * + * This class adds a templating feature to tFPDF. + */ +trait FpdfTplTrait +{ + /** + * Data of all created templates. + * + * @var array + */ + protected $templates = []; + + /** + * The template id for the currently created template. + * + * @var null|int + */ + protected $currentTemplateId; + + /** + * A counter for template ids. + * + * @var int + */ + protected $templateId = 0; + + /** + * Set the page format of the current page. + * + * @param array $size An array with two values defining the size. + * @param string $orientation "L" for landscape, "P" for portrait. + * @throws \BadMethodCallException + */ + public function setPageFormat($size, $orientation) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('The page format cannot be changed when writing to a template.'); + } + + if (!\in_array($orientation, ['P', 'L'], true)) { + throw new \InvalidArgumentException(\sprintf( + 'Invalid page orientation "%s"! Only "P" and "L" are allowed!', + $orientation + )); + } + + $size = $this->_getpagesize($size); + + if ( + $orientation != $this->CurOrientation + || $size[0] != $this->CurPageSize[0] + || $size[1] != $this->CurPageSize[1] + ) { + // New size or orientation + if ($orientation === 'P') { + $this->w = $size[0]; + $this->h = $size[1]; + } else { + $this->w = $size[1]; + $this->h = $size[0]; + } + $this->wPt = $this->w * $this->k; + $this->hPt = $this->h * $this->k; + $this->PageBreakTrigger = $this->h - $this->bMargin; + $this->CurOrientation = $orientation; + $this->CurPageSize = $size; + + $this->PageInfo[$this->page]['size'] = array($this->wPt, $this->hPt); + } + } + + /** + * Draws a template onto the page or another template. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param array|float|int $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size + * @see FpdfTplTrait::getTemplateSize() + */ + public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + if (!isset($this->templates[$tpl])) { + throw new \InvalidArgumentException('Template does not exist!'); + } + + if (\is_array($x)) { + unset($x['tpl']); + \extract($x, EXTR_IF_EXISTS); + /** @noinspection NotOptimalIfConditionsInspection */ + /** @noinspection PhpConditionAlreadyCheckedInspection */ + if (\is_array($x)) { + $x = 0; + } + } + + $template = $this->templates[$tpl]; + + $originalSize = $this->getTemplateSize($tpl); + $newSize = $this->getTemplateSize($tpl, $width, $height); + if ($adjustPageSize) { + $this->setPageFormat($newSize, $newSize['orientation']); + } + + $this->_out( + // reset standard values, translate and scale + \sprintf( + 'q 0 J 1 w 0 j 0 G 0 g %.4F 0 0 %.4F %.4F %.4F cm /%s Do Q', + ($newSize['width'] / $originalSize['width']), + ($newSize['height'] / $originalSize['height']), + $x * $this->k, + ($this->h - $y - $newSize['height']) * $this->k, + $template['id'] + ) + ); + + return $newSize; + } + + /** + * Get the size of a template. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) + */ + public function getTemplateSize($tpl, $width = null, $height = null) + { + if (!isset($this->templates[$tpl])) { + return false; + } + + if ($width === null && $height === null) { + $width = $this->templates[$tpl]['width']; + $height = $this->templates[$tpl]['height']; + } elseif ($width === null) { + $width = $height * $this->templates[$tpl]['width'] / $this->templates[$tpl]['height']; + } + + if ($height === null) { + $height = $width * $this->templates[$tpl]['height'] / $this->templates[$tpl]['width']; + } + + if ($height <= 0. || $width <= 0.) { + throw new \InvalidArgumentException('Width or height parameter needs to be larger than zero.'); + } + + return [ + 'width' => $width, + 'height' => $height, + 0 => $width, + 1 => $height, + 'orientation' => $width > $height ? 'L' : 'P' + ]; + } + + /** + * Begins a new template. + * + * @param float|int|null $width The width of the template. If null, the current page width is used. + * @param float|int|null $height The height of the template. If null, the current page height is used. + * @param bool $groupXObject Define the form XObject as a group XObject to support transparency (if used). + * @return int A template identifier. + */ + public function beginTemplate($width = null, $height = null, $groupXObject = false) + { + if ($width === null) { + $width = $this->w; + } + + if ($height === null) { + $height = $this->h; + } + + $templateId = $this->getNextTemplateId(); + + // initiate buffer with current state of FPDF + $buffer = "2 J\n" + . \sprintf('%.2F w', $this->LineWidth * $this->k) . "\n"; + + if ($this->FontFamily) { + $buffer .= \sprintf("BT /F%d %.2F Tf ET\n", $this->CurrentFont['i'], $this->FontSizePt); + } + + if ($this->DrawColor !== '0 G') { + $buffer .= $this->DrawColor . "\n"; + } + if ($this->FillColor !== '0 g') { + $buffer .= $this->FillColor . "\n"; + } + + if ($groupXObject && \version_compare('1.4', $this->PDFVersion, '>')) { + $this->PDFVersion = '1.4'; + } + + $this->templates[$templateId] = [ + 'objectNumber' => null, + 'id' => 'TPL' . $templateId, + 'buffer' => $buffer, + 'width' => $width, + 'height' => $height, + 'groupXObject' => $groupXObject, + 'state' => [ + 'x' => $this->x, + 'y' => $this->y, + 'AutoPageBreak' => $this->AutoPageBreak, + 'bMargin' => $this->bMargin, + 'tMargin' => $this->tMargin, + 'lMargin' => $this->lMargin, + 'rMargin' => $this->rMargin, + 'h' => $this->h, + 'w' => $this->w, + 'FontFamily' => $this->FontFamily, + 'FontStyle' => $this->FontStyle, + 'FontSizePt' => $this->FontSizePt, + 'FontSize' => $this->FontSize, + 'underline' => $this->underline, + 'TextColor' => $this->TextColor, + 'DrawColor' => $this->DrawColor, + 'FillColor' => $this->FillColor, + 'ColorFlag' => $this->ColorFlag + ] + ]; + + $this->SetAutoPageBreak(false); + $this->currentTemplateId = $templateId; + + $this->h = $height; + $this->w = $width; + + $this->SetXY($this->lMargin, $this->tMargin); + $this->SetRightMargin($this->w - $width + $this->rMargin); + + return $templateId; + } + + /** + * Ends a template. + * + * @return bool|int|null A template identifier. + */ + public function endTemplate() + { + if ($this->currentTemplateId === null) { + return false; + } + + $templateId = $this->currentTemplateId; + $template = $this->templates[$templateId]; + + $state = $template['state']; + $this->SetXY($state['x'], $state['y']); + $this->tMargin = $state['tMargin']; + $this->lMargin = $state['lMargin']; + $this->rMargin = $state['rMargin']; + $this->h = $state['h']; + $this->w = $state['w']; + $this->SetAutoPageBreak($state['AutoPageBreak'], $state['bMargin']); + + $this->FontFamily = $state['FontFamily']; + $this->FontStyle = $state['FontStyle']; + $this->FontSizePt = $state['FontSizePt']; + $this->FontSize = $state['FontSize']; + + $this->TextColor = $state['TextColor']; + $this->DrawColor = $state['DrawColor']; + $this->FillColor = $state['FillColor']; + $this->ColorFlag = $state['ColorFlag']; + + $this->underline = $state['underline']; + + $fontKey = $this->FontFamily . $this->FontStyle; + if ($fontKey) { + $this->CurrentFont =& $this->fonts[$fontKey]; + } else { + unset($this->CurrentFont); + } + + $this->currentTemplateId = null; + + return $templateId; + } + + /** + * Get the next template id. + * + * @return int + */ + protected function getNextTemplateId() + { + return $this->templateId++; + } + + /* overwritten FPDF methods: */ + + /** + * @inheritdoc + */ + public function AddPage($orientation = '', $size = '', $rotation = 0) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('Pages cannot be added when writing to a template.'); + } + parent::AddPage($orientation, $size, $rotation); + } + + /** + * @inheritdoc + */ + public function Link($x, $y, $w, $h, $link) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('Links cannot be set when writing to a template.'); + } + parent::Link($x, $y, $w, $h, $link); + } + + /** + * @inheritdoc + */ + public function SetLink($link, $y = 0, $page = -1) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('Links cannot be set when writing to a template.'); + } + return parent::SetLink($link, $y, $page); + } + + /** + * @inheritdoc + */ + public function SetDrawColor($r, $g = null, $b = null) + { + parent::SetDrawColor($r, $g, $b); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out($this->DrawColor); + } + } + + /** + * @inheritdoc + */ + public function SetFillColor($r, $g = null, $b = null) + { + parent::SetFillColor($r, $g, $b); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out($this->FillColor); + } + } + + /** + * @inheritdoc + */ + public function SetLineWidth($width) + { + parent::SetLineWidth($width); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out(\sprintf('%.2F w', $width * $this->k)); + } + } + + /** + * @inheritdoc + */ + public function SetFont($family, $style = '', $size = 0) + { + parent::SetFont($family, $style, $size); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out(\sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); + } + } + + /** + * @inheritdoc + */ + public function SetFontSize($size) + { + parent::SetFontSize($size); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); + } + } + + /** + * @inheritdoc + */ + protected function _putimages() + { + parent::_putimages(); + + foreach ($this->templates as $key => $template) { + $this->_newobj(); + $this->templates[$key]['objectNumber'] = $this->n; + + $this->_put('<</Type /XObject /Subtype /Form /FormType 1'); + $this->_put(\sprintf( + '/BBox[0 0 %.2F %.2F]', + $template['width'] * $this->k, + $template['height'] * $this->k + )); + $this->_put('/Resources 2 0 R'); // default resources dictionary of FPDF + + if ($this->compress) { + $buffer = \gzcompress($template['buffer']); + $this->_put('/Filter/FlateDecode'); + } else { + $buffer = $template['buffer']; + } + + $this->_put('/Length ' . \strlen($buffer)); + + if ($template['groupXObject']) { + $this->_put('/Group <</Type/Group/S/Transparency>>'); + } + + $this->_put('>>'); + $this->_putstream($buffer); + $this->_put('endobj'); + } + } + + /** + * @inheritdoc + */ + protected function _putxobjectdict() + { + foreach ($this->templates as $key => $template) { + $this->_put('/' . $template['id'] . ' ' . $template['objectNumber'] . ' 0 R'); + } + + parent::_putxobjectdict(); + } + + /** + * @inheritdoc + */ + public function _out($s) + { + if ($this->currentTemplateId !== null) { + $this->templates[$this->currentTemplateId]['buffer'] .= $s . "\n"; + } else { + parent::_out($s); + } + } +} |