Exemplo n.º 1
0
 /**
  * Dereference.
  * Take inderect object, take $value member of this object (must be \ZendPdf\InternalType\AbstractTypeObject),
  * take reference to the $value member of this object and assign it to
  * $value member of current PDF Reference object
  * $obj can be null
  *
  * @throws \ZendPdf\Exception\ExceptionInterface
  */
 private function _dereference()
 {
     if (($obj = $this->_factory->fetchObject($this->_objNum . ' ' . $this->_genNum)) === null) {
         $obj = $this->_context->getParser()->getObject($this->_context->getRefTable()->getOffset($this->_objNum . ' ' . $this->_genNum . ' R'), $this->_context);
     }
     if ($obj === null) {
         $this->_ref = new NullObject();
         return;
     }
     if ($obj->toString() != $this->_objNum . ' ' . $this->_genNum . ' R') {
         throw new Exception\RuntimeException('Incorrect reference to the object');
     }
     $this->_ref = $obj;
 }
Exemplo n.º 2
0
 /**
  * Clone page, extract it and dependent objects from the current document,
  * so it can be used within other docs.
  */
 public function __clone()
 {
     $factory = \ZendPdf\ObjectFactory::createFactory(1);
     $processed = array();
     // Clone dictionary object.
     // Do it explicitly to prevent sharing page attributes between different
     // results of clonePage() operation (other resources are still shared)
     $dictionary = new InternalType\DictionaryObject();
     foreach ($this->_pageDictionary->getKeys() as $key) {
         $dictionary->{$key} = $this->_pageDictionary->{$key}->makeClone($factory, $processed, InternalType\AbstractTypeObject::CLONE_MODE_SKIP_PAGES);
     }
     $this->_pageDictionary = $factory->newObject($dictionary);
     $this->_objFactory = $factory;
     $this->_attached = false;
     $this->_style = null;
     $this->_font = null;
 }
Exemplo n.º 3
0
 /**
  *
  * @param \ZendPdf\Annotation\AbstractAnnotation $annotation
  * @return \ZendPdf\Page
  */
 public function attachAnnotation(Annotation\AbstractAnnotation $annotation)
 {
     $annotationDictionary = $annotation->getResource();
     if (!$annotationDictionary instanceof InternalType\IndirectObject && !$annotationDictionary instanceof InternalType\IndirectObjectReference) {
         $annotationDictionary = $this->_objFactory->newObject($annotationDictionary);
     }
     if ($this->_pageDictionary->Annots === null) {
         $this->_pageDictionary->touch();
         $this->_pageDictionary->Annots = new InternalType\ArrayObject();
     } else {
         $this->_pageDictionary->Annots->touch();
     }
     $this->_pageDictionary->Annots->items[] = $annotationDictionary;
     $annotationDictionary->touch();
     $annotationDictionary->P = $this->_pageDictionary;
     return $this;
 }
