Skip to content
Browse files

Merge branch 'master' of git://github.com/zendframework/zf2

  • Loading branch information...
2 parents cd3deb5 + dc86be6 commit c7c402a3a89db4883d43001dc8eadc49c1c058fd @sgehrig sgehrig committed
Showing with 995 additions and 913 deletions.
  1. +78 −35 documentation/manual/en/module_specs/Zend_Pdf-Pages.xml
  2. +3 −2 library/Zend/Pdf/Action/AbstractAction.php
  3. +20 −0 library/Zend/Pdf/InternalType/AbstractTypeObject.php
  4. +33 −0 library/Zend/Pdf/InternalType/ArrayObject.php
  5. +47 −1 library/Zend/Pdf/InternalType/DictionaryObject.php
  6. +39 −2 library/Zend/Pdf/InternalType/IndirectObject.php
  7. +26 −0 library/Zend/Pdf/InternalType/IndirectObjectReference.php
  8. +12 −5 library/Zend/Pdf/InternalType/StreamContent.php
  9. +76 −45 library/Zend/Pdf/InternalType/StreamObject.php
  10. +298 −24 library/Zend/Pdf/ObjectFactory.php
  11. +0 −443 library/Zend/Pdf/ObjectFactory/ElementFactory.php
  12. +0 −233 library/Zend/Pdf/ObjectFactory/Proxy.php
  13. +4 −4 library/Zend/Pdf/Outline/AbstractOutline.php
  14. +4 −4 library/Zend/Pdf/Outline/Created.php
  15. +4 −4 library/Zend/Pdf/Outline/Loaded.php
  16. +82 −30 library/Zend/Pdf/Page.php
  17. +1 −1 library/Zend/Pdf/PdfDocument.php
  18. +6 −6 library/Zend/Pdf/PdfParser/DataParser.php
  19. +56 −1 library/Zend/Pdf/Resource/AbstractResource.php
  20. +83 −0 library/Zend/Pdf/Resource/Extractor.php
  21. +2 −2 library/Zend/Pdf/Resource/Image/Png.php
  22. +1 −1 library/Zend/Session/Configuration/StandardConfiguration.php
  23. +1 −53 tests/Bootstrap.php
  24. +3 −3 tests/Zend/Pdf/ActionTest.php
  25. +11 −11 tests/Zend/Pdf/InternalType/ObjectTest.php
  26. +3 −3 tests/Zend/Pdf/InternalType/StreamObjectTest.php
  27. +22 −0 tests/Zend/Session/ContainerTest.php
  28. +22 −0 tests/Zend/Session/SessionManagerTest.php
  29. +58 −0 tests/_autoload.php
