/** * Object constructor * * Note: PHP duplicates string, which is sent by value, only of it's updated. * Thus we don't need to care about overhead * * @param mixed $source * @param Zend_Pdf_ElementFactory_Interface $factory * @param boolean $load * @throws Zend_Exception */ public function __construct($source, Zend_Pdf_ElementFactory_Interface $factory, $load) { if ($load) { if (($pdfFile = @fopen($source, 'rb')) === false) { require_once LIB_DIR . '/Zend/Pdf/Exception.php'; throw new Zend_Pdf_Exception("Can not open '{$source}' file for reading."); } $data = ''; $byteCount = filesize($source); while ($byteCount > 0 && !feof($pdfFile)) { $nextBlock = fread($pdfFile, $byteCount); if ($nextBlock === false) { require_once LIB_DIR . '/Zend/Pdf/Exception.php'; throw new Zend_Pdf_Exception("Error occured while '{$source}' file reading."); } $data .= $nextBlock; $byteCount -= strlen($nextBlock); } if ($byteCount != 0) { require_once LIB_DIR . '/Zend/Pdf/Exception.php'; throw new Zend_Pdf_Exception("Error occured while '{$source}' file reading."); } fclose($pdfFile); $this->_stringParser = new Zend_Pdf_StringParser($data, $factory); } else { $this->_stringParser = new Zend_Pdf_StringParser($source, $factory); } $pdfVersionComment = $this->_stringParser->readComment(); if (substr($pdfVersionComment, 0, 5) != '%PDF-') { require_once LIB_DIR . '/Zend/Pdf/Exception.php'; throw new Zend_Pdf_Exception('File is not a PDF.'); } $pdfVersion = substr($pdfVersionComment, 5); if (version_compare($pdfVersion, '0.9', '<') || version_compare($pdfVersion, '1.61', '>=')) { /** * @todo * To support PDF versions 1.5 (Acrobat 6) and PDF version 1.7 (Acrobat 7) * Stream compression filter must be implemented (for compressed object streams). * Cross reference streams must be implemented */ require_once LIB_DIR . '/Zend/Pdf/Exception.php'; throw new Zend_Pdf_Exception(sprintf('Unsupported PDF version. Zend_Pdf supports PDF 1.0-1.4. Current version - \'%f\'', $pdfVersion)); } $this->_pdfVersion = $pdfVersion; $this->_stringParser->offset = strrpos($this->_stringParser->data, '%%EOF'); if ($this->_stringParser->offset === false || strlen($this->_stringParser->data) - $this->_stringParser->offset > 7) { require_once LIB_DIR . '/Zend/Pdf/Exception.php'; throw new Zend_Pdf_Exception('Pdf file syntax error. End-of-fle marker expected at the end of file.'); } $this->_stringParser->offset--; /** * Go to end of cross-reference table offset */ while (Zend_Pdf_StringParser::isWhiteSpace(ord($this->_stringParser->data[$this->_stringParser->offset])) && $this->_stringParser->offset > 0) { $this->_stringParser->offset--; } /** * Go to the start of cross-reference table offset */ while (!Zend_Pdf_StringParser::isWhiteSpace(ord($this->_stringParser->data[$this->_stringParser->offset])) && $this->_stringParser->offset > 0) { $this->_stringParser->offset--; } /** * Go to the end of 'startxref' keyword */ while (Zend_Pdf_StringParser::isWhiteSpace(ord($this->_stringParser->data[$this->_stringParser->offset])) && $this->_stringParser->offset > 0) { $this->_stringParser->offset--; } /** * Go to the white space (eol marker) before 'startxref' keyword */ $this->_stringParser->offset -= 9; $nextLexeme = $this->_stringParser->readLexeme(); if ($nextLexeme != 'startxref') { require_once LIB_DIR . '/Zend/Pdf/Exception.php'; throw new Zend_Pdf_Exception(sprintf('Pdf file syntax error. \'startxref\' keyword expected. Offset - 0x%X.', $this->_stringParser->offset - strlen($nextLexeme))); } $startXref = $this->_stringParser->readLexeme(); if (!ctype_digit($startXref)) { require_once LIB_DIR . '/Zend/Pdf/Exception.php'; throw new Zend_Pdf_Exception(sprintf('Pdf file syntax error. Cross-reference table offset must contain only digits. Offset - 0x%X.', $this->_stringParser->offset - strlen($nextLexeme))); } $this->_trailer = $this->_loadXRefTable($startXref); $factory->setObjectCount($this->_trailer->Size->value); }
/** * Set object counter * * @param integer $objCount */ public function setObjectCount($objCount) { $this->_factory->setObjectCount($objCount); }
/** * Rollback document $steps number of revisions. * This method must be invoked before any changes, applied to the document. * Otherwise behavior is undefined. * * @param integer $steps */ public function rollback($steps) { for ($count = 0; $count < $steps; $count++) { if ($this->_trailer->getPrev() !== null && $this->_trailer->getPrev()->Root !== null) { $this->_trailer = $this->_trailer->getPrev(); } else { break; } } $this->_objFactory->setObjectCount($this->_trailer->Size->value); // Mark content as modified to force new trailer generation at render time $this->_trailer->Root->touch(); $this->pages = array(); $this->_loadPages($this->_trailer->Root->Pages); }