Exemplo n.º 4
0
 /**
  * Object constructor
  *
  * @param string $imageFileName
  * @throws \ZendPdf\Exception\ExceptionInterface
  * @todo Add compression conversions to support compression strategys other than PNG_COMPRESSION_DEFAULT_STRATEGY.
  * @todo Add pre-compression filtering.
  * @todo Add interlaced image handling.
  * @todo Add support for 16-bit images. Requires PDF version bump to 1.5 at least.
  * @todo Add processing for all PNG chunks defined in the spec. gAMA etc.
  * @todo Fix tRNS chunk support for Indexed Images to a SMask.
  */
 public function __construct($imageFileName)
 {
     if (($imageFile = @fopen($imageFileName, 'rb')) === false) {
         throw new Exception\IOException("Can not open '{$imageFileName}' file for reading.");
     }
     parent::__construct();
     //Check if the file is a PNG
     fseek($imageFile, 1, SEEK_CUR);
     //First signature byte (%)
     if ('PNG' != fread($imageFile, 3)) {
         throw new Exception\DomainException('Image is not a PNG');
     }
     fseek($imageFile, 12, SEEK_CUR);
     //Signature bytes (Includes the IHDR chunk) IHDR processed linerarly because it doesnt contain a variable chunk length
     $wtmp = unpack('Ni', fread($imageFile, 4));
     //Unpack a 4-Byte Long
     $width = $wtmp['i'];
     $htmp = unpack('Ni', fread($imageFile, 4));
     $height = $htmp['i'];
     $bits = ord(fread($imageFile, 1));
     //Higher than 8 bit depths are only supported in later versions of PDF.
     $color = ord(fread($imageFile, 1));
     $compression = ord(fread($imageFile, 1));
     $prefilter = ord(fread($imageFile, 1));
     if (($interlacing = ord(fread($imageFile, 1))) != self::PNG_INTERLACING_DISABLED) {
         throw new Exception\NotImplementedException('Only non-interlaced images are currently supported.');
     }
     $this->_width = $width;
     $this->_height = $height;
     $this->_imageProperties = array();
     $this->_imageProperties['bitDepth'] = $bits;
     $this->_imageProperties['pngColorType'] = $color;
     $this->_imageProperties['pngFilterType'] = $prefilter;
     $this->_imageProperties['pngCompressionType'] = $compression;
     $this->_imageProperties['pngInterlacingType'] = $interlacing;
     fseek($imageFile, 4, SEEK_CUR);
     //4 Byte Ending Sequence
     $imageData = '';
     /*
      * The following loop processes PNG chunks. 4 Byte Longs are packed first give the chunk length
      * followed by the chunk signature, a four byte code. IDAT and IEND are manditory in any PNG.
      */
     while (($chunkLengthBytes = fread($imageFile, 4)) !== false) {
         $chunkLengthtmp = unpack('Ni', $chunkLengthBytes);
         $chunkLength = $chunkLengthtmp['i'];
         $chunkType = fread($imageFile, 4);
         switch ($chunkType) {
             case 'IDAT':
                 //Image Data
                 /*
                  * Reads the actual image data from the PNG file. Since we know at this point that the compression
                  * strategy is the default strategy, we also know that this data is Zip compressed. We will either copy
                  * the data directly to the PDF and provide the correct FlateDecode predictor, or decompress the data
                  * decode the filters and output the data as a raw pixel map.
                  */
                 $imageData .= fread($imageFile, $chunkLength);
                 fseek($imageFile, 4, SEEK_CUR);
                 break;
             case 'PLTE':
                 //Palette
                 $paletteData = fread($imageFile, $chunkLength);
                 fseek($imageFile, 4, SEEK_CUR);
                 break;
             case 'tRNS':
                 //Basic (non-alpha channel) transparency.
                 $trnsData = fread($imageFile, $chunkLength);
                 switch ($color) {
                     case self::PNG_CHANNEL_GRAY:
                         $baseColor = ord(substr($trnsData, 1, 1));
                         $transparencyData = array(new InternalType\NumericObject($baseColor), new InternalType\NumericObject($baseColor));
                         break;
                     case self::PNG_CHANNEL_RGB:
                         $red = ord(substr($trnsData, 1, 1));
                         $green = ord(substr($trnsData, 3, 1));
                         $blue = ord(substr($trnsData, 5, 1));
                         $transparencyData = array(new InternalType\NumericObject($red), new InternalType\NumericObject($red), new InternalType\NumericObject($green), new InternalType\NumericObject($green), new InternalType\NumericObject($blue), new InternalType\NumericObject($blue));
                         break;
                     case self::PNG_CHANNEL_INDEXED:
                         //Find the first transparent color in the index, we will mask that. (This is a bit of a hack. This should be a SMask and mask all entries values).
                         if (($trnsIdx = strpos($trnsData, "")) !== false) {
                             $transparencyData = array(new InternalType\NumericObject($trnsIdx), new InternalType\NumericObject($trnsIdx));
                         }
                         break;
                     case self::PNG_CHANNEL_GRAY_ALPHA:
                         // Fall through to the next case
                     // Fall through to the next case
                     case self::PNG_CHANNEL_RGB_ALPHA:
                         throw new Exception\CorruptedImageException("tRNS chunk illegal for Alpha Channel Images");
                         break;
                 }
                 fseek($imageFile, 4, SEEK_CUR);
                 //4 Byte Ending Sequence
                 break;
             case 'IEND':
                 break 2;
                 //End the loop too
             //End the loop too
             default:
                 fseek($imageFile, $chunkLength + 4, SEEK_CUR);
                 //Skip the section
                 break;
         }
     }
     fclose($imageFile);
     $compressed = true;
     $imageDataTmp = '';
     $smaskData = '';
     switch ($color) {
         case self::PNG_CHANNEL_RGB:
             $colorSpace = new InternalType\NameObject('DeviceRGB');
             break;
         case self::PNG_CHANNEL_GRAY:
             $colorSpace = new InternalType\NameObject('DeviceGray');
             break;
         case self::PNG_CHANNEL_INDEXED:
             if (empty($paletteData)) {
                 throw new Exception\CorruptedImageException("PNG Corruption: No palette data read for indexed type PNG.");
             }
             $colorSpace = new InternalType\ArrayObject();
             $colorSpace->items[] = new InternalType\NameObject('Indexed');
             $colorSpace->items[] = new InternalType\NameObject('DeviceRGB');
             $colorSpace->items[] = new InternalType\NumericObject(strlen($paletteData) / 3 - 1);
             $paletteObject = $this->_objectFactory->newObject(new InternalType\BinaryStringObject($paletteData));
             $colorSpace->items[] = $paletteObject;
             break;
         case self::PNG_CHANNEL_GRAY_ALPHA:
             /*
              * To decode PNG's with alpha data we must create two images from one. One image will contain the Gray data
              * the other will contain the Gray transparency overlay data. The former will become the object data and the latter
              * will become the Shadow Mask (SMask).
              */
             if ($bits > 8) {
                 throw new Exception\NotImplementedException('Alpha PNGs with bit depth > 8 are not yet supported');
             }
             $colorSpace = new InternalType\NameObject('DeviceGray');
             $decodingObjFactory = ObjectFactory::createFactory(1);
             $decodingStream = $decodingObjFactory->newStreamObject($imageData);
             $decodingStream->dictionary->Filter = new InternalType\NameObject('FlateDecode');
             $decodingStream->dictionary->DecodeParms = new InternalType\DictionaryObject();
             $decodingStream->dictionary->DecodeParms->Predictor = new InternalType\NumericObject(15);
             $decodingStream->dictionary->DecodeParms->Columns = new InternalType\NumericObject($width);
             $decodingStream->dictionary->DecodeParms->Colors = new InternalType\NumericObject(2);
             //GreyAlpha
             $decodingStream->dictionary->DecodeParms->BitsPerComponent = new InternalType\NumericObject($bits);
             $decodingStream->skipFilters();
             $pngDataRawDecoded = $decodingStream->value;
             //Iterate every pixel and copy out gray data and alpha channel (this will be slow)
             for ($pixel = 0, $pixelcount = $width * $height; $pixel < $pixelcount; $pixel++) {
                 $imageDataTmp .= $pngDataRawDecoded[$pixel * 2];
                 $smaskData .= $pngDataRawDecoded[$pixel * 2 + 1];
             }
             $compressed = false;
             $imageData = $imageDataTmp;
             //Overwrite image data with the gray channel without alpha
             break;
         case self::PNG_CHANNEL_RGB_ALPHA:
             /*
              * To decode PNG's with alpha data we must create two images from one. One image will contain the RGB data
              * the other will contain the Gray transparency overlay data. The former will become the object data and the latter
              * will become the Shadow Mask (SMask).
              */
             if ($bits > 8) {
                 throw new Exception\NotImplementedException('Alpha PNGs with bit depth > 8 are not yet supported');
             }
             $colorSpace = new InternalType\NameObject('DeviceRGB');
             $decodingObjFactory = ObjectFactory::createFactory(1);
             $decodingStream = $decodingObjFactory->newStreamObject($imageData);
             $decodingStream->dictionary->Filter = new InternalType\NameObject('FlateDecode');
             $decodingStream->dictionary->DecodeParms = new InternalType\DictionaryObject();
             $decodingStream->dictionary->DecodeParms->Predictor = new InternalType\NumericObject(15);
             $decodingStream->dictionary->DecodeParms->Columns = new InternalType\NumericObject($width);
             $decodingStream->dictionary->DecodeParms->Colors = new InternalType\NumericObject(4);
             //RGBA
             $decodingStream->dictionary->DecodeParms->BitsPerComponent = new InternalType\NumericObject($bits);
             $decodingStream->skipFilters();
             $pngDataRawDecoded = $decodingStream->value;
             //Iterate every pixel and copy out rgb data and alpha channel (this will be slow)
             for ($pixel = 0, $pixelcount = $width * $height; $pixel < $pixelcount; $pixel++) {
                 $imageDataTmp .= $pngDataRawDecoded[$pixel * 4 + 0] . $pngDataRawDecoded[$pixel * 4 + 1] . $pngDataRawDecoded[$pixel * 4 + 2];
                 $smaskData .= $pngDataRawDecoded[$pixel * 4 + 3];
             }
             $compressed = false;
             $imageData = $imageDataTmp;
             //Overwrite image data with the RGB channel without alpha
             break;
         default:
             throw new Exception\CorruptedImageException('PNG Corruption: Invalid color space.');
     }
     if (empty($imageData)) {
         throw new Exception\CorruptedImageException('Corrupt PNG Image. Mandatory IDAT chunk not found.');
     }
     $imageDictionary = $this->_resource->dictionary;
     if (!empty($smaskData)) {
         /*
          * Includes the Alpha transparency data as a Gray Image, then assigns the image as the Shadow Mask for the main image data.
          */
         $smaskStream = $this->_objectFactory->newStreamObject($smaskData);
         $smaskStream->dictionary->Type = new InternalType\NameObject('XObject');
         $smaskStream->dictionary->Subtype = new InternalType\NameObject('Image');
         $smaskStream->dictionary->Width = new InternalType\NumericObject($width);
         $smaskStream->dictionary->Height = new InternalType\NumericObject($height);
         $smaskStream->dictionary->ColorSpace = new InternalType\NameObject('DeviceGray');
         $smaskStream->dictionary->BitsPerComponent = new InternalType\NumericObject($bits);
         $imageDictionary->SMask = $smaskStream;
         // Encode stream with FlateDecode filter
         $smaskStreamDecodeParms = array();
         $smaskStreamDecodeParms['Predictor'] = new InternalType\NumericObject(15);
         $smaskStreamDecodeParms['Columns'] = new InternalType\NumericObject($width);
         $smaskStreamDecodeParms['Colors'] = new InternalType\NumericObject(1);
         $smaskStreamDecodeParms['BitsPerComponent'] = new InternalType\NumericObject(8);
         $smaskStream->dictionary->DecodeParms = new InternalType\DictionaryObject($smaskStreamDecodeParms);
         $smaskStream->dictionary->Filter = new InternalType\NameObject('FlateDecode');
     }
     if (!empty($transparencyData)) {
         //This is experimental and not properly tested.
         $imageDictionary->Mask = new InternalType\ArrayObject($transparencyData);
     }
     $imageDictionary->Width = new InternalType\NumericObject($width);
     $imageDictionary->Height = new InternalType\NumericObject($height);
     $imageDictionary->ColorSpace = $colorSpace;
     $imageDictionary->BitsPerComponent = new InternalType\NumericObject($bits);
     $imageDictionary->Filter = new InternalType\NameObject('FlateDecode');
     $decodeParms = array();
     $decodeParms['Predictor'] = new InternalType\NumericObject(15);
     // Optimal prediction
     $decodeParms['Columns'] = new InternalType\NumericObject($width);
     $decodeParms['Colors'] = new InternalType\NumericObject($color == self::PNG_CHANNEL_RGB || $color == self::PNG_CHANNEL_RGB_ALPHA ? 3 : 1);
     $decodeParms['BitsPerComponent'] = new InternalType\NumericObject($bits);
     $imageDictionary->DecodeParms = new InternalType\DictionaryObject($decodeParms);
     //Include only the image IDAT section data.
     $this->_resource->value = $imageData;
     //Skip double compression
     if ($compressed) {
         $this->_resource->skipFilters();
     }
 }
