FpdfTrait.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <?php
  2. /**
  3. * This file is part of FPDI
  4. *
  5. * @package setasign\Fpdi
  6. * @copyright Copyright (c) 2024 Setasign GmbH & Co. KG (https://www.setasign.com)
  7. * @license http://opensource.org/licenses/mit-license The MIT License
  8. */
  9. namespace setasign\Fpdi;
  10. use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException;
  11. use setasign\Fpdi\PdfParser\PdfParserException;
  12. use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
  13. use setasign\Fpdi\PdfParser\Type\PdfNull;
  14. use setasign\Fpdi\PdfParser\Type\PdfType;
  15. /**
  16. * This trait is used for the implementation of FPDI in FPDF and tFPDF.
  17. */
  18. trait FpdfTrait
  19. {
  20. protected function _enddoc()
  21. {
  22. parent::_enddoc();
  23. $this->cleanUp();
  24. }
  25. /**
  26. * Draws an imported page or a template onto the page or another template.
  27. *
  28. * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
  29. * aspect ratio.
  30. *
  31. * @param mixed $tpl The template id
  32. * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
  33. * with the keys "x", "y", "width", "height", "adjustPageSize".
  34. * @param float|int $y The ordinate of upper-left corner.
  35. * @param float|int|null $width The width.
  36. * @param float|int|null $height The height.
  37. * @param bool $adjustPageSize
  38. * @return array The size
  39. * @see Fpdi::getTemplateSize()
  40. */
  41. public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
  42. {
  43. if (isset($this->importedPages[$tpl])) {
  44. $size = $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize);
  45. if ($this->currentTemplateId !== null) {
  46. $this->templates[$this->currentTemplateId]['resources']['templates']['importedPages'][$tpl] = $tpl;
  47. }
  48. return $size;
  49. }
  50. return parent::useTemplate($tpl, $x, $y, $width, $height, $adjustPageSize);
  51. }
  52. /**
  53. * Get the size of an imported page or template.
  54. *
  55. * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
  56. * aspect ratio.
  57. *
  58. * @param mixed $tpl The template id
  59. * @param float|int|null $width The width.
  60. * @param float|int|null $height The height.
  61. * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P)
  62. */
  63. public function getTemplateSize($tpl, $width = null, $height = null)
  64. {
  65. $size = parent::getTemplateSize($tpl, $width, $height);
  66. if ($size === false) {
  67. return $this->getImportedPageSize($tpl, $width, $height);
  68. }
  69. return $size;
  70. }
  71. /**
  72. * @throws CrossReferenceException
  73. * @throws PdfParserException
  74. */
  75. protected function _putimages()
  76. {
  77. $this->currentReaderId = null;
  78. parent::_putimages();
  79. foreach ($this->importedPages as $key => $pageData) {
  80. $this->_newobj();
  81. $this->importedPages[$key]['objectNumber'] = $this->n;
  82. $this->currentReaderId = $pageData['readerId'];
  83. $this->writePdfType($pageData['stream']);
  84. $this->_put('endobj');
  85. }
  86. foreach (\array_keys($this->readers) as $readerId) {
  87. $parser = $this->getPdfReader($readerId)->getParser();
  88. $this->currentReaderId = $readerId;
  89. while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) {
  90. try {
  91. $object = $parser->getIndirectObject($objectNumber);
  92. } catch (CrossReferenceException $e) {
  93. if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) {
  94. $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull());
  95. } else {
  96. throw $e;
  97. }
  98. }
  99. $this->writePdfType($object);
  100. }
  101. }
  102. $this->currentReaderId = null;
  103. }
  104. /**
  105. * @inheritdoc
  106. */
  107. protected function _putxobjectdict()
  108. {
  109. foreach ($this->importedPages as $pageData) {
  110. $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R');
  111. }
  112. parent::_putxobjectdict();
  113. }
  114. /**
  115. * @param int $n
  116. * @return void
  117. * @throws PdfParser\Type\PdfTypeException
  118. */
  119. protected function _putlinks($n)
  120. {
  121. foreach ($this->PageLinks[$n] as $pl) {
  122. $this->_newobj();
  123. $rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0] + $pl[2], $pl[1] - $pl[3]);
  124. $this->_put('<</Type /Annot /Subtype /Link /Rect [' . $rect . ']', false);
  125. if (is_string($pl[4])) {
  126. $this->_put('/A <</S /URI /URI ' . $this->_textstring($pl[4]) . '>>');
  127. if (isset($pl['importedLink'])) {
  128. $values = $pl['importedLink']['pdfObject']->value;
  129. foreach ($values as $name => $entry) {
  130. $this->_put('/' . $name . ' ', false);
  131. $this->writePdfType($entry);
  132. }
  133. if (isset($pl['quadPoints'])) {
  134. $s = '/QuadPoints[';
  135. foreach ($pl['quadPoints'] as $value) {
  136. $s .= sprintf('%.2F ', $value);
  137. }
  138. $s .= ']';
  139. $this->_put($s);
  140. }
  141. } else {
  142. $this->_put('/Border [0 0 0]', false);
  143. }
  144. $this->_put('>>');
  145. } else {
  146. $this->_put('/Border [0 0 0] ', false);
  147. $l = $this->links[$pl[4]];
  148. if (isset($this->PageInfo[$l[0]]['size'])) {
  149. $h = $this->PageInfo[$l[0]]['size'][1];
  150. } else {
  151. $h = ($this->DefOrientation === 'P')
  152. ? $this->DefPageSize[1] * $this->k
  153. : $this->DefPageSize[0] * $this->k;
  154. }
  155. $this->_put(sprintf(
  156. '/Dest [%d 0 R /XYZ 0 %.2F null]>>',
  157. $this->PageInfo[$l[0]]['n'],
  158. $h - $l[1] * $this->k
  159. ));
  160. }
  161. $this->_put('endobj');
  162. }
  163. }
  164. protected function _put($s, $newLine = true)
  165. {
  166. if ($newLine) {
  167. $this->buffer .= $s . "\n";
  168. } else {
  169. $this->buffer .= $s;
  170. }
  171. }
  172. }