• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List

E:/E/GEAMP/www/openbiz/openbiz/others/Zend/Pdf.php

00001 <?php
00027 require_once 'Zend/Pdf/Page.php';
00028 
00030 require_once 'Zend/Pdf/Style.php';
00031 
00033 require_once 'Zend/Pdf/Color/GrayScale.php';
00034 
00036 require_once 'Zend/Pdf/Color/Rgb.php';
00037 
00039 require_once 'Zend/Pdf/Color/Cmyk.php';
00040 
00042 require_once 'Zend/Pdf/Color/Html.php';
00043 
00045 require_once 'Zend/Pdf/Image.php';
00046 
00048 require_once 'Zend/Pdf/Font.php';
00049 
00050 
00052 require_once 'Zend/Pdf/Element.php';
00053 require_once 'Zend/Pdf/Element/Array.php';
00054 require_once 'Zend/Pdf/Element/String/Binary.php';
00055 require_once 'Zend/Pdf/Element/Boolean.php';
00056 require_once 'Zend/Pdf/Element/Dictionary.php';
00057 require_once 'Zend/Pdf/Element/Name.php';
00058 require_once 'Zend/Pdf/Element/Null.php';
00059 require_once 'Zend/Pdf/Element/Numeric.php';
00060 require_once 'Zend/Pdf/Element/String.php';
00061 
00062 
00078 class Zend_Pdf
00079 {
00080   /**** Class Constants ****/
00081 
00085     const PDF_VERSION = '1.4';
00086 
00090     const PDF_HEADER  = "%PDF-1.4\n%\xE2\xE3\xCF\xD3\n";
00091 
00092 
00093 
00103     public $pages = array();
00104 
00120     public $properties = array();
00121 
00129     protected $_originalProperties = array();
00130 
00136     protected $_javaScript = null;
00137 
00144     protected $_namedTargets = array();
00145 
00151     public $outlines = array();
00152 
00159     protected $_originalOutlines = array();
00160 
00167     protected $_originalOpenOutlinesCount = 0;
00168 
00174     protected $_trailer = null;
00175 
00181     protected $_objFactory = null;
00182 
00188     protected static $_memoryManager = null;
00189 
00196     protected $_parser;
00197 
00198 
00204     protected static $_inheritableAttributes = array('Resources', 'MediaBox', 'CropBox', 'Rotate');
00205 
00211     static public function getMemoryManager()
00212     {
00213         if (self::$_memoryManager === null) {
00214             require_once 'Zend/Memory.php';
00215             self::$_memoryManager = Zend_Memory::factory('none');
00216         }
00217 
00218         return self::$_memoryManager;
00219     }
00220 
00226     static public function setMemoryManager(Zend_Memory_Manager $memoryManager)
00227     {
00228         self::$_memoryManager = $memoryManager;
00229     }
00230 
00231 
00239     public static function parse(&$source = null, $revision = null)
00240     {
00241         return new Zend_Pdf($source, $revision);
00242     }
00243 
00251     public static function load($source = null, $revision = null)
00252     {
00253         return new Zend_Pdf($source, $revision, true);
00254     }
00255 
00265     public function save($filename, $updateOnly = false)
00266     {
00267         if (($file = @fopen($filename, $updateOnly ? 'ab':'wb')) === false ) {
00268             require_once 'Zend/Pdf/Exception.php';
00269             throw new Zend_Pdf_Exception( "Can not open '$filename' file for writing." );
00270         }
00271 
00272         $this->render($updateOnly, $file);
00273 
00274         fclose($file);
00275     }
00276 
00296     public function __construct($source = null, $revision = null, $load = false)
00297     {
00298         require_once 'Zend/Pdf/ElementFactory.php';
00299         $this->_objFactory = Zend_Pdf_ElementFactory::createFactory(1);
00300 
00301         if ($source !== null) {
00302             require_once 'Zend/Pdf/Parser.php';
00303             $this->_parser           = new Zend_Pdf_Parser($source, $this->_objFactory, $load);
00304             $this->_pdfHeaderVersion = $this->_parser->getPDFVersion();
00305             $this->_trailer          = $this->_parser->getTrailer();
00306             if ($this->_trailer->Encrypt !== null) {
00307                 require_once 'Zend/Pdf/Exception.php';
00308                 throw new Zend_Pdf_Exception('Encrypted document modification is not supported');
00309             }
00310             if ($revision !== null) {
00311                 $this->rollback($revision);
00312             } else {
00313                 $this->_loadPages($this->_trailer->Root->Pages);
00314             }
00315 
00316             $this->_loadNamedDestinations($this->_trailer->Root, $this->_parser->getPDFVersion());
00317             $this->_loadOutlines($this->_trailer->Root);
00318 
00319             if ($this->_trailer->Info !== null) {
00320                 $this->properties = $this->_trailer->Info->toPhp();
00321 
00322                 if (isset($this->properties['Trapped'])) {
00323                     switch ($this->properties['Trapped']) {
00324                         case 'True':
00325                             $this->properties['Trapped'] = true;
00326                             break;
00327 
00328                         case 'False':
00329                             $this->properties['Trapped'] = false;
00330                             break;
00331 
00332                         case 'Unknown':
00333                             $this->properties['Trapped'] = null;
00334                             break;
00335 
00336                         default:
00337                             // Wrong property value
00338                             // Do nothing
00339                             break;
00340                     }
00341                 }
00342 
00343                 $this->_originalProperties = $this->properties;
00344             }
00345         } else {
00346             $this->_pdfHeaderVersion = Zend_Pdf::PDF_VERSION;
00347 
00348             $trailerDictionary = new Zend_Pdf_Element_Dictionary();
00349 
00353             $docId = md5(uniqid(rand(), true));   // 32 byte (128 bit) identifier
00354             $docIdLow  = substr($docId,  0, 16);  // first 16 bytes
00355             $docIdHigh = substr($docId, 16, 16);  // second 16 bytes
00356 
00357             $trailerDictionary->ID = new Zend_Pdf_Element_Array();
00358             $trailerDictionary->ID->items[] = new Zend_Pdf_Element_String_Binary($docIdLow);
00359             $trailerDictionary->ID->items[] = new Zend_Pdf_Element_String_Binary($docIdHigh);
00360 
00361             $trailerDictionary->Size = new Zend_Pdf_Element_Numeric(0);
00362 
00363             require_once 'Zend/Pdf/Trailer/Generator.php';
00364             $this->_trailer = new Zend_Pdf_Trailer_Generator($trailerDictionary);
00365 
00369             $docCatalog = $this->_objFactory->newObject(new Zend_Pdf_Element_Dictionary());
00370             $docCatalog->Type    = new Zend_Pdf_Element_Name('Catalog');
00371             $docCatalog->Version = new Zend_Pdf_Element_Name(Zend_Pdf::PDF_VERSION);
00372             $this->_trailer->Root = $docCatalog;
00373 
00377             $docPages = $this->_objFactory->newObject(new Zend_Pdf_Element_Dictionary());
00378             $docPages->Type  = new Zend_Pdf_Element_Name('Pages');
00379             $docPages->Kids  = new Zend_Pdf_Element_Array();
00380             $docPages->Count = new Zend_Pdf_Element_Numeric(0);
00381             $docCatalog->Pages = $docPages;
00382         }
00383     }
00384 
00390     public function revisions()
00391     {
00392         $revisions = 1;
00393         $currentTrailer = $this->_trailer;
00394 
00395         while ($currentTrailer->getPrev() !== null && $currentTrailer->getPrev()->Root !== null ) {
00396             $revisions++;
00397             $currentTrailer = $currentTrailer->getPrev();
00398         }
00399 
00400         return $revisions++;
00401     }
00402 
00410     public function rollback($steps)
00411     {
00412         for ($count = 0; $count < $steps; $count++) {
00413             if ($this->_trailer->getPrev() !== null && $this->_trailer->getPrev()->Root !== null) {
00414                 $this->_trailer = $this->_trailer->getPrev();
00415             } else {
00416                 break;
00417             }
00418         }
00419         $this->_objFactory->setObjectCount($this->_trailer->Size->value);
00420 
00421         // Mark content as modified to force new trailer generation at render time
00422         $this->_trailer->Root->touch();
00423 
00424         $this->pages = array();
00425         $this->_loadPages($this->_trailer->Root->Pages);
00426     }
00427 
00428 
00435     protected function _loadPages(Zend_Pdf_Element_Reference $pages, $attributes = array())
00436     {
00437         if ($pages->getType() != Zend_Pdf_Element::TYPE_DICTIONARY) {
00438             require_once 'Zend/Pdf/Exception.php';
00439             throw new Zend_Pdf_Exception('Wrong argument');
00440         }
00441 
00442         foreach ($pages->getKeys() as $property) {
00443             if (in_array($property, self::$_inheritableAttributes)) {
00444                 $attributes[$property] = $pages->$property;
00445                 $pages->$property = null;
00446             }
00447         }
00448 
00449 
00450         foreach ($pages->Kids->items as $child) {
00451             if ($child->Type->value == 'Pages') {
00452                 $this->_loadPages($child, $attributes);
00453             } else if ($child->Type->value == 'Page') {
00454                 foreach (self::$_inheritableAttributes as $property) {
00455                     if ($child->$property === null && array_key_exists($property, $attributes)) {
00461                         if ($attributes[$property] instanceof Zend_Pdf_Element_Object  ||
00462                             $attributes[$property] instanceof Zend_Pdf_Element_Reference) {
00463                             $child->$property = $attributes[$property];
00464                         } else {
00465                             $child->$property = $this->_objFactory->newObject($attributes[$property]);
00466                         }
00467                     }
00468                 }
00469 
00470                 require_once 'Zend/Pdf/Page.php';
00471                 $this->pages[] = new Zend_Pdf_Page($child, $this->_objFactory);
00472             }
00473         }
00474     }
00475 
00483     protected function _loadNamedDestinations(Zend_Pdf_Element_Reference $root, $pdfHeaderVersion)
00484     {
00485         if ($root->Version !== null  &&  version_compare($root->Version->value, $pdfHeaderVersion, '>')) {
00486             $versionIs_1_2_plus = version_compare($root->Version->value,    '1.1', '>');
00487         } else {
00488             $versionIs_1_2_plus = version_compare($pdfHeaderVersion, '1.1', '>');
00489         }
00490 
00491         if ($versionIs_1_2_plus) {
00492             // PDF version is 1.2+
00493             // Look for Destinations structure at Name dictionary
00494             if ($root->Names !== null  &&  $root->Names->Dests !== null) {
00495                 require_once 'Zend/Pdf/NameTree.php';
00496                 require_once 'Zend/Pdf/Target.php';
00497                 foreach (new Zend_Pdf_NameTree($root->Names->Dests) as $name => $destination) {
00498                     $this->_namedTargets[$name] = Zend_Pdf_Target::load($destination);
00499                 }
00500             }
00501         } else {
00502             // PDF version is 1.1 (or earlier)
00503             // Look for Destinations sructure at Dest entry of document catalog
00504             if ($root->Dests !== null) {
00505                 if ($root->Dests->getType() != Zend_Pdf_Element::TYPE_DICTIONARY) {
00506                     require_once 'Zend/Pdf/Exception.php';
00507                     throw new Zend_Pdf_Exception('Document catalog Dests entry must be a dictionary.');
00508                 }
00509 
00510                 require_once 'Zend/Pdf/Target.php';
00511                 foreach ($root->Dests->getKeys() as $destKey) {
00512                     $this->_namedTargets[$destKey] = Zend_Pdf_Target::load($root->Dests->$destKey);
00513                 }
00514             }
00515         }
00516     }
00517 
00523     protected function _loadOutlines(Zend_Pdf_Element_Reference $root)
00524     {
00525         if ($root->Outlines === null) {
00526             return;
00527         }
00528 
00529         if ($root->Outlines->getType() != Zend_Pdf_Element::TYPE_DICTIONARY) {
00530             require_once 'Zend/Pdf/Exception.php';
00531             throw new Zend_Pdf_Exception('Document catalog Outlines entry must be a dictionary.');
00532         }
00533 
00534         if ($root->Outlines->Type !== null  &&  $root->Outlines->Type->value != 'Outlines') {
00535             require_once 'Zend/Pdf/Exception.php';
00536             throw new Zend_Pdf_Exception('Outlines Type entry must be an \'Outlines\' string.');
00537         }
00538 
00539         if ($root->Outlines->First === null) {
00540             return;
00541         }
00542 
00543         $outlineDictionary = $root->Outlines->First;
00544         $processedDictionaries = new SplObjectStorage();
00545         while ($outlineDictionary !== null  &&  !$processedDictionaries->contains($outlineDictionary)) {
00546             $processedDictionaries->attach($outlineDictionary);
00547 
00548             require_once 'Zend/Pdf/Outline/Loaded.php';
00549             $this->outlines[] = new Zend_Pdf_Outline_Loaded($outlineDictionary);
00550 
00551             $outlineDictionary = $outlineDictionary->Next;
00552         }
00553 
00554         $this->_originalOutlines = $this->outlines;
00555 
00556         if ($root->Outlines->Count !== null) {
00557             $this->_originalOpenOutlinesCount = $root->Outlines->Count->value;
00558         }
00559     }
00560 
00569     protected function _dumpPages()
00570     {
00571         $root = $this->_trailer->Root;
00572         $pagesContainer = $root->Pages;
00573 
00574         $pagesContainer->touch();
00575         $pagesContainer->Kids->items = array();
00576 
00577         foreach ($this->pages as $page ) {
00578             $page->render($this->_objFactory);
00579 
00580             $pageDictionary = $page->getPageDictionary();
00581             $pageDictionary->touch();
00582             $pageDictionary->Parent = $pagesContainer;
00583 
00584             $pagesContainer->Kids->items[] = $pageDictionary;
00585         }
00586 
00587         $this->_refreshPagesHash();
00588 
00589         $pagesContainer->Count->touch();
00590         $pagesContainer->Count->value = count($this->pages);
00591 
00592 
00593         // Refresh named destinations list
00594         foreach ($this->_namedTargets as $name => $namedTarget) {
00595             if ($namedTarget instanceof Zend_Pdf_Destination_Explicit) {
00596                 // Named target is an explicit destination
00597                 if ($this->resolveDestination($namedTarget, false) === null) {
00598                     unset($this->_namedTargets[$name]);
00599                 }
00600             } else if ($namedTarget instanceof Zend_Pdf_Action) {
00601                 // Named target is an action
00602                 if ($this->_cleanUpAction($namedTarget, false) === null) {
00603                     // Action is a GoTo action with an unresolved destination
00604                     unset($this->_namedTargets[$name]);
00605                 }
00606             } else {
00607                 require_once 'Zend/Pdf/Exception.php';
00608                 throw new Zend_Pdf_Exception('Wrong type of named targed (\'' . get_class($namedTarget) . '\').');
00609             }
00610         }
00611 
00612         // Refresh outlines
00613         require_once 'Zend/Pdf/RecursivelyIteratableObjectsContainer.php';
00614         $iterator = new RecursiveIteratorIterator(new Zend_Pdf_RecursivelyIteratableObjectsContainer($this->outlines), RecursiveIteratorIterator::SELF_FIRST);
00615         foreach ($iterator as $outline) {
00616             $target = $outline->getTarget();
00617 
00618             if ($target !== null) {
00619                 if ($target instanceof Zend_Pdf_Destination) {
00620                     // Outline target is a destination
00621                     if ($this->resolveDestination($target, false) === null) {
00622                         $outline->setTarget(null);
00623                     }
00624                 } else if ($target instanceof Zend_Pdf_Action) {
00625                     // Outline target is an action
00626                     if ($this->_cleanUpAction($target, false) === null) {
00627                         // Action is a GoTo action with an unresolved destination
00628                         $outline->setTarget(null);
00629                     }
00630                 } else {
00631                     require_once 'Zend/Pdf/Exception.php';
00632                     throw new Zend_Pdf_Exception('Wrong outline target.');
00633                 }
00634             }
00635         }
00636 
00637         $openAction = $this->getOpenAction();
00638         if ($openAction !== null) {
00639             if ($openAction instanceof Zend_Pdf_Action) {
00640                 // OpenAction is an action
00641                 if ($this->_cleanUpAction($openAction, false) === null) {
00642                     // Action is a GoTo action with an unresolved destination
00643                     $this->setOpenAction(null);
00644                 }
00645             } else if ($openAction instanceof Zend_Pdf_Destination) {
00646                 // OpenAction target is a destination
00647                 if ($this->resolveDestination($openAction, false) === null) {
00648                     $this->setOpenAction(null);
00649                 }
00650             } else {
00651                 require_once 'Zend/Pdf/Exception.php';
00652                 throw new Zend_Pdf_Exception('OpenAction has to be either PDF Action or Destination.');
00653             }
00654         }
00655     }
00656 
00662     protected function _dumpNamedDestinations()
00663     {
00664         ksort($this->_namedTargets, SORT_STRING);
00665 
00666         $destArrayItems = array();
00667         foreach ($this->_namedTargets as $name => $destination) {
00668             $destArrayItems[] = new Zend_Pdf_Element_String($name);
00669 
00670             if ($destination instanceof Zend_Pdf_Target) {
00671                 $destArrayItems[] = $destination->getResource();
00672             } else {
00673                 require_once 'Zend/Pdf/Exception.php';
00674                 throw new Zend_Pdf_Exception('PDF named destinations must be a Zend_Pdf_Target object.');
00675             }
00676         }
00677         $destArray = $this->_objFactory->newObject(new Zend_Pdf_Element_Array($destArrayItems));
00678 
00679         $DestTree = $this->_objFactory->newObject(new Zend_Pdf_Element_Dictionary());
00680         $DestTree->Names = $destArray;
00681 
00682         $root = $this->_trailer->Root;
00683 
00684         if ($root->Names === null) {
00685             $root->touch();
00686             $root->Names = $this->_objFactory->newObject(new Zend_Pdf_Element_Dictionary());
00687         } else {
00688             $root->Names->touch();
00689         }
00690         $root->Names->Dests = $DestTree;
00691     }
00692 
00696     protected function _dumpOutlines()
00697     {
00698         $root = $this->_trailer->Root;
00699 
00700         if ($root->Outlines === null) {
00701             if (count($this->outlines) == 0) {
00702                 return;
00703             } else {
00704                 $root->Outlines = $this->_objFactory->newObject(new Zend_Pdf_Element_Dictionary());
00705                 $root->Outlines->Type = new Zend_Pdf_Element_Name('Outlines');
00706                 $updateOutlinesNavigation = true;
00707             }
00708         } else {
00709             $updateOutlinesNavigation = false;
00710             if (count($this->_originalOutlines) != count($this->outlines)) {
00711                 // If original and current outlines arrays have different size then outlines list was updated
00712                 $updateOutlinesNavigation = true;
00713             } else if ( !(array_keys($this->_originalOutlines) === array_keys($this->outlines)) ) {
00714                 // If original and current outlines arrays have different keys (with a glance to an order) then outlines list was updated
00715                 $updateOutlinesNavigation = true;
00716             } else {
00717                 foreach ($this->outlines as $key => $outline) {
00718                     if ($this->_originalOutlines[$key] !== $outline) {
00719                         $updateOutlinesNavigation = true;
00720                     }
00721                 }
00722             }
00723         }
00724 
00725         $lastOutline = null;
00726         $openOutlinesCount = 0;
00727         if ($updateOutlinesNavigation) {
00728             $root->Outlines->touch();
00729             $root->Outlines->First = null;
00730 
00731             foreach ($this->outlines as $outline) {
00732                 if ($lastOutline === null) {
00733                     // First pass. Update Outlines dictionary First entry using corresponding value
00734                     $lastOutline = $outline->dumpOutline($this->_objFactory, $updateOutlinesNavigation, $root->Outlines);
00735                     $root->Outlines->First = $lastOutline;
00736                 } else {
00737                     // Update previous outline dictionary Next entry (Prev is updated within dumpOutline() method)
00738                     $currentOutlineDictionary = $outline->dumpOutline($this->_objFactory, $updateOutlinesNavigation, $root->Outlines, $lastOutline);
00739                     $lastOutline->Next = $currentOutlineDictionary;
00740                     $lastOutline       = $currentOutlineDictionary;
00741                 }
00742                 $openOutlinesCount += $outline->openOutlinesCount();
00743             }
00744 
00745             $root->Outlines->Last  = $lastOutline;
00746         } else {
00747             foreach ($this->outlines as $outline) {
00748                 $lastOutline = $outline->dumpOutline($this->_objFactory, $updateOutlinesNavigation, $root->Outlines, $lastOutline);
00749                 $openOutlinesCount += $outline->openOutlinesCount();
00750             }
00751         }
00752 
00753         if ($openOutlinesCount != $this->_originalOpenOutlinesCount) {
00754             $root->Outlines->touch;
00755             $root->Outlines->Count = new Zend_Pdf_Element_Numeric($openOutlinesCount);
00756         }
00757     }
00758 
00781     public function newPage($param1, $param2 = null)
00782     {
00783         require_once 'Zend/Pdf/Page.php';
00784         if ($param2 === null) {
00785             return new Zend_Pdf_Page($param1, $this->_objFactory);
00786         } else {
00787             return new Zend_Pdf_Page($param1, $param2, $this->_objFactory);
00788         }
00789     }
00790 
00797     public function getMetadata()
00798     {
00799         if ($this->_trailer->Root->Metadata !== null) {
00800             return $this->_trailer->Root->Metadata->value;
00801         } else {
00802             return null;
00803         }
00804     }
00805 
00811     public function setMetadata($metadata)
00812     {
00813         $metadataObject = $this->_objFactory->newStreamObject($metadata);
00814         $metadataObject->dictionary->Type    = new Zend_Pdf_Element_Name('Metadata');
00815         $metadataObject->dictionary->Subtype = new Zend_Pdf_Element_Name('XML');
00816 
00817         $this->_trailer->Root->Metadata = $metadataObject;
00818         $this->_trailer->Root->touch();
00819     }
00820 
00827     public function getJavaScript()
00828     {
00829         return $this->_javaScript;
00830     }
00831 
00838     public function getOpenAction()
00839     {
00840         if ($this->_trailer->Root->OpenAction !== null) {
00841             require_once 'Zend/Pdf/Target.php';
00842             return Zend_Pdf_Target::load($this->_trailer->Root->OpenAction);
00843         } else {
00844             return null;
00845         }
00846     }
00847 
00854     public function setOpenAction(Zend_Pdf_Target $openAction = null)
00855     {
00856         $root = $this->_trailer->Root;
00857         $root->touch();
00858 
00859         if ($openAction === null) {
00860             $root->OpenAction = null;
00861         } else {
00862             $root->OpenAction = $openAction->getResource();
00863 
00864             if ($openAction instanceof Zend_Pdf_Action)  {
00865                 $openAction->dumpAction($this->_objFactory);
00866             }
00867         }
00868 
00869         return $this;
00870     }
00871 
00879     public function getNamedDestinations()
00880     {
00881         return $this->_namedTargets;
00882     }
00883 
00890     public function getNamedDestination($name)
00891     {
00892         if (isset($this->_namedTargets[$name])) {
00893             return $this->_namedTargets[$name];
00894         } else {
00895             return null;
00896         }
00897     }
00898 
00905     public function setNamedDestination($name, $destination = null)
00906     {
00907         if ($destination !== null  &&
00908             !$destination instanceof Zend_Pdf_Action_GoTo  &&
00909             !$destination instanceof Zend_Pdf_Destination_Explicit) {
00910             require_once 'Zend/Pdf/Exception.php';
00911             throw new Zend_Pdf_Exception('PDF named destination must refer an explicit destination or a GoTo PDF action.');
00912         }
00913 
00914         if ($destination !== null) {
00915            $this->_namedTargets[$name] = $destination;
00916         } else {
00917             unset($this->_namedTargets[$name]);
00918         }
00919     }
00920 
00927     protected $_pageReferences = null;
00928 
00935     protected $_pageNumbers = null;
00936 
00942     protected function _refreshPagesHash()
00943     {
00944         $this->_pageReferences = array();
00945         $this->_pageNumbers    = array();
00946         $count = 1;
00947         foreach ($this->pages as $page) {
00948             $pageDictionaryHashId = spl_object_hash($page->getPageDictionary()->getObject());
00949             $this->_pageReferences[$pageDictionaryHashId] = $page;
00950             $this->_pageNumbers[$count++]                 = $page;
00951         }
00952 
00953         return $this;
00954     }
00955 
00966     public function resolveDestination(Zend_Pdf_Destination $destination, $refreshPageCollectionHashes = true)
00967     {
00968         if ($this->_pageReferences === null  ||  $refreshPageCollectionHashes) {
00969             $this->_refreshPagesHash();
00970         }
00971 
00972         if ($destination instanceof Zend_Pdf_Destination_Named) {
00973             if (!isset($this->_namedTargets[$destination->getName()])) {
00974                 return null;
00975             }
00976             $destination = $this->getNamedDestination($destination->getName());
00977 
00978             if ($destination instanceof Zend_Pdf_Action) {
00979                 if (!$destination instanceof Zend_Pdf_Action_GoTo) {
00980                     return null;
00981                 }
00982                 $destination = $destination->getDestination();
00983             }
00984 
00985             if (!$destination instanceof Zend_Pdf_Destination_Explicit) {
00986                 require_once 'Zend/Pdf/Exception.php';
00987                 throw new Zend_Pdf_Exception('Named destination target has to be an explicit destination.');
00988             }
00989         }
00990 
00991         // Named target is an explicit destination
00992         $pageElement = $destination->getResource()->items[0];
00993 
00994         if ($pageElement->getType() == Zend_Pdf_Element::TYPE_NUMERIC) {
00995             // Page reference is a PDF number
00996             if (!isset($this->_pageNumbers[$pageElement->value])) {
00997                 return null;
00998             }
00999 
01000             return $this->_pageNumbers[$pageElement->value];
01001         }
01002 
01003         // Page reference is a PDF page dictionary reference
01004         $pageDictionaryHashId = spl_object_hash($pageElement->getObject());
01005         if (!isset($this->_pageReferences[$pageDictionaryHashId])) {
01006             return null;
01007         }
01008         return $this->_pageReferences[$pageDictionaryHashId];
01009     }
01010 
01023     protected function _cleanUpAction(Zend_Pdf_Action $action, $refreshPageCollectionHashes = true)
01024     {
01025         if ($this->_pageReferences === null  ||  $refreshPageCollectionHashes) {
01026             $this->_refreshPagesHash();
01027         }
01028 
01029         // Named target is an action
01030         if ($action instanceof Zend_Pdf_Action_GoTo  &&
01031             $this->resolveDestination($action->getDestination(), false) === null) {
01032             // Action itself is a GoTo action with an unresolved destination
01033             return null;
01034         }
01035 
01036         // Walk through child actions
01037         $iterator = new RecursiveIteratorIterator($action, RecursiveIteratorIterator::SELF_FIRST);
01038 
01039         $actionsToClean        = array();
01040         $deletionCandidateKeys = array();
01041         foreach ($iterator as $chainedAction) {
01042             if ($chainedAction instanceof Zend_Pdf_Action_GoTo  &&
01043                 $this->resolveDestination($chainedAction->getDestination(), false) === null) {
01044                 // Some child action is a GoTo action with an unresolved destination
01045                 // Mark it as a candidate for deletion
01046                 $actionsToClean[]        = $iterator->getSubIterator();
01047                 $deletionCandidateKeys[] = $iterator->getSubIterator()->key();
01048             }
01049         }
01050         foreach ($actionsToClean as $id => $action) {
01051             unset($action->next[$deletionCandidateKeys[$id]]);
01052         }
01053 
01054         return $action;
01055     }
01056 
01065     public function extractFonts()
01066     {
01067         $fontResourcesUnique = array();
01068         foreach ($this->pages as $page) {
01069             $pageResources = $page->extractResources();
01070 
01071             if ($pageResources->Font === null) {
01072                 // Page doesn't contain have any font reference
01073                 continue;
01074             }
01075 
01076             $fontResources = $pageResources->Font;
01077 
01078             foreach ($fontResources->getKeys() as $fontResourceName) {
01079                 $fontDictionary = $fontResources->$fontResourceName;
01080 
01081                 if (! ($fontDictionary instanceof Zend_Pdf_Element_Reference  ||
01082                        $fontDictionary instanceof Zend_Pdf_Element_Object) ) {
01083                     require_once 'Zend/Pdf/Exception.php';
01084                     throw new Zend_Pdf_Exception('Font dictionary has to be an indirect object or object reference.');
01085                 }
01086 
01087                 $fontResourcesUnique[spl_object_hash($fontDictionary->getObject())] = $fontDictionary;
01088             }
01089         }
01090 
01091         $fonts = array();
01092         require_once 'Zend/Pdf/Exception.php';
01093         foreach ($fontResourcesUnique as $resourceId => $fontDictionary) {
01094             try {
01095                 // Try to extract font
01096                 require_once 'Zend/Pdf/Resource/Font/Extracted.php';
01097                 $extractedFont = new Zend_Pdf_Resource_Font_Extracted($fontDictionary);
01098 
01099                 $fonts[$resourceId] = $extractedFont;
01100             } catch (Zend_Pdf_Exception $e) {
01101                 if ($e->getMessage() != 'Unsupported font type.') {
01102                     throw $e;
01103                 }
01104             }
01105         }
01106 
01107         return $fonts;
01108     }
01109 
01118     public function extractFont($fontName)
01119     {
01120         $fontResourcesUnique = array();
01121         require_once 'Zend/Pdf/Exception.php';
01122         foreach ($this->pages as $page) {
01123             $pageResources = $page->extractResources();
01124 
01125             if ($pageResources->Font === null) {
01126                 // Page doesn't contain have any font reference
01127                 continue;
01128             }
01129 
01130             $fontResources = $pageResources->Font;
01131 
01132             foreach ($fontResources->getKeys() as $fontResourceName) {
01133                 $fontDictionary = $fontResources->$fontResourceName;
01134 
01135                 if (! ($fontDictionary instanceof Zend_Pdf_Element_Reference  ||
01136                        $fontDictionary instanceof Zend_Pdf_Element_Object) ) {
01137                     require_once 'Zend/Pdf/Exception.php';
01138                     throw new Zend_Pdf_Exception('Font dictionary has to be an indirect object or object reference.');
01139                 }
01140 
01141                 $resourceId = spl_object_hash($fontDictionary->getObject());
01142                 if (isset($fontResourcesUnique[$resourceId])) {
01143                     continue;
01144                 } else {
01145                     // Mark resource as processed
01146                     $fontResourcesUnique[$resourceId] = 1;
01147                 }
01148 
01149                 if ($fontDictionary->BaseFont->value != $fontName) {
01150                     continue;
01151                 }
01152 
01153                 try {
01154                     // Try to extract font
01155                     require_once 'Zend/Pdf/Resource/Font/Extracted.php';
01156                     return new Zend_Pdf_Resource_Font_Extracted($fontDictionary);
01157                 } catch (Zend_Pdf_Exception $e) {
01158                     if ($e->getMessage() != 'Unsupported font type.') {
01159                         throw $e;
01160                     }
01161                     // Continue searhing
01162                 }
01163             }
01164         }
01165 
01166         return null;
01167     }
01168 
01178     public function render($newSegmentOnly = false, $outputStream = null)
01179     {
01180         // Save document properties if necessary
01181         if ($this->properties != $this->_originalProperties) {
01182             $docInfo = $this->_objFactory->newObject(new Zend_Pdf_Element_Dictionary());
01183 
01184             foreach ($this->properties as $key => $value) {
01185                 switch ($key) {
01186                     case 'Trapped':
01187                         switch ($value) {
01188                             case true:
01189                                 $docInfo->$key = new Zend_Pdf_Element_Name('True');
01190                                 break;
01191 
01192                             case false:
01193                                 $docInfo->$key = new Zend_Pdf_Element_Name('False');
01194                                 break;
01195 
01196                             case null:
01197                                 $docInfo->$key = new Zend_Pdf_Element_Name('Unknown');
01198                                 break;
01199 
01200                             default:
01201                                 require_once 'Zend/Pdf/Exception.php';
01202                                 throw new Zend_Pdf_Exception('Wrong Trapped document property vale: \'' . $value . '\'. Only true, false and null values are allowed.');
01203                                 break;
01204                         }
01205 
01206                     case 'CreationDate':
01207                         // break intentionally omitted
01208                     case 'ModDate':
01209                         $docInfo->$key = new Zend_Pdf_Element_String((string)$value);
01210                         break;
01211 
01212                     case 'Title':
01213                         // break intentionally omitted
01214                     case 'Author':
01215                         // break intentionally omitted
01216                     case 'Subject':
01217                         // break intentionally omitted
01218                     case 'Keywords':
01219                         // break intentionally omitted
01220                     case 'Creator':
01221                         // break intentionally omitted
01222                     case 'Producer':
01223                         if (extension_loaded('mbstring') === true) {
01224                             $detected = mb_detect_encoding($value);
01225                             if ($detected !== 'ASCII') {
01226                                 $value = chr(254) . chr(255) . mb_convert_encoding($value, 'UTF-16', $detected);
01227                             }
01228                         }
01229                         $docInfo->$key = new Zend_Pdf_Element_String((string)$value);
01230                         break;
01231 
01232                     default:
01233                         // Set property using PDF type based on PHP type
01234                         $docInfo->$key = Zend_Pdf_Element::phpToPdf($value);
01235                         break;
01236                 }
01237             }
01238 
01239             $this->_trailer->Info = $docInfo;
01240         }
01241 
01242         $this->_dumpPages();
01243         $this->_dumpNamedDestinations();
01244         $this->_dumpOutlines();
01245 
01246         // Check, that PDF file was modified
01247         // File is always modified by _dumpPages() now, but future implementations may eliminate this.
01248         if (!$this->_objFactory->isModified()) {
01249             if ($newSegmentOnly) {
01250                 // Do nothing, return
01251                 return '';
01252             }
01253 
01254             if ($outputStream === null) {
01255                 return $this->_trailer->getPDFString();
01256             } else {
01257                 $pdfData = $this->_trailer->getPDFString();
01258                 while ( strlen($pdfData) > 0 && ($byteCount = fwrite($outputStream, $pdfData)) != false ) {
01259                     $pdfData = substr($pdfData, $byteCount);
01260                 }
01261 
01262                 return '';
01263             }
01264         }
01265 
01266         // offset (from a start of PDF file) of new PDF file segment
01267         $offset = $this->_trailer->getPDFLength();
01268         // Last Object number in a list of free objects
01269         $lastFreeObject = $this->_trailer->getLastFreeObject();
01270 
01271         // Array of cross-reference table subsections
01272         $xrefTable = array();
01273         // Object numbers of first objects in each subsection
01274         $xrefSectionStartNums = array();
01275 
01276         // Last cross-reference table subsection
01277         $xrefSection = array();
01278         // Dummy initialization of the first element (specail case - header of linked list of free objects).
01279         $xrefSection[] = 0;
01280         $xrefSectionStartNums[] = 0;
01281         // Object number of last processed PDF object.
01282         // Used to manage cross-reference subsections.
01283         // Initialized by zero (specail case - header of linked list of free objects).
01284         $lastObjNum = 0;
01285 
01286         if ($outputStream !== null) {
01287             if (!$newSegmentOnly) {
01288                 $pdfData = $this->_trailer->getPDFString();
01289                 while ( strlen($pdfData) > 0 && ($byteCount = fwrite($outputStream, $pdfData)) != false ) {
01290                     $pdfData = substr($pdfData, $byteCount);
01291                 }
01292             }
01293         } else {
01294             $pdfSegmentBlocks = ($newSegmentOnly) ? array() : array($this->_trailer->getPDFString());
01295         }
01296 
01297         // Iterate objects to create new reference table
01298         foreach ($this->_objFactory->listModifiedObjects() as $updateInfo) {
01299             $objNum = $updateInfo->getObjNum();
01300 
01301             if ($objNum - $lastObjNum != 1) {
01302                 // Save cross-reference table subsection and start new one
01303                 $xrefTable[] = $xrefSection;
01304                 $xrefSection = array();
01305                 $xrefSectionStartNums[] = $objNum;
01306             }
01307 
01308             if ($updateInfo->isFree()) {
01309                 // Free object cross-reference table entry
01310                 $xrefSection[]  = sprintf("%010d %05d f \n", $lastFreeObject, $updateInfo->getGenNum());
01311                 $lastFreeObject = $objNum;
01312             } else {
01313                 // In-use object cross-reference table entry
01314                 $xrefSection[]  = sprintf("%010d %05d n \n", $offset, $updateInfo->getGenNum());
01315 
01316                 $pdfBlock = $updateInfo->getObjectDump();
01317                 $offset += strlen($pdfBlock);
01318 
01319                 if ($outputStream === null) {
01320                     $pdfSegmentBlocks[] = $pdfBlock;
01321                 } else {
01322                     while ( strlen($pdfBlock) > 0 && ($byteCount = fwrite($outputStream, $pdfBlock)) != false ) {
01323                         $pdfBlock = substr($pdfBlock, $byteCount);
01324                     }
01325                 }
01326             }
01327             $lastObjNum = $objNum;
01328         }
01329         // Save last cross-reference table subsection
01330         $xrefTable[] = $xrefSection;
01331 
01332         // Modify first entry (specail case - header of linked list of free objects).
01333         $xrefTable[0][0] = sprintf("%010d 65535 f \n", $lastFreeObject);
01334 
01335         $xrefTableStr = "xref\n";
01336         foreach ($xrefTable as $sectId => $xrefSection) {
01337             $xrefTableStr .= sprintf("%d %d \n", $xrefSectionStartNums[$sectId], count($xrefSection));
01338             foreach ($xrefSection as $xrefTableEntry) {
01339                 $xrefTableStr .= $xrefTableEntry;
01340             }
01341         }
01342 
01343         $this->_trailer->Size->value = $this->_objFactory->getObjectCount();
01344 
01345         $pdfBlock = $xrefTableStr
01346                  .  $this->_trailer->toString()
01347                  . "startxref\n" . $offset . "\n"
01348                  . "%%EOF\n";
01349 
01350         $this->_objFactory->cleanEnumerationShiftCache();
01351 
01352         if ($outputStream === null) {
01353             $pdfSegmentBlocks[] = $pdfBlock;
01354 
01355             return implode('', $pdfSegmentBlocks);
01356         } else {
01357             while ( strlen($pdfBlock) > 0 && ($byteCount = fwrite($outputStream, $pdfBlock)) != false ) {
01358                 $pdfBlock = substr($pdfBlock, $byteCount);
01359             }
01360 
01361             return '';
01362         }
01363     }
01364 
01365 
01371     public function setJavaScript($javascript)
01372     {
01373         $this->_javaScript = $javascript;
01374     }
01375 
01376 
01394     public static function pdfDate($timestamp = null)
01395     {
01396         if ($timestamp === null) {
01397             $date = date('\D\:YmdHisO');
01398         } else {
01399             $date = date('\D\:YmdHisO', $timestamp);
01400         }
01401         return substr_replace($date, '\'', -2, 0) . '\'';
01402     }
01403 
01404 }

Generated on Thu Apr 19 2012 17:01:18 for openbiz by  doxygen 1.7.2