Exemplo n.º 5
0
 /**
  * Dump object to a string to save within PDF file
  *
  * $factory parameter defines operation context.
  *
  * @param \ZendPdf\ObjectFactory $factory
  * @return string
  */
 public function dump(ObjectFactory $factory)
 {
     $shift = $factory->getEnumerationShift($this->_factory);
     if ($this->_streamDecoded) {
         $this->_initialDictionaryData = $this->_extractDictionaryData();
         $this->_encodeStream();
     } elseif ($this->_initialDictionaryData != null) {
         $newDictionary = $this->_extractDictionaryData();
         if ($this->_initialDictionaryData !== $newDictionary) {
             $this->_decodeStream();
             $this->_initialDictionaryData = $newDictionary;
             $this->_encodeStream();
         }
     }
     // Update stream length
     $this->dictionary->Length->value = $this->_value->length();
     return $this->_objNum + $shift . " " . $this->_genNum . " obj \n" . $this->dictionary->toString($factory) . "\n" . $this->_value->toString($factory) . "\n" . "endobj\n";
 }
Exemplo n.º 6
0
 private function decode($imageData, $width, $colors, $bits)
 {
     $decodingObjFactory = ObjectFactory::createFactory(1);
     $decodingStream = $decodingObjFactory->newStreamObject($imageData);
     $decodingStream->dictionary->Filter = new InternalType\NameObject('FlateDecode');
     $decodingStream->dictionary->DecodeParms = new InternalType\DictionaryObject();
     $decodingStream->dictionary->DecodeParms->Predictor = new InternalType\NumericObject(self::PREDICATOR);
     $decodingStream->dictionary->DecodeParms->Columns = new InternalType\NumericObject($width);
     $decodingStream->dictionary->DecodeParms->Colors = new InternalType\NumericObject($colors);
     $decodingStream->dictionary->DecodeParms->BitsPerComponent = new InternalType\NumericObject($bits);
     $decodingStream->skipFilters();
     return $decodingStream->value;
 }