View
113 documentation/manual/en/module_specs/Zend_Pdf-Pages.xml
@@ -8,49 +8,42 @@
<para>
The pages in a <acronym>PDF</acronym> document are represented as
- <classname>Zend_Pdf_Page</classname> instances in <classname>Zend_Pdf</classname>.
+ <classname>\Zend\Pdf\Page</classname> instances in <code>Zend\Pdf</code>.
</para>
<para>
<acronym>PDF</acronym> pages either are loaded from an existing <acronym>PDF</acronym>
- or created using the <classname>Zend_Pdf</classname> <acronym>API</acronym>.
+ or created using the <code>Zend\Pdf</code> <acronym>API</acronym>.
</para>
<para>
- New pages can be created by instantiating new <classname>Zend_Pdf_Page</classname>
- objects directly or by calling the <methodname>Zend_Pdf::newPage()</methodname> method,
- which returns a <classname>Zend_Pdf_Page</classname> object.
- <methodname>Zend_Pdf::newPage()</methodname> creates a page that is already attached to
- a document. Unattached pages can't be used with multiple <acronym>PDF</acronym>
- documents, but they are somewhat more performant.
-
- <footnote>
- <para>
- It's a limitation of current Zend Framework version. It will be eliminated in
- future versions. But unattached pages will always give better (more optimal)
- result for sharing pages between documents.
- </para>
- </footnote>
+ New pages can be created by instantiating new <classname>\Zend\Pdf\Page</classname>
+ objects directly or by calling the <methodname>\Zend\Pdf\PdfDocument::newPage()</methodname> method,
+ which returns a <classname>\Zend\Pdf\Page</classname> object.
+ <methodname>\Zend\Pdf\PdfDocument::newPage()</methodname> creates a page that is already attached to
+ a document. Attached pages can't be used with another <acronym>PDF</acronym>
+ documents until it's not cloned. See <link linkend="zend.pdf.pages.cloning">Page
+ cloning</link> section for the details.
</para>
<para>
- The <methodname>Zend_Pdf::newPage()</methodname> method and the
- <classname>Zend_Pdf_Page</classname> constructor take the same parameters specifying
+ The <methodname>\Zend\Pdf\PdfDocument::newPage()</methodname> method and the
+ <classname>\Zend\Pdf\Page</classname> constructor take the same parameters specifying
page size. They can take either the size of page ($x, $y) in points (1/72 inch) or a
predefined constant representing a page type:
<itemizedlist>
- <listitem><para>Zend_Pdf_Page::SIZE_A4</para></listitem>
- <listitem><para>Zend_Pdf_Page::SIZE_A4_LANDSCAPE</para></listitem>
- <listitem><para>Zend_Pdf_Page::SIZE_LETTER</para></listitem>
- <listitem><para>Zend_Pdf_Page::SIZE_LETTER_LANDSCAPE</para></listitem>
+ <listitem><para>\Zend\Pdf\Page::SIZE_A4</para></listitem>
+ <listitem><para>\Zend\Pdf\Page::SIZE_A4_LANDSCAPE</para></listitem>
+ <listitem><para>\Zend\Pdf\Page::SIZE_LETTER</para></listitem>
+ <listitem><para>\Zend\Pdf\Page::SIZE_LETTER_LANDSCAPE</para></listitem>
</itemizedlist>
</para>
<para>
Document pages are stored in the <varname>$pages</varname> public attribute of the
- <classname>Zend_Pdf</classname> class. The attribute holds an array of
- <classname>Zend_Pdf_Page</classname> objects and completely defines the instances and
+ <classname>\Zend\Pdf\PdfDocument</classname> class. The attribute holds an array of
+ <classname>\Zend\Pdf\Page</classname> objects and completely defines the instances and
order of pages. This array can be manipulated like any other <acronym>PHP</acronym>
array:
</para>
@@ -64,9 +57,9 @@
$pdf->pages = array_reverse($pdf->pages);
...
// Add new page
-$pdf->pages[] = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_A4);
+$pdf->pages[] = new \Zend\Pdf\Page(\Zend\Pdf\Page::SIZE_A4);
// Add new page
-$pdf->pages[] = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
+$pdf->pages[] = $pdf->newPage(\Zend\Pdf\Page::SIZE_A4);
// Remove specified page.
unset($pdf->pages[$id]);
@@ -80,12 +73,12 @@ unset($pdf->pages[$id]);
<title>Page cloning</title>
<para>
- Existing <acronym>PDF</acronym> page can be cloned by creating new
- <classname>Zend_Pdf_Page</classname> object with existing page as a parameter:
+ Existing <acronym>PDF</acronym> page can be duplicated by creating new
+ <classname>\Zend\Pdf\Page</classname> object with existing page as a parameter:
</para>
<example id="zend.pdf.pages.example-2">
- <title>Cloning existing page</title>
+ <title>Duplicating existing page</title>
<programlisting language="php"><![CDATA[
...
@@ -93,12 +86,14 @@ unset($pdf->pages[$id]);
$template = $pdf->pages[$templatePageIndex];
...
// Add new page
-$page1 = new Zend_Pdf_Page($template);
+$page1 = new \Zend\Pdf\Page($template);
+$page1->drawText('Some text...', $x, $y);
$pdf->pages[] = $page1;
...
// Add another page
-$page2 = new Zend_Pdf_Page($template);
+$page2 = new \Zend\Pdf\Page($template);
+$page2->drawText('Another text...', $x, $y);
$pdf->pages[] = $page2;
...
@@ -115,11 +110,59 @@ unset($pdf->pages[$templatePageIndex]);
<caution>
<para>
- Important! Cloned page shares some <acronym>PDF</acronym> resources with a template
- page, so it can be used only within the same document as a template page. Modified
- document can be saved as new one.
+ Important! Duplicated page shares some <acronym>PDF</acronym> resources with
+ a template page, so it can be used only within the same document as a template page.
+ Modified document can be saved as new one.
</para>
- </caution>
+</caution>
+
+ <para>
+ <code>clone</code> operator may be used to create page which is not attached to any document.
+ It takes more time than duplicating page since it needs to copy all dependent objects
+ (used fonts, images and other resources), but it allows to use pages from different source
+ documents to create new one:
+ </para>
+
+ <example id="zend.pdf.pages.example-3">
+ <title>Cloning existing page</title>
+
+ <programlisting language="php"><![CDATA[
+$page1 = clone $pdf1->pages[$templatePageIndex1];
+$page2 = clone $pdf2->pages[$templatePageIndex2];
+$page1->drawText('Some text...', $x, $y);
+$page2->drawText('Another text...', $x, $y);
+...
+$pdf = new \Zend\Pdf\PdfDocument();
+$pdf->pages[] = $page1;
+$pdf->pages[] = $page2;
+]]></programlisting>
+ </example>
+
+ <para>
+ If several template pages are planned to be used as templates then it could be more efficient
+ to utilize <classname>\Zend\Pdf\Resource\Extractor</classname> class which gives an ability
+ to share resources between cloned pages - fonts, images, etc. (otherwise new resource copy
+ will be created for each cloned page):
+ </para>
+
+ <example id="zend.pdf.pages.example-4">
+ <title>
+ Cloning existing page using <classname>\Zend\Pdf\Resource\Extractor</classname> class
+ </title>
+
+ <programlisting language="php"><![CDATA[
+$extractor = new \Zend\Pdf\Resource\Extractor();
+....
+$page1 = $extractor->clonePage($pdf->pages[$templatePageIndex1]);
+$page2 = $extractor->clonePage($pdf->pages[$templatePageIndex2]);
+$page1->drawText('Some text...', $x, $y);
+$page2->drawText('Another text...', $x, $y);
+...
+$pdf = new Zend_Pdf();
+$pdf->pages[] = $page1;
+$pdf->pages[] = $page2;
+]]></programlisting>
+ </example>
</sect2>
</sect1>
<!--
View
5 library/Zend/Pdf/Action/AbstractAction.php
@@ -24,6 +24,7 @@
* @namespace
*/
namespace Zend\Pdf\Action;
+use Zend\Pdf\ObjectFactory;
use Zend\Pdf\InternalType;
use Zend\Pdf;
@@ -249,12 +250,12 @@ public function getResource()
* Returns dictionary indirect object or reference
*
* @internal
- * @param \Zend\Pdf\ObjectFactory $factory Object factory for newly created indirect objects
+ * @param \Zend\Pdf\ObjectFactory $factory Object factory for newly created indirect objects
* @param SplObjectStorage $processedActions list of already processed actions
* (used to prevent infinity loop caused by cyclic references)
* @return \Zend\Pdf\InternalType\IndirectObject|\Zend\Pdf\InternalType\IndirectObjectReference
*/
- public function dumpAction(Pdf\ObjectFactory $factory, \SplObjectStorage $processedActions = null)
+ public function dumpAction(ObjectFactory $factory, \SplObjectStorage $processedActions = null)
{
if ($processedActions === null) {
$processedActions = new \SplObjectStorage();
View
20 library/Zend/Pdf/InternalType/AbstractTypeObject.php
@@ -24,6 +24,7 @@
* @namespace
*/
namespace Zend\Pdf\InternalType;
+use Zend\Pdf;
/**
* PDF file element implementation
@@ -76,6 +77,25 @@
abstract public function toString($factory = null);
+ const CLONE_MODE_SKIP_PAGES = 1; // Do not follow pages during deep copy process
+ const CLONE_MODE_FORCE_CLONING = 2; // Force top level object cloning even it's already processed
+
+ /**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @todo It's necessary to check if SplObjectStorage class works faster
+ * (Needs PHP 5.3.x to attach object _with_ additional data to storage)
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ */
+ public function makeClone(Pdf\ObjectFactory $factory, array &$processed, $mode)
+ {
+ return clone $this;
+ }
+
/**
* Set top level parent indirect object.
*
View
33 library/Zend/Pdf/InternalType/ArrayObject.php
@@ -133,6 +133,39 @@ public function toString($factory = null)
}
/**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ */
+ public function makeClone(Pdf\ObjectFactory $factory, array &$processed, $mode)
+ {
+ $newArray = new self();
+
+ foreach ($this->items as $key => $value) {
+ $newArray->items[$key] = $value->makeClone($factory, $processed, $mode);
+ }
+
+ return $newArray;
+ }
+
+ /**
+ * Set top level parent indirect object.
+ *
+ * @param \Zend\Pdf\InternalType\IndirectObject $parent
+ */
+ public function setParentObject(IndirectObject $parent)
+ {
+ parent::setParentObject($parent);
+
+ foreach ($this->items as $item) {
+ $item->setParentObject($parent);
+ }
+ }
+
+ /**
* Convert PDF element to PHP type.
*
* Dictionary is returned as an associative array
View
48 library/Zend/Pdf/InternalType/DictionaryObject.php
@@ -137,7 +137,6 @@ public function getType()
return AbstractTypeObject::TYPE_DICTIONARY;
}
-
/**
* Return object as string
*
@@ -167,6 +166,53 @@ public function toString($factory = null)
return $outStr;
}
+ /**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ * @throws \Zend\Pdf\Exception
+ */
+ public function makeClone(Pdf\ObjectFactory $factory, array &$processed, $mode)
+ {
+ if (isset($this->_items['Type'])) {
+ if ($this->_items['Type']->value == 'Pages') {
+ // It's a page tree node
+ // skip it and its children
+ return new NullObject();
+ }
+
+ if ($this->_items['Type']->value == 'Page' &&
+ $mode == AbstractTypeObject::CLONE_MODE_SKIP_PAGES
+ ) {
+ // It's a page node, skip it
+ return new NullObject();
+ }
+ }
+
+ $newDictionary = new self();
+ foreach ($this->_items as $key => $value) {
+ $newDictionary->_items[$key] = $value->makeClone($factory, $processed, $mode);
+ }
+
+ return $newDictionary;
+ }
+
+ /**
+ * Set top level parent indirect object.
+ *
+ * @param \Zend\Pdf\InternalType\IndirectObject $parent
+ */
+ public function setParentObject(IndirectObject $parent)
+ {
+ parent::setParentObject($parent);
+
+ foreach ($this->_items as $item) {
+ $item->setParentObject($parent);
+ }
+ }
/**
* Convert PDF element to PHP type.
View
41 library/Zend/Pdf/InternalType/IndirectObject.php
@@ -31,7 +31,7 @@
* PDF file 'indirect object' element implementation
*
* @uses \Zend\Pdf\InternalType\AbstractTypeObject
- * @uses \Zend\Pdf\ObjectFactory\ElementFactory
+ * @uses \Zend\Pdf\ObjectFactory
* @uses \Zend\Pdf\Exception
* @category Zend
* @package Zend_PDF
@@ -78,7 +78,10 @@ class IndirectObject extends AbstractTypeObject
* @param \Zend\Pdf\ObjectFactory $factory
* @throws \Zend\Pdf\Exception
*/
- public function __construct(AbstractTypeObject $val, $objNum, $genNum, ObjectFactory $factory)
+ public function __construct(AbstractTypeObject $val,
+ $objNum,
+ $genNum,
+ ObjectFactory $factory)
{
if ($val instanceof self) {
throw new Pdf\Exception('Object number must not be an instance of \Zend\Pdf\InternalType\IndirectObject.');
@@ -215,6 +218,40 @@ public function __call($method, $args)
return call_user_func_array(array($this->_value, $method), $args);
}
+ /**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ */
+ public function makeClone(ObjectFactory $factory, array &$processed, $mode)
+ {
+ $id = spl_object_hash($this);
+ if (isset($processed[$id])) {
+ // Do nothing if object is already processed
+ // return it
+ return $processed[$id];
+ }
+
+ // Create obect with null value and register it in $processed container
+ $processed[$id] = $clonedObject = $factory->newObject(new NullObject());
+
+ // Pecursively process actual data
+ $clonedObject->_value = $this->_value->makeClone($factory, $processed, $mode);
+
+ if ($clonedObject->_value instanceof NullObject) {
+ // Do not store null objects within $processed container since it may be filtered
+ // by $mode parameter but used in some future pass
+ unset($processed[$id]);
+
+ // Return direct null object
+ return $clonedObject->_value;
+ }
+
+ return $clonedObject;
+ }
/**
* Mark object as modified, to include it into new PDF file segment
View
26 library/Zend/Pdf/InternalType/IndirectObjectReference.php
@@ -185,6 +185,32 @@ private function _dereference()
}
/**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ */
+ public function makeClone(Pdf\ObjectFactory $factory, array &$processed, $mode)
+ {
+ if ($this->_ref === null) {
+ $this->_dereference();
+ }
+
+ // This code duplicates code in \Zend\Pdf\InternalType\IndirectObject class,
+ // but allows to avoid unnecessary method call in most cases
+ $id = spl_object_hash($this->_ref);
+ if (isset($processed[$id])) {
+ // Do nothing if object is already processed
+ // return it
+ return $processed[$id];
+ }
+
+ return $this->_ref->makeClone($factory, $processed, $mode);
+ }
+
+ /**
* Mark object as modified, to include it into new PDF file segment.
*/
public function touch()
View
17 library/Zend/Pdf/InternalType/StreamContent.php
@@ -46,7 +46,6 @@ class StreamContent extends AbstractTypeObject
*/
public $value;
-
/**
* Object constructor
*
@@ -57,7 +56,6 @@ public function __construct($val)
$this->value = Pdf\PdfDocument::getMemoryManager()->create($val);
}
-
/**
* Return type of the element.
*
@@ -68,7 +66,6 @@ public function getType()
return AbstractTypeObject::TYPE_STREAM;
}
-
/**
* Stream length.
* (Method is used to avoid string copying, which may occurs in some cases)
@@ -80,7 +77,6 @@ public function length()
return strlen($this->value->getRef());
}
-
/**
* Clear stream
*
@@ -92,7 +88,6 @@ public function clear()
$this->value->touch();
}
-
/**
* Append value to a stream
*
@@ -105,6 +100,18 @@ public function append($val)
$this->value->touch();
}
+ /**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ */
+ public function makeClone(Pdf\ObjectFactory $factory, array &$processed, $mode)
+ {
+ return new self($this->value->getRef());
+ }
/**
* Return object as string
View
121 library/Zend/Pdf/InternalType/StreamObject.php
@@ -65,13 +65,13 @@ class StreamObject extends IndirectObject
/**
* Stored original stream object dictionary.
- * Used to decode stream during an access time.
+ * Used to decode stream at access time.
*
- * The only properties, which affect decoding, are sored here.
+ * The only properties affecting decoding are sored here.
*
* @var array|null
*/
- private $_originalDictionary = null;
+ private $_initialDictionaryData = null;
/**
* Object constructor
@@ -99,77 +99,80 @@ public function __construct($val, $objNum, $genNum, ObjectFactory $factory, $dic
/**
- * Store original dictionary information in $_originalDictionary class member.
- * Used to store information and to normalize filters information before defiltering.
+ * Extract dictionary data which are used to store information and to normalize filters
+ * information before defiltering.
*
+ * @return array
*/
- private function _storeOriginalDictionary()
+ private function _extractDictionaryData()
{
- $this->_originalDictionary = array();
+ $dictionaryArray = array();
- $this->_originalDictionary['Filter'] = array();
- $this->_originalDictionary['DecodeParms'] = array();
+ $dictionaryArray['Filter'] = array();
+ $dictionaryArray['DecodeParms'] = array();
if ($this->_dictionary->Filter === null) {
// Do nothing.
} else if ($this->_dictionary->Filter->getType() == AbstractTypeObject::TYPE_ARRAY) {
foreach ($this->_dictionary->Filter->items as $id => $filter) {
- $this->_originalDictionary['Filter'][$id] = $filter->value;
- $this->_originalDictionary['DecodeParms'][$id] = array();
+ $dictionaryArray['Filter'][$id] = $filter->value;
+ $dictionaryArray['DecodeParms'][$id] = array();
if ($this->_dictionary->DecodeParms !== null ) {
if ($this->_dictionary->DecodeParms->items[$id] !== null &&
$this->_dictionary->DecodeParms->items[$id]->value !== null ) {
foreach ($this->_dictionary->DecodeParms->items[$id]->getKeys() as $paramKey) {
- $this->_originalDictionary['DecodeParms'][$id][$paramKey] =
+ $dictionaryArray['DecodeParms'][$id][$paramKey] =
$this->_dictionary->DecodeParms->items[$id]->$paramKey->value;
}
}
}
}
} else if ($this->_dictionary->Filter->getType() != AbstractTypeObject::TYPE_NULL) {
- $this->_originalDictionary['Filter'][0] = $this->_dictionary->Filter->value;
- $this->_originalDictionary['DecodeParms'][0] = array();
+ $dictionaryArray['Filter'][0] = $this->_dictionary->Filter->value;
+ $dictionaryArray['DecodeParms'][0] = array();
if ($this->_dictionary->DecodeParms !== null ) {
foreach ($this->_dictionary->DecodeParms->getKeys() as $paramKey) {
- $this->_originalDictionary['DecodeParms'][0][$paramKey] =
+ $dictionaryArray['DecodeParms'][0][$paramKey] =
$this->_dictionary->DecodeParms->$paramKey->value;
}
}
}
if ($this->_dictionary->F !== null) {
- $this->_originalDictionary['F'] = $this->_dictionary->F->value;
+ $dictionaryArray['F'] = $this->_dictionary->F->value;
}
- $this->_originalDictionary['FFilter'] = array();
- $this->_originalDictionary['FDecodeParms'] = array();
+ $dictionaryArray['FFilter'] = array();
+ $dictionaryArray['FDecodeParms'] = array();
if ($this->_dictionary->FFilter === null) {
// Do nothing.
} else if ($this->_dictionary->FFilter->getType() == AbstractTypeObject::TYPE_ARRAY) {
foreach ($this->_dictionary->FFilter->items as $id => $filter) {
- $this->_originalDictionary['FFilter'][$id] = $filter->value;
- $this->_originalDictionary['FDecodeParms'][$id] = array();
+ $dictionaryArray['FFilter'][$id] = $filter->value;
+ $dictionaryArray['FDecodeParms'][$id] = array();
if ($this->_dictionary->FDecodeParms !== null ) {
if ($this->_dictionary->FDecodeParms->items[$id] !== null &&
$this->_dictionary->FDecodeParms->items[$id]->value !== null) {
foreach ($this->_dictionary->FDecodeParms->items[$id]->getKeys() as $paramKey) {
- $this->_originalDictionary['FDecodeParms'][$id][$paramKey] =
+ $dictionaryArray['FDecodeParms'][$id][$paramKey] =
$this->_dictionary->FDecodeParms->items[$id]->items[$paramKey]->value;
}
}
}
}
} else {
- $this->_originalDictionary['FFilter'][0] = $this->_dictionary->FFilter->value;
- $this->_originalDictionary['FDecodeParms'][0] = array();
+ $dictionaryArray['FFilter'][0] = $this->_dictionary->FFilter->value;
+ $dictionaryArray['FDecodeParms'][0] = array();
if ($this->_dictionary->FDecodeParms !== null ) {
foreach ($this->_dictionary->FDecodeParms->getKeys() as $paramKey) {
- $this->_originalDictionary['FDecodeParms'][0][$paramKey] =
+ $dictionaryArray['FDecodeParms'][0][$paramKey] =
$this->_dictionary->FDecodeParms->items[$paramKey]->value;
}
}
}
+
+ return $dictionaryArray;
}
/**
@@ -179,20 +182,20 @@ private function _storeOriginalDictionary()
*/
private function _decodeStream()
{
- if ($this->_originalDictionary === null) {
- $this->_storeOriginalDictionary();
+ if ($this->_initialDictionaryData === null) {
+ $this->_initialDictionaryData = $this->_extractDictionaryData();
}
/**
* All applied stream filters must be processed to decode stream.
* If we don't recognize any of applied filetrs an exception should be thrown here
*/
- if (isset($this->_originalDictionary['F'])) {
+ if (isset($this->_initialDictionaryData['F'])) {
/** @todo Check, how external files can be processed. */
throw new Pdf\Exception('External filters are not supported now.');
}
- foreach ($this->_originalDictionary['Filter'] as $id => $filterName ) {
+ foreach ($this->_initialDictionaryData['Filter'] as $id => $filterName ) {
$valueRef = &$this->_value->value->getRef();
$this->_value->value->touch();
switch ($filterName) {
@@ -206,12 +209,12 @@ private function _decodeStream()
case 'FlateDecode':
$valueRef = CompressionFilter\Flate::decode($valueRef,
- $this->_originalDictionary['DecodeParms'][$id]);
+ $this->_initialDictionaryData['DecodeParms'][$id]);
break;
case 'LZWDecode':
$valueRef = CompressionFilter\Lzw::decode($valueRef,
- $this->_originalDictionary['DecodeParms'][$id]);
+ $this->_initialDictionaryData['DecodeParms'][$id]);
break;
case 'RunLengthDecode':
@@ -237,12 +240,12 @@ private function _encodeStream()
* All applied stream filters must be processed to encode stream.
* If we don't recognize any of applied filetrs an exception should be thrown here
*/
- if (isset($this->_originalDictionary['F'])) {
+ if (isset($this->_initialDictionaryData['F'])) {
/** @todo Check, how external files can be processed. */
throw new Pdf\Exception('External filters are not supported now.');
}
- $filters = array_reverse($this->_originalDictionary['Filter'], true);
+ $filters = array_reverse($this->_initialDictionaryData['Filter'], true);
foreach ($filters as $id => $filterName ) {
$valueRef = &$this->_value->value->getRef();
@@ -258,12 +261,12 @@ private function _encodeStream()
case 'FlateDecode':
$valueRef = CompressionFilter\Flate::encode($valueRef,
- $this->_originalDictionary['DecodeParms'][$id]);
+ $this->_initialDictionaryData['DecodeParms'][$id]);
break;
case 'LZWDecode':
$valueRef = CompressionFilter\Lzw::encode($valueRef,
- $this->_originalDictionary['DecodeParms'][$id]);
+ $this->_initialDictionaryData['DecodeParms'][$id]);
break;
case 'RunLengthDecode':
@@ -291,8 +294,8 @@ public function __get($property)
/**
* If stream is note decoded yet, then store original decoding options (do it only once).
*/
- if (( !$this->_streamDecoded ) && ($this->_originalDictionary === null)) {
- $this->_storeOriginalDictionary();
+ if (( !$this->_streamDecoded ) && ($this->_initialDictionaryData === null)) {
+ $this->_initialDictionaryData = $this->_extractDictionaryData();
}
return $this->_dictionary;
@@ -365,6 +368,38 @@ public function __call($method, $args)
}
/**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ */
+ public function makeClone(ObjectFactory $factory, array &$processed, $mode)
+ {
+ $id = spl_object_hash($this);
+ if (isset($processed[$id])) {
+ // Do nothing if object is already processed
+ // return it
+ return $processed[$id];
+ }
+
+ $streamValue = $this->_value;
+ $streamDictionary = $this->_dictionary->makeClone($factory, $processed, $mode);
+
+ // Make new empty instance of stream object and register it in $processed container
+ $processed[$id] = $clonedObject = $factory->newStreamObject('');
+
+ // Copy current object data and state
+ $clonedObject->_dictionary = $this->_dictionary->makeClone($factory, $processed, $mode);
+ $clonedObject->_value = $this->_value->makeClone($factory, $processed, $mode);
+ $clonedObject->_initialDictionaryData = $this->_initialDictionaryData;
+ $clonedObject->_streamDecoded = $this->_streamDecoded;
+
+ return $clonedObject;
+ }
+
+ /**
* Dump object to a string to save within PDF file
*
* $factory parameter defines operation context.
@@ -377,18 +412,14 @@ public function dump(ObjectFactory $factory)
$shift = $factory->getEnumerationShift($this->_factory);
if ($this->_streamDecoded) {
- $this->_storeOriginalDictionary();
+ $this->_initialDictionaryData = $this->_extractDictionaryData();
$this->_encodeStream();
- } else if ($this->_originalDictionary != null) {
- $startDictionary = $this->_originalDictionary;
- $this->_storeOriginalDictionary();
- $newDictionary = $this->_originalDictionary;
+ } else if ($this->_initialDictionaryData != null) {
+ $newDictionary = $this->_extractDictionaryData();
- if ($startDictionary !== $newDictionary) {
- $this->_originalDictionary = $startDictionary;
+ if ($this->_initialDictionaryData !== $newDictionary) {
$this->_decodeStream();
-
- $this->_originalDictionary = $newDictionary;
+ $this->_initialDictionaryData = $newDictionary;
$this->_encodeStream();
}
}
View
322 library/Zend/Pdf/ObjectFactory.php
@@ -25,58 +25,195 @@
*/
namespace Zend\Pdf;
+use Zend\Pdf\ObjectFactory\UpdateInfoContainer,
+ Zend\Pdf,
+ Zend\Pdf\InternalType;
+
/**
- * PDF element factory interface.
+ * PDF element factory.
* Responsibility is to log PDF changes
*
+ * @uses SplObjectStorage
+ * @uses \Zend\Pdf\ObjectFactory
+ * @uses \Zend\Pdf\ObjectFactory\UpdateInfoContainer
+ * @uses \Zend\Pdf\InternalType\IndirectObject
+ * @uses \Zend\Pdf\InternalType\StreamObject
+ * @uses \Zend\Pdf\Exception
* @package Zend_PDF
* @package Zend_PDF_Internal
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-interface ObjectFactory
+class ObjectFactory
{
/**
- * Close factory and clean-up resources
+ * List of the modified objects.
+ * Also contains new and removed objects
*
- * @internal
+ * Array: ojbectNumber => \Zend\Pdf\InternalType\IndirectObject
+ *
+ * @var array
+ */
+ private $_modifiedObjects = array();
+
+ /**
+ * List of the removed objects
+ *
+ * Array: ojbectNumber => \Zend\Pdf\InternalType\IndirectObject
+ *
+ * @var SplObjectStorage
*/
- public function close();
+ private $_removedObjects;
/**
- * Get source factory object
+ * List of registered objects.
+ * Used for resources clean up when factory is destroyed.
*
+ * Array of \Zend\Pdf\InternalType\AbstractTypeObject objects
+ *
+ * @var array
+ */
+ private $_registeredObjects = array();
+
+ /**
+ * PDF object counter.
+ * Actually it's an object number for new PDF object
+ *
+ * @var integer
+ */
+ private $_objectCount;
+
+
+ /**
+ * List of the attached object factories.
+ * Array of \Zend\Pdf\ObjectFactory objects
+ *
+ * @var array
+ */
+ private $_attachedFactories = array();
+
+
+ /**
+ * Factory internal id
+ *
+ * @var integer
+ */
+ private $_factoryId;
+
+ /**
+ * Identity, used for factory id generation
+ *
+ * @var integer
+ */
+ private static $_identity = 0;
+
+
+ /**
+ * Internal cache to save calculated shifts
+ *
+ * @var array
+ */
+ private $_shiftCalculationCache = array();
+
+
+ /**
+ * Object constructor
+ *
+ * @param integer $objCount
+ */
+ public function __construct($objCount)
+ {
+ $this->_objectCount = (int)$objCount;
+ $this->_factoryId = self::$_identity++;
+ $this->_removedObjects = new \SplObjectStorage();
+ }
+
+
+ /**
+ * Factory generator
+ *
+ * @param integer $objCount
* @return \Zend\Pdf\ObjectFactory
*/
- public function resolve();
+ static public function createFactory($objCount)
+ {
+ return new self($objCount);
+ }
+
+ /**
+ * Close factory and clean-up resources
+ *
+ * @internal
+ */
+ public function close()
+ {
+ $this->_modifiedObjects = null;
+ $this->_removedObjects = null;
+ $this->_attachedFactories = null;
+
+ foreach ($this->_registeredObjects as $obj) {
+ $obj->cleanUp();
+ }
+ $this->_registeredObjects = null;
+ }
/**
* Get factory ID
*
* @return integer
*/
- public function getId();
+ public function getId()
+ {
+ return $this->_factoryId;
+ }
/**
* Set object counter
*
* @param integer $objCount
*/
- public function setObjectCount($objCount);
+ public function setObjectCount($objCount)
+ {
+ $this->_objectCount = (int)$objCount;
+ }
/**
* Get object counter
*
* @return integer
*/
- public function getObjectCount();
+ public function getObjectCount()
+ {
+ $count = $this->_objectCount;
+
+ foreach ($this->_attachedFactories as $attached) {
+ $count += $attached->getObjectCount() - 1; // -1 as "0" object is a special case and shared between factories
+ }
+
+ return $count;
+ }
+
/**
* Attach factory to the current;
*
* @param \Zend\Pdf\ObjectFactory $factory
*/
- public function attach(ObjectFactory $factory);
+ public function attach(ObjectFactory $factory)
+ {
+ if ( $factory === $this || isset($this->_attachedFactories[$factory->getId()])) {
+ /**
+ * Don't attach factory twice.
+ * We do not check recusively because of nature of attach operation
+ * (Pages are always attached to the Documents, Fonts are always attached
+ * to the pages even if pages already use Document level object factory and so on)
+ */
+ return;
+ }
+
+ $this->_attachedFactories[$factory->getId()] = $factory;
+ }
+
/**
* Calculate object enumeration shift.
@@ -84,16 +221,46 @@ public function attach(ObjectFactory $factory);
* @param \Zend\Pdf\ObjectFactory $factory
* @return integer
*/
- public function calculateShift(ObjectFactory $factory);
+ public function calculateShift(ObjectFactory $factory)
+ {
+ if ($factory === $this) {
+ return 0;
+ }
+
+ if (isset($this->_shiftCalculationCache[$factory->_factoryId])) {
+ return $this->_shiftCalculationCache[$factory->_factoryId];
+ }
+
+ $shift = $this->_objectCount - 1;
+
+ foreach ($this->_attachedFactories as $subFactory) {
+ $subFactoryShift = $subFactory->calculateShift($factory);
+
+ if ($subFactoryShift != -1) {
+ // context found
+ $this->_shiftCalculationCache[$factory->_factoryId] = $shift + $subFactoryShift;
+ return $shift + $subFactoryShift;
+ } else {
+ $shift += $subFactory->getObjectCount()-1;
+ }
+ }
+
+ $this->_shiftCalculationCache[$factory->_factoryId] = -1;
+ return -1;
+ }
/**
* Clean enumeration shift cache.
* Has to be used after PDF render operation to let followed updates be correct.
- *
- * @param \Zend\Pdf\ObjectFactory $factory
- * @return integer
*/
- public function cleanEnumerationShiftCache();
+ public function cleanEnumerationShiftCache()
+ {
+ $this->_shiftCalculationCache = array();
+
+ foreach ($this->_attachedFactories as $attached) {
+ $attached->cleanEnumerationShiftCache();
+ }
+ }
/**
* Retrive object enumeration shift.
@@ -102,7 +269,14 @@ public function cleanEnumerationShiftCache();
* @return integer
* @throws \Zend\Pdf\Exception
*/
- public function getEnumerationShift(ObjectFactory $factory);
+ public function getEnumerationShift(ObjectFactory $factory)
+ {
+ if (($shift = $this->calculateShift($factory)) == -1) {
+ throw new Pdf\Exception('Wrong object context');
+ }
+
+ return $shift;
+ }
/**
* Mark object as modified in context of current factory.
@@ -110,7 +284,15 @@ public function getEnumerationShift(ObjectFactory $factory);
* @param \Zend\Pdf\InternalType\IndirectObject $obj
* @throws \Zend\Pdf\Exception
*/
- public function markAsModified(InternalType\IndirectObject $obj);
+ public function markAsModified(InternalType\IndirectObject $obj)
+ {
+ if ($obj->getFactory() !== $this) {
+ throw new Pdf\Exception('Object is not generated by this factory');
+ }
+
+ $this->_modifiedObjects[$obj->getObjNum()] = $obj;
+ }
+
/**
* Remove object in context of current factory.
@@ -118,7 +300,16 @@ public function markAsModified(InternalType\IndirectObject $obj);
* @param \Zend\Pdf\InternalType\IndirectObject $obj
* @throws \Zend\Pdf\Exception
*/
- public function remove(InternalType\IndirectObject $obj);
+ public function remove(InternalType\IndirectObject $obj)
+ {
+ if (!$obj->compareFactory($this)) {
+ throw new Pdf\Exception('Object is not generated by this factory');
+ }
+
+ $this->_modifiedObjects[$obj->getObjNum()] = $obj;
+ $this->_removedObjects->attach($obj);
+ }
+
/**
* Generate new \Zend\Pdf\InternalType\IndirectObject
@@ -128,7 +319,12 @@ public function remove(InternalType\IndirectObject $obj);
* @param \Zend\Pdf\InternalType\AbstractTypeObject $objectValue
* @return \Zend\Pdf\InternalType\IndirectObject
*/
- public function newObject(InternalType\AbstractTypeObject $objectValue);
+ public function newObject(InternalType\AbstractTypeObject $objectValue)
+ {
+ $obj = new InternalType\IndirectObject($objectValue, $this->_objectCount++, 0, $this);
+ $this->_modifiedObjects[$obj->getObjNum()] = $obj;
+ return $obj;
+ }
/**
* Generate new \Zend\Pdf\InternalType\StreamObject
@@ -138,21 +334,99 @@ public function newObject(InternalType\AbstractTypeObject $objectValue);
* @param mixed $objectValue
* @return \Zend\Pdf\InternalType\StreamObject
*/
- public function newStreamObject($streamValue);
+ public function newStreamObject($streamValue)
+ {
+ $obj = new InternalType\StreamObject($streamValue, $this->_objectCount++, 0, $this);
+ $this->_modifiedObjects[$obj->getObjNum()] = $obj;
+ return $obj;
+ }
+
/**
* Enumerate modified objects.
- * Returns array of Zend_PDF_UpdateInfoContainer
+ * Returns array of \Zend\PDF\ObjectFactory\UpdateInfoContainer
*
* @param \Zend\Pdf\ObjectFactory $rootFactory
* @return array
*/
- public function listModifiedObjects($rootFactory = null);
+ public function listModifiedObjects($rootFactory = null)
+ {
+ if ($rootFactory == null) {
+ $rootFactory = $this;
+ $shift = 0;
+ } else {
+ $shift = $rootFactory->getEnumerationShift($this);
+ }
+
+ ksort($this->_modifiedObjects);
+
+ $result = array();
+ foreach ($this->_modifiedObjects as $objNum => $obj) {
+ if ($this->_removedObjects->contains($obj)) {
+ $result[$objNum+$shift] = new UpdateInfoContainer($objNum + $shift,
+ $obj->getGenNum()+1,
+ true);
+ } else {
+ $result[$objNum+$shift] = new UpdateInfoContainer($objNum + $shift,
+ $obj->getGenNum(),
+ false,
+ $obj->dump($rootFactory));
+ }
+ }
+
+ foreach ($this->_attachedFactories as $factory) {
+ $result += $factory->listModifiedObjects($rootFactory);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Register object in the factory
+ *
+ * It's used to clear "parent object" referencies when factory is closed and clean up resources
+ *
+ * @param string $refString
+ * @param \Zend\Pdf\InternalType\IndirectObject $obj
+ */
+ public function registerObject(InternalType\IndirectObject $obj, $refString)
+ {
+ $this->_registeredObjects[$refString] = $obj;
+ }
+
+ /**
+ * Fetch object specified by reference
+ *
+ * @param string $refString
+ * @return \Zend\Pdf\InternalType\IndirectObject|null
+ */
+ public function fetchObject($refString)
+ {
+ if (!isset($this->_registeredObjects[$refString])) {
+ return null;
+ }
+ return $this->_registeredObjects[$refString];
+ }
+
/**
* Check if PDF file was modified
*
* @return boolean
*/
- public function isModified();
+ public function isModified()
+ {
+ if (count($this->_modifiedObjects) != 0) {
+ return true;
+ }
+
+ foreach ($this->_attachedFactories as $subFactory) {
+ if ($subFactory->isModified()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
+
View
443 library/Zend/Pdf/ObjectFactory/ElementFactory.php
@@ -1,443 +0,0 @@
-<?php
-/**
- * Zend Framework
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category Zend
- * @package Zend_PDF
- * @package Zend_PDF_Internal
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id$
- */
-
-/**
- * @namespace
- */
-namespace Zend\Pdf\ObjectFactory;
-
-use Zend\Pdf\ObjectFactory,
- Zend\Pdf,
- Zend\Pdf\InternalType;
-
-/**
- * PDF element factory.
- * Responsibility is to log PDF changes
- *
- * @uses SplObjectStorage
- * @uses \Zend\Pdf\ObjectFactory
- * @uses \Zend\Pdf\ObjectFactory\Proxy
- * @uses \Zend\Pdf\ObjectFactory\UpdateInfoContainer
- * @uses \Zend\Pdf\InternalType\IndirectObject
- * @uses \Zend\Pdf\InternalType\StreamObject
- * @uses \Zend\Pdf\Exception
- * @package Zend_PDF
- * @package Zend_PDF_Internal
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
-class ElementFactory implements ObjectFactory
-{
- /**
- * List of the modified objects.
- * Also contains new and removed objects
- *
- * Array: ojbectNumber => \Zend\Pdf\InternalType\IndirectObject
- *
- * @var array
- */
- private $_modifiedObjects = array();
-
- /**
- * List of the removed objects
- *
- * Array: ojbectNumber => \Zend\Pdf\InternalType\IndirectObject
- *
- * @var SplObjectStorage
- */
- private $_removedObjects;
-
- /**
- * List of registered objects.
- * Used for resources clean up when factory is destroyed.
- *
- * Array of \Zend\Pdf\InternalType\AbstractTypeObject objects
- *
- * @var array
- */
- private $_registeredObjects = array();
-
- /**
- * PDF object counter.
- * Actually it's an object number for new PDF object
- *
- * @var integer
- */
- private $_objectCount;
-
-
- /**
- * List of the attached object factories.
- * Array of \Zend\Pdf\ObjectFactory objects
- *
- * @var array
- */
- private $_attachedFactories = array();
-
-
- /**
- * Factory internal id
- *
- * @var integer
- */
- private $_factoryId;
-
- /**
- * Identity, used for factory id generation
- *
- * @var integer
- */
- private static $_identity = 0;
-
-
- /**
- * Internal cache to save calculated shifts
- *
- * @var array
- */
- private $_shiftCalculationCache = array();
-
-
- /**
- * Object constructor
- *
- * @param integer $objCount
- */
- public function __construct($objCount)
- {
- $this->_objectCount = (int)$objCount;
- $this->_factoryId = self::$_identity++;
- $this->_removedObjects = new \SplObjectStorage();
- }
-
-
- /**
- * Factory generator
- *
- * @param integer $objCount
- * @return \Zend\Pdf\ObjectFactory
- */
- static public function createFactory($objCount)
- {
- return new Proxy(new self($objCount));
- }
-
- /**
- * Close factory and clean-up resources
- *
- * @internal
- */
- public function close()
- {
- $this->_modifiedObjects = null;
- $this->_removedObjects = null;
- $this->_attachedFactories = null;
-
- foreach ($this->_registeredObjects as $obj) {
- $obj->cleanUp();
- }
- $this->_registeredObjects = null;
- }
-
- /**
- * Get source factory object
- *
- * @return \Zend\Pdf\ObjectFactory\ElementFactory
- */
- public function resolve()
- {
- return $this;
- }
-
- /**
- * Get factory ID
- *
- * @return integer
- */
- public function getId()
- {
- return $this->_factoryId;
- }
-
- /**
- * Set object counter
- *
- * @param integer $objCount
- */
- public function setObjectCount($objCount)
- {
- $this->_objectCount = (int)$objCount;
- }
-
- /**
- * Get object counter
- *
- * @return integer
- */
- public function getObjectCount()
- {
- $count = $this->_objectCount;
-
- foreach ($this->_attachedFactories as $attached) {
- $count += $attached->getObjectCount() - 1; // -1 as "0" object is a special case and shared between factories
- }
-
- return $count;
- }
-
-
- /**
- * Attach factory to the current;
- *
- * @param \Zend\Pdf\ObjectFactory $factory
- */
- public function attach(ObjectFactory $factory)
- {
- if ( $factory === $this || isset($this->_attachedFactories[$factory->getId()])) {
- /**
- * Don't attach factory twice.
- * We do not check recusively because of nature of attach operation
- * (Pages are always attached to the Documents, Fonts are always attached
- * to the pages even if pages already use Document level object factory and so on)
- */
- return;
- }
-
- $this->_attachedFactories[$factory->getId()] = $factory;
- }
-
-
- /**
- * Calculate object enumeration shift.
- *
- * @param \Zend\Pdf\ObjectFactory $factory
- * @return integer
- */
- public function calculateShift(ObjectFactory $factory)
- {
- if ($factory === $this) {
- return 0;
- }
-
- if (isset($this->_shiftCalculationCache[$factory->_factoryId])) {
- return $this->_shiftCalculationCache[$factory->_factoryId];
- }
-
- $shift = $this->_objectCount - 1;
-
- foreach ($this->_attachedFactories as $subFactory) {
- $subFactoryShift = $subFactory->calculateShift($factory);
-
- if ($subFactoryShift != -1) {
- // context found
- $this->_shiftCalculationCache[$factory->_factoryId] = $shift + $subFactoryShift;
- return $shift + $subFactoryShift;
- } else {
- $shift += $subFactory->getObjectCount()-1;
- }
- }
-
- $this->_shiftCalculationCache[$factory->_factoryId] = -1;
- return -1;
- }
-
- /**
- * Clean enumeration shift cache.
- * Has to be used after PDF render operation to let followed updates be correct.
- */
- public function cleanEnumerationShiftCache()
- {
- $this->_shiftCalculationCache = array();
-
- foreach ($this->_attachedFactories as $attached) {
- $attached->cleanEnumerationShiftCache();
- }
- }
-
- /**
- * Retrive object enumeration shift.
- *
- * @param \Zend\Pdf\ObjectFactory $factory
- * @return integer
- * @throws \Zend\Pdf\Exception
- */
- public function getEnumerationShift(ObjectFactory $factory)
- {
- if (($shift = $this->calculateShift($factory)) == -1) {
- throw new Pdf\Exception('Wrong object context');
- }
-
- return $shift;
- }
-
- /**
- * Mark object as modified in context of current factory.
- *
- * @param \Zend\Pdf\InternalType\IndirectObject $obj
- * @throws \Zend\Pdf\Exception
- */
- public function markAsModified(InternalType\IndirectObject $obj)
- {
- if ($obj->getFactory() !== $this) {
- throw new Pdf\Exception('Object is not generated by this factory');
- }
-
- $this->_modifiedObjects[$obj->getObjNum()] = $obj;
- }
-
-
- /**
- * Remove object in context of current factory.
- *
- * @param \Zend\Pdf\InternalType\IndirectObject $obj
- * @throws \Zend\Pdf\Exception
- */
- public function remove(InternalType\IndirectObject $obj)
- {
- if (!$obj->compareFactory($this)) {
- throw new Pdf\Exception('Object is not generated by this factory');
- }
-
- $this->_modifiedObjects[$obj->getObjNum()] = $obj;
- $this->_removedObjects->attach($obj);
- }
-
-
- /**
- * Generate new \Zend\Pdf\InternalType\IndirectObject
- *
- * @todo Reusage of the freed object. It's not a support of new feature, but only improvement.
- *
- * @param \Zend\Pdf\InternalType\AbstractTypeObject $objectValue
- * @return \Zend\Pdf\InternalType\IndirectObject
- */
- public function newObject(InternalType\AbstractTypeObject $objectValue)
- {
- $obj = new InternalType\IndirectObject($objectValue, $this->_objectCount++, 0, $this);
- $this->_modifiedObjects[$obj->getObjNum()] = $obj;
- return $obj;
- }
-
- /**
- * Generate new \Zend\Pdf\InternalType\StreamObject
- *
- * @todo Reusage of the freed object. It's not a support of new feature, but only improvement.
- *
- * @param mixed $objectValue
- * @return \Zend\Pdf\InternalType\StreamObject
- */
- public function newStreamObject($streamValue)
- {
- $obj = new InternalType\StreamObject($streamValue, $this->_objectCount++, 0, $this);
- $this->_modifiedObjects[$obj->getObjNum()] = $obj;
- return $obj;
- }
-
-
- /**
- * Enumerate modified objects.
- * Returns array of Zend_PDF_UpdateInfoContainer
- *
- * @param \Zend\Pdf\ObjectFactory $rootFactory
- * @return array
- */
- public function listModifiedObjects($rootFactory = null)
- {
- if ($rootFactory == null) {
- $rootFactory = $this;
- $shift = 0;
- } else {
- $shift = $rootFactory->getEnumerationShift($this);
- }
-
- ksort($this->_modifiedObjects);
-
- $result = array();
- foreach ($this->_modifiedObjects as $objNum => $obj) {
- if ($this->_removedObjects->contains($obj)) {
- $result[$objNum+$shift] = new UpdateInfoContainer($objNum + $shift,
- $obj->getGenNum()+1,
- true);
- } else {
- $result[$objNum+$shift] = new UpdateInfoContainer($objNum + $shift,
- $obj->getGenNum(),
- false,
- $obj->dump($rootFactory));
- }
- }
-
- foreach ($this->_attachedFactories as $factory) {
- $result += $factory->listModifiedObjects($rootFactory);
- }
-
- return $result;
- }
-
- /**
- * Register object in the factory
- *
- * It's used to clear "parent object" referencies when factory is closed and clean up resources
- *
- * @param string $refString
- * @param \Zend\Pdf\InternalType\IndirectObject $obj
- */
- public function registerObject(InternalType\IndirectObject $obj, $refString)
- {
- $this->_registeredObjects[$refString] = $obj;
- }
-
- /**
- * Fetch object specified by reference
- *
- * @param string $refString
- * @return \Zend\Pdf\InternalType\IndirectObject|null
- */
- public function fetchObject($refString)
- {
- if (!isset($this->_registeredObjects[$refString])) {
- return null;
- }
- return $this->_registeredObjects[$refString];
- }
-
-
- /**
- * Check if PDF file was modified
- *
- * @return boolean
- */
- public function isModified()
- {
- if (count($this->_modifiedObjects) != 0) {
- return true;
- }
-
- foreach ($this->_attachedFactories as $subFactory) {
- if ($subFactory->isModified()) {
- return true;
- }
- }
-
- return false;
- }
-}
-
View
233 library/Zend/Pdf/ObjectFactory/Proxy.php
@@ -1,233 +0,0 @@
-<?php
-/**
- * Zend Framework
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category Zend
- * @package Zend_PDF
- * @package Zend_PDF_Internal
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id$
- */
-
-/**
- * @namespace
- */
-namespace Zend\Pdf\ObjectFactory;
-
-use Zend\Pdf\ObjectFactory,
- Zend\Pdf\InternalType;
-
-/**
- * PDF element factory interface.
- * Responsibility is to log PDF changes
- *
- * @uses \Zend\Pdf\ObjectFactory
- * @uses \Zend\Pdf\InternalType
- * @package Zend_PDF
- * @package Zend_PDF_Internal
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
-class Proxy implements ObjectFactory
-{
- /**
- * Factory object
- *
- * @var \Zend\Pdf\ObjectFactory
- */
- private $_factory;
-
-
- /**
- * Object constructor
- *
- * @param \Zend\Pdf\ObjectFactory $factory
- */
- public function __construct(ObjectFactory $factory)
- {
- $this->_factory = $factory;
- }
-
- public function __destruct()
- {
- $this->_factory->close();
- $this->_factory = null;
- }
-
- /**
- * Close factory and clean-up resources
- *
- * @internal
- */
- public function close()
- {
- // Do nothing
- }
-
- /**
- * Get source factory object
- *
- * @return \Zend\Pdf\ObjectFactory
- */
- public function resolve()
- {
- return $this->_factory->resolve();
- }
-
- /**
- * Get factory ID
- *
- * @return integer
- */
- public function getId()
- {
- return $this->_factory->getId();
- }
-
- /**
- * Set object counter
- *
- * @param integer $objCount
- */
- public function setObjectCount($objCount)
- {
- $this->_factory->setObjectCount($objCount);
- }
-
- /**
- * Get object counter
- *
- * @return integer
- */
- public function getObjectCount()
- {
- return $this->_factory->getObjectCount();
- }
-
- /**
- * Attach factory to the current;
- *
- * @param \Zend\Pdf\ObjectFactory $factory
- */
- public function attach(ObjectFactory $factory)
- {
- $this->_factory->attach($factory);
- }
-
- /**
- * Calculate object enumeration shift.
- *
- * @internal
- * @param \Zend\Pdf\ObjectFactory $factory
- * @return integer
- */
- public function calculateShift(ObjectFactory $factory)
- {
- return $this->_factory->calculateShift($factory);
- }
-
- /**
- * Clean enumeration shift cache.
- * Has to be used after PDF render operation to let followed updates be correct.
- *
- * @param \Zend\Pdf\ObjectFactory $factory
- * @return integer
- */
- public function cleanEnumerationShiftCache()
- {
- return $this->_factory->cleanEnumerationShiftCache();
- }
-
- /**
- * Retrive object enumeration shift.
- *
- * @param \Zend\Pdf\ObjectFactory $factory
- * @return integer
- * @throws \Zend\Pdf\Exception
- */
- public function getEnumerationShift(ObjectFactory $factory)
- {
- return $this->_factory->getEnumerationShift($factory);
- }
-
- /**
- * Mark object as modified in context of current factory.
- *
- * @param \Zend\Pdf\InternalType\IndirectObject $obj
- * @throws \Zend\Pdf\Exception
- */
- public function markAsModified(InternalType\IndirectObject $obj)
- {
- $this->_factory->markAsModified($obj);
- }
-
- /**
- * Remove object in context of current factory.
- *
- * @param \Zend\Pdf\InternalType\IndirectObject $obj
- * @throws \Zend\Pdf\Exception
- */
- public function remove(InternalType\IndirectObject $obj)
- {
- $this->_factory->remove($obj);
- }
-
- /**
- * Generate new \Zend\Pdf\InternalType\IndirectObject
- *
- * @todo Reusage of the freed object. It's not a support of new feature, but only improvement.
- *
- * @param \Zend\Pdf\InternalType\AbstractTypeObject $objectValue
- * @return \Zend\Pdf\InternalType\IndirectObject
- */
- public function newObject(InternalType\AbstractTypeObject $objectValue)
- {
- return $this->_factory->newObject($objectValue);
- }
-
- /**
- * Generate new \Zend\Pdf\InternalType\StreamObject
- *
- * @todo Reusage of the freed object. It's not a support of new feature, but only improvement.
- *
- * @param mixed $objectValue
- * @return \Zend\Pdf\InternalType\StreamObject
- */
- public function newStreamObject($streamValue)
- {
- return $this->_factory->newStreamObject($streamValue);
- }
-
- /**
- * Enumerate modified objects.
- * Returns array of Zend_PDF_UpdateInfoContainer
- *
- * @param \Zend\Pdf\ObjectFactory $rootFactory
- * @return array
- */
- public function listModifiedObjects($rootFactory = null)
- {
- return $this->_factory->listModifiedObjects($rootFactory);
- }
-
- /**
- * Check if PDF file was modified
- *
- * @return boolean
- */
- public function isModified()
- {
- return $this->_factory->isModified();
- }
-}
View
8 library/Zend/Pdf/Outline/AbstractOutline.php
@@ -288,10 +288,10 @@ public function openOutlinesCount()
* @return \Zend\Pdf\InternalType\AbstractTypeObject
*/
abstract public function dumpOutline(ObjectFactory $factory,
- $updateNavigation,
- InternalType\AbstractTypeObject $parent,
- InternalType\AbstractTypeObject $prev = null,
- \SplObjectStorage $processedOutlines = null);
+ $updateNavigation,
+ InternalType\AbstractTypeObject $parent,
+ InternalType\AbstractTypeObject $prev = null,
+ \SplObjectStorage $processedOutlines = null);
////////////////////////////////////////////////////////////////////////
View
8 library/Zend/Pdf/Outline/Created.php
@@ -249,10 +249,10 @@ public function __construct($options = array())
* @throws \Zend\Pdf\Exception
*/
public function dumpOutline(ObjectFactory $factory,
- $updateNavigation,
- InternalType\AbstractTypeObject $parent,
- InternalType\AbstractTypeObject $prev = null,
- \SplObjectStorage $processedOutlines = null)
+ $updateNavigation,
+ InternalType\AbstractTypeObject $parent,
+ InternalType\AbstractTypeObject $prev = null,
+ \SplObjectStorage $processedOutlines = null)
{
if ($processedOutlines === null) {
$processedOutlines = new \SplObjectStorage();
View
8 library/Zend/Pdf/Outline/Loaded.php
@@ -370,10 +370,10 @@ public function __construct(InternalType\AbstractTypeObject $dictionary, \SplObj
* @throws \Zend\Pdf\Exception
*/
public function dumpOutline(ObjectFactory $factory,
- $updateNavigation,
- InternalType\AbstractTypeObject $parent,
- InternalType\AbstractTypeObject $prev = null,
- \SplObjectStorage $processedOutlines = null)
+ $updateNavigation,
+ InternalType\AbstractTypeObject $parent,
+ InternalType\AbstractTypeObject $prev = null,
+ \SplObjectStorage $processedOutlines = null)
{
if ($processedOutlines === null) {
$processedOutlines = new \SplObjectStorage();
View
112 library/Zend/Pdf/Page.php
@@ -28,7 +28,7 @@
* PDF Page
*
* @uses \Zend\Pdf\PdfDocument
- * @uses \Zend\Pdf\ObjectFactory\ElementFactory
+ * @uses \Zend\Pdf\ObjectFactory
* @uses \Zend\Pdf\InternalType
* @uses \Zend\Pdf\Exception
* @uses \Zend\Pdf\Resource\Font
@@ -36,6 +36,8 @@
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
+use Zend\Pdf\InternalType;
+
class Page
{
/**** Class Constants ****/
@@ -182,10 +184,10 @@ class Page
* Object factory is created by PDF parser.
* ---------------------------------------------------------
* new Zend_PDF_Page(\Zend\Pdf\InternalType\DictionaryObject $pageDict,
- * \Zend\Pdf\InternalType\ObjectFactory $factory);
+ * \Zend\Pdf\ObjectFactory $factory);
* ---------------------------------------------------------
*
- * 2. Clone PDF page.
+ * 2. Make a copy of the PDF page.
* New page is created in the same context as source page. Object factory is shared.
* Thus it will be attached to the document, but need to be placed into Zend_Pdf::$pages array
* to be included into output.
@@ -216,18 +218,33 @@ class Page
*/
public function __construct($param1, $param2 = null, $param3 = null)
{
- if ($param1 instanceof InternalType\IndirectObjectReference &&
+ if (($param1 instanceof InternalType\IndirectObjectReference ||
+ $param1 instanceof InternalType\IndirectObject
+ ) &&
$param1->getType() == InternalType\AbstractTypeObject::TYPE_DICTIONARY &&
$param2 instanceof ObjectFactory &&
$param3 === null
) {
- $this->_pageDictionary = $param1;
- $this->_objFactory = $param2;
- $this->_attached = true;
- $this->_safeGS = false;
+ switch ($param1->getType()) {
+ case InternalType\AbstractTypeObject::TYPE_DICTIONARY:
+ $this->_pageDictionary = $param1;
+ $this->_objFactory = $param2;
+ $this->_attached = true;
+ $this->_safeGS = false;
+ return;
+ break;
- return;
+ case InternalType\AbstractTypeObject::TYPE_NULL:
+ $this->_objFactory = $param2;
+ $pageWidth = $pageHeight = 0;
+ break;
+
+ default:
+ require_once 'Zend/Pdf/Exception.php';
+ throw new Exception('Unrecognized object type.');
+ break;
+ }
} else if ($param1 instanceof Page && $param2 === null && $param3 === null) {
// Clone existing page.
// Let already existing content and resources to be shared between pages
@@ -265,7 +282,7 @@ public function __construct($param1, $param2 = null, $param3 = null)
if ($param2 !== null) {
$this->_objFactory = $param2;
} else {
- $this->_objFactory = ObjectFactory\ElementFactory::createFactory(1);
+ $this->_objFactory = ObjectFactory::createFactory(1);
}
$this->_attached = false;