vendor/setasign/fpdi/src/FpdiTrait.php line 233

Open in your IDE?
  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\Filter\FilterException;
  12. use setasign\Fpdi\PdfParser\PdfParser;
  13. use setasign\Fpdi\PdfParser\PdfParserException;
  14. use setasign\Fpdi\PdfParser\StreamReader;
  15. use setasign\Fpdi\PdfParser\Type\PdfArray;
  16. use setasign\Fpdi\PdfParser\Type\PdfBoolean;
  17. use setasign\Fpdi\PdfParser\Type\PdfDictionary;
  18. use setasign\Fpdi\PdfParser\Type\PdfHexString;
  19. use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
  20. use setasign\Fpdi\PdfParser\Type\PdfIndirectObjectReference;
  21. use setasign\Fpdi\PdfParser\Type\PdfName;
  22. use setasign\Fpdi\PdfParser\Type\PdfNull;
  23. use setasign\Fpdi\PdfParser\Type\PdfNumeric;
  24. use setasign\Fpdi\PdfParser\Type\PdfStream;
  25. use setasign\Fpdi\PdfParser\Type\PdfString;
  26. use setasign\Fpdi\PdfParser\Type\PdfToken;
  27. use setasign\Fpdi\PdfParser\Type\PdfType;
  28. use setasign\Fpdi\PdfParser\Type\PdfTypeException;
  29. use setasign\Fpdi\PdfReader\DataStructure\Rectangle;
  30. use setasign\Fpdi\PdfReader\PageBoundaries;
  31. use setasign\Fpdi\PdfReader\PdfReader;
  32. use setasign\Fpdi\PdfReader\PdfReaderException;
  33. use /* This namespace/class is used by the commercial FPDI PDF-Parser add-on. */
  34.     /** @noinspection PhpUndefinedClassInspection */
  35.     /** @noinspection PhpUndefinedNamespaceInspection */
  36.     setasign\FpdiPdfParser\PdfParser\PdfParser as FpdiPdfParser;
  37. /**
  38.  * The FpdiTrait
  39.  *
  40.  * This trait offers the core functionalities of FPDI. By passing them to a trait we can reuse it with e.g. TCPDF in a
  41.  * very easy way.
  42.  */
  43. trait FpdiTrait
  44. {
  45.     /**
  46.      * The pdf reader instances.
  47.      *
  48.      * @var PdfReader[]
  49.      */
  50.     protected $readers = [];
  51.     /**
  52.      * Instances created internally.
  53.      *
  54.      * @var array
  55.      */
  56.     protected $createdReaders = [];
  57.     /**
  58.      * The current reader id.
  59.      *
  60.      * @var string|null
  61.      */
  62.     protected $currentReaderId;
  63.     /**
  64.      * Data of all imported pages.
  65.      *
  66.      * @var array
  67.      */
  68.     protected $importedPages = [];
  69.     /**
  70.      * A map from object numbers of imported objects to new assigned object numbers by FPDF.
  71.      *
  72.      * @var array
  73.      */
  74.     protected $objectMap = [];
  75.     /**
  76.      * An array with information about objects, which needs to be copied to the resulting document.
  77.      *
  78.      * @var array
  79.      */
  80.     protected $objectsToCopy = [];
  81.     /**
  82.      * Release resources and file handles.
  83.      *
  84.      * This method is called internally when the document is created successfully. By default it only cleans up
  85.      * stream reader instances which were created internally.
  86.      *
  87.      * @param bool $allReaders
  88.      */
  89.     public function cleanUp($allReaders false)
  90.     {
  91.         $readers $allReaders array_keys($this->readers) : $this->createdReaders;
  92.         foreach ($readers as $id) {
  93.             $this->readers[$id]->getParser()->getStreamReader()->cleanUp();
  94.             unset($this->readers[$id]);
  95.         }
  96.         $this->createdReaders = [];
  97.     }
  98.     /**
  99.      * Set the minimal PDF version.
  100.      *
  101.      * @param string $pdfVersion
  102.      */
  103.     protected function setMinPdfVersion($pdfVersion)
  104.     {
  105.         if (\version_compare($pdfVersion$this->PDFVersion'>')) {
  106.             $this->PDFVersion $pdfVersion;
  107.         }
  108.     }
  109.     /** @noinspection PhpUndefinedClassInspection */
  110.     /**
  111.      * Get a new pdf parser instance.
  112.      *
  113.      * @param StreamReader $streamReader
  114.      * @param array $parserParams Individual parameters passed to the parser instance.
  115.      * @return PdfParser|FpdiPdfParser
  116.      */
  117.     protected function getPdfParserInstance(StreamReader $streamReader, array $parserParams = [])
  118.     {
  119.         // note: if you get an exception here - turn off errors/warnings on not found classes for your autoloader.
  120.         // psr-4 (https://www.php-fig.org/psr/psr-4/) says: Autoloader implementations MUST NOT throw
  121.         // exceptions, MUST NOT raise errors of any level, and SHOULD NOT return a value.
  122.         /** @noinspection PhpUndefinedClassInspection */
  123.         if (\class_exists(FpdiPdfParser::class)) {
  124.             /** @noinspection PhpUndefinedClassInspection */
  125.             return new FpdiPdfParser($streamReader$parserParams);
  126.         }
  127.         return new PdfParser($streamReader);
  128.     }
  129.     /**
  130.      * Get an unique reader id by the $file parameter.
  131.      *
  132.      * @param string|resource|PdfReader|StreamReader $file An open file descriptor, a path to a file, a PdfReader
  133.      *                                                     instance or a StreamReader instance.
  134.      * @param array $parserParams Individual parameters passed to the parser instance.
  135.      * @return string
  136.      */
  137.     protected function getPdfReaderId($file, array $parserParams = [])
  138.     {
  139.         if (\is_resource($file)) {
  140.             $id = (string) $file;
  141.         } elseif (\is_string($file)) {
  142.             $id \realpath($file);
  143.             if ($id === false) {
  144.                 $id $file;
  145.             }
  146.         } elseif (\is_object($file)) {
  147.             $id \spl_object_hash($file);
  148.         } else {
  149.             throw new \InvalidArgumentException(
  150.                 \sprintf('Invalid type in $file parameter (%s)'\gettype($file))
  151.             );
  152.         }
  153.         /** @noinspection OffsetOperationsInspection */
  154.         if (isset($this->readers[$id])) {
  155.             return $id;
  156.         }
  157.         if (\is_resource($file)) {
  158.             $streamReader = new StreamReader($file);
  159.         } elseif (\is_string($file)) {
  160.             $streamReader StreamReader::createByFile($file);
  161.             $this->createdReaders[] = $id;
  162.         } else {
  163.             $streamReader $file;
  164.         }
  165.         $reader = new PdfReader($this->getPdfParserInstance($streamReader$parserParams));
  166.         /** @noinspection OffsetOperationsInspection */
  167.         $this->readers[$id] = $reader;
  168.         return $id;
  169.     }
  170.     /**
  171.      * Get a pdf reader instance by its id.
  172.      *
  173.      * @param string $id
  174.      * @return PdfReader
  175.      */
  176.     protected function getPdfReader($id)
  177.     {
  178.         if (isset($this->readers[$id])) {
  179.             return $this->readers[$id];
  180.         }
  181.         throw new \InvalidArgumentException(
  182.             \sprintf('No pdf reader with the given id (%s) exists.'$id)
  183.         );
  184.     }
  185.     /**
  186.      * Set the source PDF file.
  187.      *
  188.      * @param string|resource|StreamReader $file Path to the file or a stream resource or a StreamReader instance.
  189.      * @return int The page count of the PDF document.
  190.      * @throws PdfParserException
  191.      */
  192.     public function setSourceFile($file)
  193.     {
  194.         return $this->setSourceFileWithParserParams($file);
  195.     }
  196.     /**
  197.      * Set the source PDF file with parameters which are passed to the parser instance.
  198.      *
  199.      * This method allows us to pass e.g. authentication information to the parser instance.
  200.      *
  201.      * @param string|resource|StreamReader $file Path to the file or a stream resource or a StreamReader instance.
  202.      * @param array $parserParams Individual parameters passed to the parser instance.
  203.      * @return int The page count of the PDF document.
  204.      * @throws CrossReferenceException
  205.      * @throws PdfParserException
  206.      * @throws PdfTypeException
  207.      */
  208.     public function setSourceFileWithParserParams($file, array $parserParams = [])
  209.     {
  210.         $this->currentReaderId $this->getPdfReaderId($file$parserParams);
  211.         $this->objectsToCopy[$this->currentReaderId] = [];
  212.         $reader $this->getPdfReader($this->currentReaderId);
  213.         $this->setMinPdfVersion($reader->getPdfVersion());
  214.         return $reader->getPageCount();
  215.     }
  216.     /**
  217.      * Imports a page.
  218.      *
  219.      * @param int $pageNumber The page number.
  220.      * @param string $box The page boundary to import. Default set to PageBoundaries::CROP_BOX.
  221.      * @param bool $groupXObject Define the form XObject as a group XObject to support transparency (if used).
  222.      * @param bool $importExternalLinks Define whether external links are imported or not.
  223.      * @return string A unique string identifying the imported page.
  224.      * @throws CrossReferenceException
  225.      * @throws FilterException
  226.      * @throws PdfParserException
  227.      * @throws PdfTypeException
  228.      * @throws PdfReaderException
  229.      * @see PageBoundaries
  230.      */
  231.     public function importPage(
  232.         $pageNumber,
  233.         $box PageBoundaries::CROP_BOX,
  234.         $groupXObject true,
  235.         $importExternalLinks false
  236.     ) {
  237.         if ($this->currentReaderId === null) {
  238.             throw new \BadMethodCallException('No reader initiated. Call setSourceFile() first.');
  239.         }
  240.         $pageId $this->currentReaderId;
  241.         $pageNumber = (int)$pageNumber;
  242.         $pageId .= '|' $pageNumber '|' . ($groupXObject '1' '0') . '|' . ($importExternalLinks '1' '0');
  243.         // for backwards compatibility with FPDI 1
  244.         $box \ltrim($box'/');
  245.         if (!PageBoundaries::isValidName($box)) {
  246.             throw new \InvalidArgumentException(
  247.                 \sprintf('Box name is invalid: "%s"'$box)
  248.             );
  249.         }
  250.         $pageId .= '|' $box;
  251.         if (isset($this->importedPages[$pageId])) {
  252.             return $pageId;
  253.         }
  254.         $reader $this->getPdfReader($this->currentReaderId);
  255.         $page $reader->getPage($pageNumber);
  256.         $bbox $page->getBoundary($box);
  257.         if ($bbox === false) {
  258.             throw new PdfReaderException(
  259.                 \sprintf("Page doesn't have a boundary box (%s)."$box),
  260.                 PdfReaderException::MISSING_DATA
  261.             );
  262.         }
  263.         $dict = new PdfDictionary();
  264.         $dict->value['Type'] = PdfName::create('XObject');
  265.         $dict->value['Subtype'] = PdfName::create('Form');
  266.         $dict->value['FormType'] = PdfNumeric::create(1);
  267.         $dict->value['BBox'] = $bbox->toPdfArray();
  268.         if ($groupXObject) {
  269.             $this->setMinPdfVersion('1.4');
  270.             $dict->value['Group'] = PdfDictionary::create([
  271.                 'Type' => PdfName::create('Group'),
  272.                 'S' => PdfName::create('Transparency')
  273.             ]);
  274.         }
  275.         $resources $page->getAttribute('Resources');
  276.         if ($resources !== null) {
  277.             $dict->value['Resources'] = $resources;
  278.         }
  279.         list($width$height) = $page->getWidthAndHeight($box);
  280.         $a 1;
  281.         $b 0;
  282.         $c 0;
  283.         $d 1;
  284.         $e = -$bbox->getLlx();
  285.         $f = -$bbox->getLly();
  286.         $rotation $page->getRotation();
  287.         if ($rotation !== 0) {
  288.             $rotation *= -1;
  289.             $angle $rotation M_PI 180;
  290.             $a \cos($angle);
  291.             $b \sin($angle);
  292.             $c = -$b;
  293.             $d $a;
  294.             switch ($rotation) {
  295.                 case -90:
  296.                     $e = -$bbox->getLly();
  297.                     $f $bbox->getUrx();
  298.                     break;
  299.                 case -180:
  300.                     $e $bbox->getUrx();
  301.                     $f $bbox->getUry();
  302.                     break;
  303.                 case -270:
  304.                     $e $bbox->getUry();
  305.                     $f = -$bbox->getLlx();
  306.                     break;
  307.             }
  308.         }
  309.         // we need to rotate/translate
  310.         if ($a != || $b != || $c != || $d != || $e != || $f != 0) {
  311.             $dict->value['Matrix'] = PdfArray::create([
  312.                 PdfNumeric::create($a), PdfNumeric::create($b), PdfNumeric::create($c),
  313.                 PdfNumeric::create($d), PdfNumeric::create($e), PdfNumeric::create($f)
  314.             ]);
  315.         }
  316.         // try to use the existing content stream
  317.         $pageDict $page->getPageDictionary();
  318.         try {
  319.             $contentsObject PdfType::resolve(PdfDictionary::get($pageDict'Contents'), $reader->getParser(), true);
  320.             $contents =  PdfType::resolve($contentsObject$reader->getParser());
  321.             // just copy the stream reference if it is only a single stream
  322.             if (
  323.                 ($contentsIsStream = ($contents instanceof PdfStream))
  324.                 || ($contents instanceof PdfArray && \count($contents->value) === 1)
  325.             ) {
  326.                 if ($contentsIsStream) {
  327.                     /**
  328.                      * @var PdfIndirectObject $contentsObject
  329.                      */
  330.                     $stream $contents;
  331.                 } else {
  332.                     $stream PdfType::resolve($contents->value[0], $reader->getParser());
  333.                 }
  334.                 $filter PdfDictionary::get($stream->value'Filter');
  335.                 if (!$filter instanceof PdfNull) {
  336.                     $dict->value['Filter'] = $filter;
  337.                 }
  338.                 $length PdfType::resolve(PdfDictionary::get($stream->value'Length'), $reader->getParser());
  339.                 $dict->value['Length'] = $length;
  340.                 $stream->value $dict;
  341.                 // otherwise extract it from the array and re-compress the whole stream
  342.             } else {
  343.                 $streamContent $this->compress
  344.                     \gzcompress($page->getContentStream())
  345.                     : $page->getContentStream();
  346.                 $dict->value['Length'] = PdfNumeric::create(\strlen($streamContent));
  347.                 if ($this->compress) {
  348.                     $dict->value['Filter'] = PdfName::create('FlateDecode');
  349.                 }
  350.                 $stream PdfStream::create($dict$streamContent);
  351.             }
  352.         // Catch faulty pages and use an empty content stream
  353.         } catch (FpdiException $e) {
  354.             $dict->value['Length'] = PdfNumeric::create(0);
  355.             $stream PdfStream::create($dict'');
  356.         }
  357.         $externalLinks = [];
  358.         if ($importExternalLinks) {
  359.             $externalLinks $page->getExternalLinks($box);
  360.         }
  361.         $this->importedPages[$pageId] = [
  362.             'objectNumber' => null,
  363.             'readerId' => $this->currentReaderId,
  364.             'id' => 'TPL' $this->getNextTemplateId(),
  365.             'width' => $width $this->k,
  366.             'height' => $height $this->k,
  367.             'stream' => $stream,
  368.             'externalLinks' => $externalLinks
  369.         ];
  370.         return $pageId;
  371.     }
  372.     /**
  373.      * Draws an imported page onto the page.
  374.      *
  375.      * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
  376.      * aspect ratio.
  377.      *
  378.      * @param mixed $pageId The page id
  379.      * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
  380.      *                           with the keys "x", "y", "width", "height", "adjustPageSize".
  381.      * @param float|int $y The ordinate of upper-left corner.
  382.      * @param float|int|null $width The width.
  383.      * @param float|int|null $height The height.
  384.      * @param bool $adjustPageSize
  385.      * @return array The size.
  386.      * @see Fpdi::getTemplateSize()
  387.      */
  388.     public function useImportedPage($pageId$x 0$y 0$width null$height null$adjustPageSize false)
  389.     {
  390.         if (\is_array($x)) {
  391.             /** @noinspection OffsetOperationsInspection */
  392.             unset($x['pageId']);
  393.             \extract($xEXTR_IF_EXISTS);
  394.             /** @noinspection NotOptimalIfConditionsInspection */
  395.             /** @phpstan-ignore function.alreadyNarrowedType  */
  396.             if (\is_array($x)) {
  397.                 $x 0;
  398.             }
  399.         }
  400.         if (!isset($this->importedPages[$pageId])) {
  401.             throw new \InvalidArgumentException('Imported page does not exist!');
  402.         }
  403.         $importedPage $this->importedPages[$pageId];
  404.         $originalSize $this->getTemplateSize($pageId);
  405.         $newSize $this->getTemplateSize($pageId$width$height);
  406.         if ($adjustPageSize) {
  407.             $this->setPageFormat($newSize$newSize['orientation']);
  408.         }
  409.         $scaleX = ($newSize['width'] / $originalSize['width']);
  410.         $scaleY = ($newSize['height'] / $originalSize['height']);
  411.         $xPt $x $this->k;
  412.         $yPt $y $this->k;
  413.         $newHeightPt $newSize['height'] * $this->k;
  414.         $this->_out(
  415.             // reset standard values, translate and scale
  416.             \sprintf(
  417.                 'q 0 J 1 w 0 j 0 G 0 g %.4F 0 0 %.4F %.4F %.4F cm /%s Do Q',
  418.                 $scaleX,
  419.                 $scaleY,
  420.                 $xPt,
  421.                 $this->hPt $yPt $newHeightPt,
  422.                 $importedPage['id']
  423.             )
  424.         );
  425.         if (count($importedPage['externalLinks']) > 0) {
  426.             foreach ($importedPage['externalLinks'] as $externalLink) {
  427.                 // mPDF uses also 'externalLinks' but doesn't come with a rect-value
  428.                 if (!isset($externalLink['rect'])) {
  429.                     continue;
  430.                 }
  431.                 /** @var Rectangle $rect */
  432.                 $rect $externalLink['rect'];
  433.                 $this->Link(
  434.                     $x $rect->getLlx() / $this->$scaleX,
  435.                     $y $newSize['height'] - ($rect->getLly() + $rect->getHeight()) / $this->$scaleY,
  436.                     $rect->getWidth() / $this->$scaleX,
  437.                     $rect->getHeight()  / $this->$scaleY,
  438.                     $externalLink['uri']
  439.                 );
  440.                 $this->adjustLastLink($externalLink$xPt$scaleX$yPt$newHeightPt$scaleY$importedPage);
  441.             }
  442.         }
  443.         return $newSize;
  444.     }
  445.     /**
  446.      * This method will add additional data to the last created link/annotation.
  447.      *
  448.      * It is separated because TCPDF uses its own logic to handle link annotations.
  449.      * This method is overwritten in the TCPDF implementation.
  450.      *
  451.      * @param array $externalLink
  452.      * @param float|int $xPt
  453.      * @param float|int $scaleX
  454.      * @param float|int $yPt
  455.      * @param float|int $newHeightPt
  456.      * @param float|int $scaleY
  457.      * @param array $importedPage
  458.      * @return void
  459.      */
  460.     protected function adjustLastLink($externalLink$xPt$scaleX$yPt$newHeightPt$scaleY$importedPage)
  461.     {
  462.         // let's create a relation of the newly created link to the data of the external link
  463.         $lastLink count($this->PageLinks[$this->page]);
  464.         $this->PageLinks[$this->page][$lastLink 1]['importedLink'] = $externalLink;
  465.         if (count($externalLink['quadPoints']) > 0) {
  466.             $quadPoints = [];
  467.             for ($i 0$n count($externalLink['quadPoints']); $i $n$i += 2) {
  468.                 $quadPoints[] = $xPt $externalLink['quadPoints'][$i] * $scaleX;
  469.                 $quadPoints[] = $this->hPt $yPt $newHeightPt $externalLink['quadPoints'][$i 1] * $scaleY;
  470.             }
  471.             $this->PageLinks[$this->page][$lastLink 1]['quadPoints'] = $quadPoints;
  472.         }
  473.     }
  474.     /**
  475.      * Get the size of an imported page.
  476.      *
  477.      * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
  478.      * aspect ratio.
  479.      *
  480.      * @param mixed $tpl The template id
  481.      * @param float|int|null $width The width.
  482.      * @param float|int|null $height The height.
  483.      * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P)
  484.      */
  485.     public function getImportedPageSize($tpl$width null$height null)
  486.     {
  487.         if (isset($this->importedPages[$tpl])) {
  488.             $importedPage $this->importedPages[$tpl];
  489.             if ($width === null && $height === null) {
  490.                 $width $importedPage['width'];
  491.                 $height $importedPage['height'];
  492.             } elseif ($width === null) {
  493.                 $width $height $importedPage['width'] / $importedPage['height'];
  494.             }
  495.             if ($height  === null) {
  496.                 $height $width $importedPage['height'] / $importedPage['width'];
  497.             }
  498.             if ($height <= 0. || $width <= 0.) {
  499.                 throw new \InvalidArgumentException('Width or height parameter needs to be larger than zero.');
  500.             }
  501.             return [
  502.                 'width' => $width,
  503.                 'height' => $height,
  504.                 => $width,
  505.                 => $height,
  506.                 'orientation' => $width $height 'L' 'P'
  507.             ];
  508.         }
  509.         return false;
  510.     }
  511.     /**
  512.      * Writes a PdfType object to the resulting buffer.
  513.      *
  514.      * @param PdfType $value
  515.      * @throws PdfTypeException
  516.      */
  517.     protected function writePdfType(PdfType $value)
  518.     {
  519.         if ($value instanceof PdfNumeric) {
  520.             if (\is_int($value->value)) {
  521.                 $this->_put($value->value ' 'false);
  522.             } else {
  523.                 $this->_put(\rtrim(\rtrim(\sprintf('%.5F'$value->value), '0'), '.') . ' 'false);
  524.             }
  525.         } elseif ($value instanceof PdfName) {
  526.             $this->_put('/' $value->value ' 'false);
  527.         } elseif ($value instanceof PdfString) {
  528.             $this->_put('(' $value->value ')'false);
  529.         } elseif ($value instanceof PdfHexString) {
  530.             $this->_put('<' $value->value '>'false);
  531.         } elseif ($value instanceof PdfBoolean) {
  532.             $this->_put($value->value 'true ' 'false 'false);
  533.         } elseif ($value instanceof PdfArray) {
  534.             $this->_put('['false);
  535.             foreach ($value->value as $entry) {
  536.                 $this->writePdfType($entry);
  537.             }
  538.             $this->_put(']');
  539.         } elseif ($value instanceof PdfDictionary) {
  540.             $this->_put('<<'false);
  541.             foreach ($value->value as $name => $entry) {
  542.                 $this->_put('/' $name ' 'false);
  543.                 $this->writePdfType($entry);
  544.             }
  545.             $this->_put('>>');
  546.         } elseif ($value instanceof PdfToken) {
  547.             $this->_put($value->value);
  548.         } elseif ($value instanceof PdfNull) {
  549.             $this->_put('null 'false);
  550.         } elseif ($value instanceof PdfStream) {
  551.             $this->writePdfType($value->value);
  552.             $this->_put('stream');
  553.             $this->_put($value->getStream());
  554.             $this->_put('endstream');
  555.         } elseif ($value instanceof PdfIndirectObjectReference) {
  556.             if (!isset($this->objectMap[$this->currentReaderId])) {
  557.                 $this->objectMap[$this->currentReaderId] = [];
  558.             }
  559.             if (!isset($this->objectMap[$this->currentReaderId][$value->value])) {
  560.                 $this->objectMap[$this->currentReaderId][$value->value] = ++$this->n;
  561.                 $this->objectsToCopy[$this->currentReaderId][] = $value->value;
  562.             }
  563.             $this->_put($this->objectMap[$this->currentReaderId][$value->value] . ' 0 R 'false);
  564.         } elseif ($value instanceof PdfIndirectObject) {
  565.             $n $this->objectMap[$this->currentReaderId][$value->objectNumber];
  566.             $this->_newobj($n);
  567.             $this->writePdfType($value->value);
  568.             // add newline before "endobj" for all objects in view to PDF/A conformance
  569.             if (
  570.                 !(
  571.                     ($value->value instanceof PdfArray) ||
  572.                     ($value->value instanceof PdfDictionary) ||
  573.                     ($value->value instanceof PdfToken) ||
  574.                     ($value->value instanceof PdfStream)
  575.                 )
  576.             ) {
  577.                 $this->_put("\n"false);
  578.             }
  579.             $this->_put('endobj');
  580.         }
  581.     }
  582. }