Exemplo n.º 7
0
 /**
  * Object constructor.
  */
 public function __construct()
 {
     $this->_factory = Pdf\ObjectFactory::createFactory(1);
     $this->_processed = array();
 }
Exemplo n.º 8
0
 /**
  * Object constructor
  *
  * Note: PHP duplicates string, which is sent by value, only of it's updated.
  * Thus we don't need to care about overhead
  *
  * @param mixed $source
  * @param \ZendPdf\ObjectFactory $factory
  * @param boolean $load
  * @throws \ZendPdf\Exception\ExceptionInterface
  */
 public function __construct($source, Pdf\ObjectFactory $factory, $load)
 {
     if ($load) {
         if (($pdfFile = @fopen($source, 'rb')) === false) {
             throw new Exception\IOException("Can not open '{$source}' file for reading.");
         }
         $byteCount = filesize($source);
         $data = fread($pdfFile, $byteCount);
         $byteCount -= strlen($data);
         while ($byteCount > 0 && ($nextBlock = fread($pdfFile, $byteCount)) != false) {
             $data .= $nextBlock;
             $byteCount -= strlen($nextBlock);
         }
         fclose($pdfFile);
         $this->_stringParser = new DataParser($data, $factory);
     } else {
         $this->_stringParser = new DataParser($source, $factory);
     }
     $pdfVersionComment = $this->_stringParser->readComment();
     if (substr($pdfVersionComment, 0, 5) != '%PDF-') {
         throw new Exception\CorruptedPdfException('File is not a PDF.');
     }
     $pdfVersion = substr($pdfVersionComment, 5);
     if (version_compare($pdfVersion, '0.9', '<') || version_compare($pdfVersion, '1.61', '>=')) {
         /**
          * @todo
          * To support PDF versions 1.5 (Acrobat 6) and PDF version 1.7 (Acrobat 7)
          * Stream compression filter must be implemented (for compressed object streams).
          * Cross reference streams must be implemented
          */
         throw new Exception\NotImplementedException(sprintf('Unsupported PDF version. Zend_PDF supports PDF 1.0-1.4. Current version - \'%f\'', $pdfVersion));
     }
     $this->_pdfVersion = $pdfVersion;
     $this->_stringParser->offset = strrpos($this->_stringParser->data, '%%EOF');
     if ($this->_stringParser->offset === false || strlen($this->_stringParser->data) - $this->_stringParser->offset > 7) {
         throw new Exception\CorruptedPdfException('PDF file syntax error. End-of-fle marker expected at the end of file.');
     }
     $this->_stringParser->offset--;
     /**
      * Go to end of cross-reference table offset
      */
     while (DataParser::isWhiteSpace(ord($this->_stringParser->data[$this->_stringParser->offset])) && $this->_stringParser->offset > 0) {
         $this->_stringParser->offset--;
     }
     /**
      * Go to the start of cross-reference table offset
      */
     while (!DataParser::isWhiteSpace(ord($this->_stringParser->data[$this->_stringParser->offset])) && $this->_stringParser->offset > 0) {
         $this->_stringParser->offset--;
     }
     /**
      * Go to the end of 'startxref' keyword
      */
     while (DataParser::isWhiteSpace(ord($this->_stringParser->data[$this->_stringParser->offset])) && $this->_stringParser->offset > 0) {
         $this->_stringParser->offset--;
     }
     /**
      * Go to the white space (eol marker) before 'startxref' keyword
      */
     $this->_stringParser->offset -= 9;
     $nextLexeme = $this->_stringParser->readLexeme();
     if ($nextLexeme != 'startxref') {
         throw new Exception\CorruptedPdfException(sprintf('PDF file syntax error. \'startxref\' keyword expected. Offset - 0x%X.', $this->_stringParser->offset - strlen($nextLexeme)));
     }
     $startXref = $this->_stringParser->readLexeme();
     if (!ctype_digit($startXref)) {
         throw new Exception\CorruptedPdfException(sprintf('PDF file syntax error. Cross-reference table offset must contain only digits. Offset - 0x%X.', $this->_stringParser->offset - strlen($nextLexeme)));
     }
     $this->_trailer = $this->_loadXRefTable($startXref);
     $factory->setObjectCount($this->_trailer->Size->value);
 }
