PageRenderTime 29ms CodeModel.GetById 16ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/framework/vendor/zend/Zend/Pdf/Element/Object/Stream.php

http://zoop.googlecode.com/
PHP | 422 lines | 242 code | 56 blank | 124 comment | 42 complexity | e8c099ebc2a49a552c9d5bdd9f6102f5 MD5 | raw file
  1<?php
  2/**
  3 * Zend Framework
  4 *
  5 * LICENSE
  6 *
  7 * This source file is subject to the new BSD license that is bundled
  8 * with this package in the file LICENSE.txt.
  9 * It is also available through the world-wide-web at this URL:
 10 * http://framework.zend.com/license/new-bsd
 11 * If you did not receive a copy of the license and are unable to
 12 * obtain it through the world-wide-web, please send an email
 13 * to license@zend.com so we can send you a copy immediately.
 14 *
 15 * @category   Zend
 16 * @package    Zend_Pdf
 17 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 18 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 19 * @version    $Id: Stream.php 20096 2010-01-06 02:05:09Z bkarwin $
 20 */
 21
 22
 23/** Internally used classes */
 24require_once 'Zend/Pdf/Element/Stream.php';
 25require_once 'Zend/Pdf/Element/Dictionary.php';
 26require_once 'Zend/Pdf/Element/Numeric.php';
 27
 28
 29/** Zend_Pdf_Element_Object */
 30require_once 'Zend/Pdf/Element/Object.php';
 31
 32/**
 33 * PDF file 'stream object' element implementation
 34 *
 35 * @category   Zend
 36 * @package    Zend_Pdf
 37 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 38 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 39 */
 40class Zend_Pdf_Element_Object_Stream extends Zend_Pdf_Element_Object
 41{
 42    /**
 43     * StreamObject dictionary
 44     * Required enries:
 45     * Length
 46     *
 47     * @var Zend_Pdf_Element_Dictionary
 48     */
 49    private $_dictionary;
 50
 51    /**
 52     * Flag which signals, that stream is decoded
 53     *
 54     * @var boolean
 55     */
 56    private $_streamDecoded;
 57
 58    /**
 59     * Stored original stream object dictionary.
 60     * Used to decode stream during an access time.
 61     *
 62     * The only properties, which affect decoding, are sored here.
 63     *
 64     * @var array|null
 65     */
 66    private $_originalDictionary = null;
 67
 68    /**
 69     * Object constructor
 70     *
 71     * @param mixed $val
 72     * @param integer $objNum
 73     * @param integer $genNum
 74     * @param Zend_Pdf_ElementFactory $factory
 75     * @param Zend_Pdf_Element_Dictionary|null $dictionary
 76     * @throws Zend_Pdf_Exception
 77     */
 78    public function __construct($val, $objNum, $genNum, Zend_Pdf_ElementFactory $factory, $dictionary = null)
 79    {
 80        parent::__construct(new Zend_Pdf_Element_Stream($val), $objNum, $genNum, $factory);
 81
 82        if ($dictionary === null) {
 83            $this->_dictionary    = new Zend_Pdf_Element_Dictionary();
 84            $this->_dictionary->Length = new Zend_Pdf_Element_Numeric(strlen( $val ));
 85            $this->_streamDecoded = true;
 86        } else {
 87            $this->_dictionary    = $dictionary;
 88            $this->_streamDecoded = false;
 89        }
 90    }
 91
 92
 93    /**
 94     * Store original dictionary information in $_originalDictionary class member.
 95     * Used to store information and to normalize filters information before defiltering.
 96     *
 97     */
 98    private function _storeOriginalDictionary()
 99    {
100        $this->_originalDictionary = array();
101
102        $this->_originalDictionary['Filter']      = array();
103        $this->_originalDictionary['DecodeParms'] = array();
104        if ($this->_dictionary->Filter === null) {
105            // Do nothing.
106        } else if ($this->_dictionary->Filter->getType() == Zend_Pdf_Element::TYPE_ARRAY) {
107            foreach ($this->_dictionary->Filter->items as $id => $filter) {
108                $this->_originalDictionary['Filter'][$id]      = $filter->value;
109                $this->_originalDictionary['DecodeParms'][$id] = array();
110
111                if ($this->_dictionary->DecodeParms !== null ) {
112                    if ($this->_dictionary->DecodeParms->items[$id] !== null &&
113                        $this->_dictionary->DecodeParms->items[$id]->value !== null ) {
114                        foreach ($this->_dictionary->DecodeParms->items[$id]->getKeys() as $paramKey) {
115                            $this->_originalDictionary['DecodeParms'][$id][$paramKey] =
116                                  $this->_dictionary->DecodeParms->items[$id]->$paramKey->value;
117                        }
118                    }
119                }
120            }
121        } else if ($this->_dictionary->Filter->getType() != Zend_Pdf_Element::TYPE_NULL) {
122            $this->_originalDictionary['Filter'][0]      = $this->_dictionary->Filter->value;
123            $this->_originalDictionary['DecodeParms'][0] = array();
124            if ($this->_dictionary->DecodeParms !== null ) {
125                foreach ($this->_dictionary->DecodeParms->getKeys() as $paramKey) {
126                    $this->_originalDictionary['DecodeParms'][0][$paramKey] =
127                          $this->_dictionary->DecodeParms->$paramKey->value;
128                }
129            }
130        }
131
132        if ($this->_dictionary->F !== null) {
133            $this->_originalDictionary['F'] = $this->_dictionary->F->value;
134        }
135
136        $this->_originalDictionary['FFilter']      = array();
137        $this->_originalDictionary['FDecodeParms'] = array();
138        if ($this->_dictionary->FFilter === null) {
139            // Do nothing.
140        } else if ($this->_dictionary->FFilter->getType() == Zend_Pdf_Element::TYPE_ARRAY) {
141            foreach ($this->_dictionary->FFilter->items as $id => $filter) {
142                $this->_originalDictionary['FFilter'][$id]      = $filter->value;
143                $this->_originalDictionary['FDecodeParms'][$id] = array();
144
145                if ($this->_dictionary->FDecodeParms !== null ) {
146                    if ($this->_dictionary->FDecodeParms->items[$id] !== null &&
147                        $this->_dictionary->FDecodeParms->items[$id]->value !== null) {
148                        foreach ($this->_dictionary->FDecodeParms->items[$id]->getKeys() as $paramKey) {
149                            $this->_originalDictionary['FDecodeParms'][$id][$paramKey] =
150                                  $this->_dictionary->FDecodeParms->items[$id]->items[$paramKey]->value;
151                        }
152                    }
153                }
154            }
155        } else {
156            $this->_originalDictionary['FFilter'][0]      = $this->_dictionary->FFilter->value;
157            $this->_originalDictionary['FDecodeParms'][0] = array();
158            if ($this->_dictionary->FDecodeParms !== null ) {
159                foreach ($this->_dictionary->FDecodeParms->getKeys() as $paramKey) {
160                    $this->_originalDictionary['FDecodeParms'][0][$paramKey] =
161                          $this->_dictionary->FDecodeParms->items[$paramKey]->value;
162                }
163            }
164        }
165    }
166
167    /**
168     * Decode stream
169     *
170     * @throws Zend_Pdf_Exception
171     */
172    private function _decodeStream()
173    {
174        if ($this->_originalDictionary === null) {
175            $this->_storeOriginalDictionary();
176        }
177
178        /**
179         * All applied stream filters must be processed to decode stream.
180         * If we don't recognize any of applied filetrs an exception should be thrown here
181         */
182        if (isset($this->_originalDictionary['F'])) {
183            /** @todo Check, how external files can be processed. */
184            require_once 'Zend/Pdf/Exception.php';
185            throw new Zend_Pdf_Exception('External filters are not supported now.');
186        }
187
188        foreach ($this->_originalDictionary['Filter'] as $id => $filterName ) {
189            $valueRef = &$this->_value->value->getRef();
190            $this->_value->value->touch();
191            switch ($filterName) {
192                case 'ASCIIHexDecode':
193                    require_once 'Zend/Pdf/Filter/AsciiHex.php';
194                    $valueRef = Zend_Pdf_Filter_AsciiHex::decode($valueRef);
195                    break;
196
197                case 'ASCII85Decode':
198                    require_once 'Zend/Pdf/Filter/Ascii85.php';
199                    $valueRef = Zend_Pdf_Filter_Ascii85::decode($valueRef);
200                    break;
201
202                case 'FlateDecode':
203                    require_once 'Zend/Pdf/Filter/Compression/Flate.php';
204                    $valueRef = Zend_Pdf_Filter_Compression_Flate::decode($valueRef,
205                                                                          $this->_originalDictionary['DecodeParms'][$id]);
206                    break;
207
208                case 'LZWDecode':
209                    require_once 'Zend/Pdf/Filter/Compression/Lzw.php';
210                    $valueRef = Zend_Pdf_Filter_Compression_Lzw::decode($valueRef,
211                                                                        $this->_originalDictionary['DecodeParms'][$id]);
212                    break;
213
214                case 'RunLengthDecode':
215                    require_once 'Zend/Pdf/Filter/RunLength.php';
216                    $valueRef = Zend_Pdf_Filter_RunLength::decode($valueRef);
217                    break;
218
219                default:
220                    require_once 'Zend/Pdf/Exception.php';
221                    throw new Zend_Pdf_Exception('Unknown stream filter: \'' . $filterName . '\'.');
222            }
223        }
224
225        $this->_streamDecoded = true;
226    }
227
228    /**
229     * Encode stream
230     *
231     * @throws Zend_Pdf_Exception
232     */
233    private function _encodeStream()
234    {
235        /**
236         * All applied stream filters must be processed to encode stream.
237         * If we don't recognize any of applied filetrs an exception should be thrown here
238         */
239        if (isset($this->_originalDictionary['F'])) {
240            /** @todo Check, how external files can be processed. */
241            require_once 'Zend/Pdf/Exception.php';
242            throw new Zend_Pdf_Exception('External filters are not supported now.');
243        }
244
245        $filters = array_reverse($this->_originalDictionary['Filter'], true);
246
247        foreach ($filters as $id => $filterName ) {
248            $valueRef = &$this->_value->value->getRef();
249            $this->_value->value->touch();
250            switch ($filterName) {
251                case 'ASCIIHexDecode':
252                    require_once 'Zend/Pdf/Filter/AsciiHex.php';
253                    $valueRef = Zend_Pdf_Filter_AsciiHex::encode($valueRef);
254                    break;
255
256                case 'ASCII85Decode':
257                    require_once 'Zend/Pdf/Filter/Ascii85.php';
258                    $valueRef = Zend_Pdf_Filter_Ascii85::encode($valueRef);
259                    break;
260
261                case 'FlateDecode':
262                    require_once 'Zend/Pdf/Filter/Compression/Flate.php';
263                    $valueRef = Zend_Pdf_Filter_Compression_Flate::encode($valueRef,
264                                                                          $this->_originalDictionary['DecodeParms'][$id]);
265                    break;
266
267                case 'LZWDecode':
268                    require_once 'Zend/Pdf/Filter/Compression/Lzw.php';
269                    $valueRef = Zend_Pdf_Filter_Compression_Lzw::encode($valueRef,
270                                                                        $this->_originalDictionary['DecodeParms'][$id]);
271                    break;
272
273                 case 'RunLengthDecode':
274                    require_once 'Zend/Pdf/Filter/RunLength.php';
275                    $valueRef = Zend_Pdf_Filter_RunLength::encode($valueRef);
276                    break;
277
278               default:
279                    require_once 'Zend/Pdf/Exception.php';
280                    throw new Zend_Pdf_Exception('Unknown stream filter: \'' . $filterName . '\'.');
281            }
282        }
283
284        $this->_streamDecoded = false;
285    }
286
287    /**
288     * Get handler
289     *
290     * @param string $property
291     * @return mixed
292     * @throws Zend_Pdf_Exception
293     */
294    public function __get($property)
295    {
296        if ($property == 'dictionary') {
297            /**
298             * If stream is note decoded yet, then store original decoding options (do it only once).
299             */
300            if (( !$this->_streamDecoded ) && ($this->_originalDictionary === null)) {
301                $this->_storeOriginalDictionary();
302            }
303
304            return $this->_dictionary;
305        }
306
307        if ($property == 'value') {
308            if (!$this->_streamDecoded) {
309                $this->_decodeStream();
310            }
311
312            return $this->_value->value->getRef();
313        }
314
315        require_once 'Zend/Pdf/Exception.php';
316        throw new Zend_Pdf_Exception('Unknown stream object property requested.');
317    }
318
319
320    /**
321     * Set handler
322     *
323     * @param string $property
324     * @param  mixed $value
325     */
326    public function __set($property, $value)
327    {
328        if ($property == 'value') {
329            $valueRef = &$this->_value->value->getRef();
330            $valueRef = $value;
331            $this->_value->value->touch();
332
333            $this->_streamDecoded = true;
334
335            return;
336        }
337
338        require_once 'Zend/Pdf/Exception.php';
339        throw new Zend_Pdf_Exception('Unknown stream object property: \'' . $property . '\'.');
340    }
341
342
343    /**
344     * Treat stream data as already encoded
345     */
346    public function skipFilters()
347    {
348        $this->_streamDecoded = false;
349    }
350
351
352    /**
353     * Call handler
354     *
355     * @param string $method
356     * @param array  $args
357     * @return mixed
358     */
359    public function __call($method, $args)
360    {
361        if (!$this->_streamDecoded) {
362            $this->_decodeStream();
363        }
364
365        switch (count($args)) {
366            case 0:
367                return $this->_value->$method();
368            case 1:
369                return $this->_value->$method($args[0]);
370            default:
371                require_once 'Zend/Pdf/Exception.php';
372                throw new Zend_Pdf_Exception('Unsupported number of arguments');
373        }
374    }
375
376    /**
377     * Dump object to a string to save within PDF file
378     *
379     * $factory parameter defines operation context.
380     *
381     * @param Zend_Pdf_ElementFactory $factory
382     * @return string
383     */
384    public function dump(Zend_Pdf_ElementFactory $factory)
385    {
386        $shift = $factory->getEnumerationShift($this->_factory);
387
388        if ($this->_streamDecoded) {
389            $this->_storeOriginalDictionary();
390            $this->_encodeStream();
391        } else if ($this->_originalDictionary != null) {
392            $startDictionary = $this->_originalDictionary;
393            $this->_storeOriginalDictionary();
394            $newDictionary = $this->_originalDictionary;
395
396            if ($startDictionary !== $newDictionary) {
397                $this->_originalDictionary = $startDictionary;
398                $this->_decodeStream();
399
400                $this->_originalDictionary = $newDictionary;
401                $this->_encodeStream();
402            }
403        }
404
405        // Update stream length
406        $this->dictionary->Length->value = $this->_value->length();
407
408        return  $this->_objNum + $shift . " " . $this->_genNum . " obj \n"
409             .  $this->dictionary->toString($factory) . "\n"
410             .  $this->_value->toString($factory) . "\n"
411             . "endobj\n";
412    }
413
414    /**
415     * Clean up resources, used by object
416     */
417    public function cleanUp()
418    {
419        $this->_dictionary = null;
420        $this->_value      = null;
421    }
422}