Exemplo n.º 9
0
 /**
  * Mark object as modified, to include it into new PDF file segment
  */
 public function touch()
 {
     $this->_factory->markAsModified($this);
 }
Exemplo n.º 10
0
 /**
  * Attach factory to the current;
  *
  * @param \ZendPdf\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;
 }
Exemplo n.º 11
0
 /**
  * Dump Outline and its child outlines into PDF structures
  *
  * Returns dictionary indirect object or reference
  *
  * @internal
  * @param \ZendPdf\ObjectFactory    $factory object factory for newly created indirect objects
  * @param boolean $updateNavigation  Update navigation flag
  * @param \ZendPdf\InternalType\AbstractTypeObject $parent   Parent outline dictionary reference
  * @param \ZendPdf\InternalType\AbstractTypeObject $prev     Previous outline dictionary reference
  * @param SplObjectStorage $processedOutlines  List of already processed outlines
  * @return \ZendPdf\InternalType\AbstractTypeObject
  * @throws \ZendPdf\Exception\ExceptionInterface
  */
 public function dumpOutline(ObjectFactory $factory, $updateNavigation, InternalType\AbstractTypeObject $parent, InternalType\AbstractTypeObject $prev = null, \SplObjectStorage $processedOutlines = null)
 {
     if ($processedOutlines === null) {
         $processedOutlines = new \SplObjectStorage();
     }
     $processedOutlines->attach($this);
     $outlineDictionary = $factory->newObject(new InternalType\DictionaryObject());
     $outlineDictionary->Title = new InternalType\StringObject($this->getTitle());
     $target = $this->getTarget();
     if ($target === null) {
         // Do nothing
     } elseif ($target instanceof Pdf\Destination\AbstractDestination) {
         $outlineDictionary->Dest = $target->getResource();
     } elseif ($target instanceof Action\AbstractAction) {
         $outlineDictionary->A = $target->getResource();
     } else {
         throw new Exception\CorruptedPdfException('Outline target has to be \\ZendPdf\\Destination, \\ZendPdf\\Action object or null');
     }
     $color = $this->getColor();
     if ($color !== null) {
         $components = $color->getComponents();
         $colorComponentElements = array(new InternalType\NumericObject($components[0]), new InternalType\NumericObject($components[1]), new InternalType\NumericObject($components[2]));
         $outlineDictionary->C = new InternalType\ArrayObject($colorComponentElements);
     }
     if ($this->isItalic() || $this->isBold()) {
         $outlineDictionary->F = new InternalType\NumericObject(($this->isItalic() ? 1 : 0) | ($this->isBold() ? 2 : 0));
         // Bit 2 - Bold
     }
     $outlineDictionary->Parent = $parent;
     $outlineDictionary->Prev = $prev;
     $lastChild = null;
     foreach ($this->childOutlines as $childOutline) {
         if ($processedOutlines->contains($childOutline)) {
             throw new Exception\CorruptedPdfException('Outlines cyclyc reference is detected.');
         }
         if ($lastChild === null) {
             $lastChild = $childOutline->dumpOutline($factory, true, $outlineDictionary, null, $processedOutlines);
             $outlineDictionary->First = $lastChild;
         } else {
             $childOutlineDictionary = $childOutline->dumpOutline($factory, true, $outlineDictionary, $lastChild, $processedOutlines);
             $lastChild->Next = $childOutlineDictionary;
             $lastChild = $childOutlineDictionary;
         }
     }
     $outlineDictionary->Last = $lastChild;
     if (count($this->childOutlines) != 0) {
         $outlineDictionary->Count = new InternalType\NumericObject(($this->isOpen() ? 1 : -1) * count($this->childOutlines));
     }
     return $outlineDictionary;
 }
Exemplo n.º 12
0
 /**
  * Prepare page to be rendered into PDF.
  *
  * @todo Don't forget to close all current graphics operations (like path drawing)
  *
  * @param \ZendPdf\ObjectFactory $objFactory
  * @throws \ZendPdf\Exception\ExceptionInterface
  */
 public function render(ObjectFactory $objFactory)
 {
     $this->flush();
     if ($objFactory === $this->_objFactory) {
         // Page is already attached to the document.
         return;
     }
     if ($this->_attached) {
         throw new Exception\LogicException('Page is attached to other document. Use clone $page to get it context free.');
     } else {
         $objFactory->attach($this->_objFactory);
     }
 }