source: trunk/data/pdf/fpdi_pdf_parser.php @ 17232

Revision 17232, 10.7 KB checked in by satou, 16 years ago (diff)

納品書発行機能 by Yammy (merge r17182)

Line 
1<?php
2//
3//  FPDI - Version 1.2
4//
5//    Copyright 2004-2007 Setasign - Jan Slabon
6//
7//  Licensed under the Apache License, Version 2.0 (the "License");
8//  you may not use this file except in compliance with the License.
9//  You may obtain a copy of the License at
10//
11//      http://www.apache.org/licenses/LICENSE-2.0
12//
13//  Unless required by applicable law or agreed to in writing, software
14//  distributed under the License is distributed on an "AS IS" BASIS,
15//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16//  See the License for the specific language governing permissions and
17//  limitations under the License.
18//
19
20require_once("pdf_parser.php");
21
22class fpdi_pdf_parser extends pdf_parser {
23
24    /**
25     * Pages
26     * Index beginns at 0
27     *
28     * @var array
29     */
30    var $pages;
31   
32    /**
33     * Page count
34     * @var integer
35     */
36    var $page_count;
37   
38    /**
39     * actual page number
40     * @var integer
41     */
42    var $pageno;
43   
44    /**
45     * PDF Version of imported Document
46     * @var string
47     */
48    var $pdfVersion;
49   
50    /**
51     * FPDI Reference
52     * @var object
53     */
54    var $fpdi;
55   
56    /**
57     * Available BoxTypes
58     *
59     * @var array
60     */
61    var $availableBoxes = array("/MediaBox","/CropBox","/BleedBox","/TrimBox","/ArtBox");
62       
63    /**
64     * Constructor
65     *
66     * @param string $filename  Source-Filename
67     * @param object $fpdi      Object of type fpdi
68     */
69    function fpdi_pdf_parser($filename,&$fpdi) {
70        $this->fpdi =& $fpdi;
71        $this->filename = $filename;
72       
73        parent::pdf_parser($filename);
74
75        // resolve Pages-Dictonary
76        $pages = $this->pdf_resolve_object($this->c, $this->root[1][1]['/Pages']);
77
78        // Read pages
79        $this->read_pages($this->c, $pages, $this->pages);
80       
81        // count pages;
82        $this->page_count = count($this->pages);
83    }
84   
85    /**
86     * Overwrite parent::error()
87     *
88     * @param string $msg  Error-Message
89     */
90    function error($msg) {
91        $this->fpdi->error($msg);   
92    }
93   
94    /**
95     * Get pagecount from sourcefile
96     *
97     * @return int
98     */
99    function getPageCount() {
100        return $this->page_count;
101    }
102
103
104    /**
105     * Set pageno
106     *
107     * @param int $pageno Pagenumber to use
108     */
109    function setPageno($pageno) {
110        $pageno = ((int) $pageno) - 1;
111
112        if ($pageno < 0 || $pageno >= $this->getPageCount()) {
113            $this->fpdi->error("Pagenumber is wrong!");
114        }
115
116        $this->pageno = $pageno;
117    }
118   
119    /**
120     * Get page-resources from current page
121     *
122     * @return array
123     */
124    function getPageResources() {
125        return $this->_getPageResources($this->pages[$this->pageno]);
126    }
127   
128    /**
129     * Get page-resources from /Page
130     *
131     * @param array $obj Array of pdf-data
132     */
133    function _getPageResources ($obj) { // $obj = /Page
134        $obj = $this->pdf_resolve_object($this->c, $obj);
135
136        // If the current object has a resources
137        // dictionary associated with it, we use
138        // it. Otherwise, we move back to its
139        // parent object.
140        if (isset ($obj[1][1]['/Resources'])) {
141            $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Resources']);
142            if ($res[0] == PDF_TYPE_OBJECT)
143                return $res[1];
144            return $res;
145        } else {
146            if (!isset ($obj[1][1]['/Parent'])) {
147                return false;
148            } else {
149                $res = $this->_getPageResources($obj[1][1]['/Parent']);
150                if ($res[0] == PDF_TYPE_OBJECT)
151                    return $res[1];
152                return $res;
153            }
154        }
155    }
156
157
158    /**
159     * Get content of current page
160     *
161     * If more /Contents is an array, the streams are concated
162     *
163     * @return string
164     */
165    function getContent() {
166        $buffer = "";
167       
168        if (isset($this->pages[$this->pageno][1][1]['/Contents'])) {
169            $contents = $this->_getPageContent($this->pages[$this->pageno][1][1]['/Contents']);
170            foreach($contents AS $tmp_content) {
171                $buffer .= $this->_rebuildContentStream($tmp_content).' ';
172            }
173        }
174       
175        return $buffer;
176    }
177   
178   
179    /**
180     * Resolve all content-objects
181     *
182     * @param array $content_ref
183     * @return array
184     */
185    function _getPageContent($content_ref) {
186        $contents = array();
187       
188        if ($content_ref[0] == PDF_TYPE_OBJREF) {
189            $content = $this->pdf_resolve_object($this->c, $content_ref);
190            if ($content[1][0] == PDF_TYPE_ARRAY) {
191                $contents = $this->_getPageContent($content[1]);
192            } else {
193                $contents[] = $content;
194            }
195        } else if ($content_ref[0] == PDF_TYPE_ARRAY) {
196            foreach ($content_ref[1] AS $tmp_content_ref) {
197                $contents = array_merge($contents,$this->_getPageContent($tmp_content_ref));
198            }
199        }
200
201        return $contents;
202    }
203
204
205    /**
206     * Rebuild content-streams
207     *
208     * @param array $obj
209     * @return string
210     */
211    function _rebuildContentStream($obj) {
212        $filters = array();
213       
214        if (isset($obj[1][1]['/Filter'])) {
215            $_filter = $obj[1][1]['/Filter'];
216
217            if ($_filter[0] == PDF_TYPE_TOKEN) {
218                $filters[] = $_filter;
219            } else if ($_filter[0] == PDF_TYPE_ARRAY) {
220                $filters = $_filter[1];
221            }
222        }
223
224        $stream = $obj[2][1];
225
226        foreach ($filters AS $_filter) {
227            switch ($_filter[1]) {
228                case "/FlateDecode":
229                    if (function_exists('gzuncompress')) {
230                        $stream = (strlen($stream) > 0) ? @gzuncompress($stream) : '';                       
231                    } else {
232                        $this->fpdi->error(sprintf("To handle %s filter, please compile php with zlib support.",$_filter[1]));
233                    }
234                    if ($stream === false) {
235                        $this->fpdi->error("Error while decompressing stream.");
236                    }
237                break;
238                case null:
239                    $stream = $stream;
240                break;
241                default:
242                    if (preg_match("/^\/[a-z85]*$/i", $_filter[1], $filterName) && @include_once('decoders'.$_filter[1].'.php')) {
243                        $filterName = substr($_filter[1],1);
244                        if (class_exists($filterName)) {
245                            $decoder =& new $filterName($this->fpdi);
246                            $stream = $decoder->decode(trim($stream));
247                        } else {
248                            $this->fpdi->error(sprintf("Unsupported Filter: %s",$_filter[1]));
249                        }
250                    } else {
251                        $this->fpdi->error(sprintf("Unsupported Filter: %s",$_filter[1]));
252                    }
253            }
254        }
255       
256        return $stream;
257    }
258   
259   
260    /**
261     * Get a Box from a page
262     * Arrayformat is same as used by fpdf_tpl
263     *
264     * @param array $page a /Page
265     * @param string $box_index Type of Box @see $availableBoxes
266     * @return array
267     */
268    function getPageBox($page, $box_index) {
269        $page = $this->pdf_resolve_object($this->c,$page);
270        $box = null;
271        if (isset($page[1][1][$box_index]))
272            $box =& $page[1][1][$box_index];
273       
274        if (!is_null($box) && $box[0] == PDF_TYPE_OBJREF) {
275            $tmp_box = $this->pdf_resolve_object($this->c,$box);
276            $box = $tmp_box[1];
277        }
278           
279        if (!is_null($box) && $box[0] == PDF_TYPE_ARRAY) {
280            $b =& $box[1];
281            return array("x" => $b[0][1]/$this->fpdi->k,
282                         "y" => $b[1][1]/$this->fpdi->k,
283                         "w" => abs($b[0][1]-$b[2][1])/$this->fpdi->k,
284                         "h" => abs($b[1][1]-$b[3][1])/$this->fpdi->k);
285        } else if (!isset ($page[1][1]['/Parent'])) {
286            return false;
287        } else {
288            return $this->getPageBox($this->pdf_resolve_object($this->c, $page[1][1]['/Parent']), $box_index);
289        }
290    }
291
292    function getPageBoxes($pageno) {
293        return $this->_getPageBoxes($this->pages[$pageno-1]);
294    }
295   
296    /**
297     * Get all Boxes from /Page
298     *
299     * @param array a /Page
300     * @return array
301     */
302    function _getPageBoxes($page) {
303        $boxes = array();
304
305        foreach($this->availableBoxes AS $box) {
306            if ($_box = $this->getPageBox($page,$box)) {
307                $boxes[$box] = $_box;
308            }
309        }
310
311        return $boxes;
312    }
313
314    function getPageRotation($pageno) {
315        return $this->_getPageRotation($this->pages[$pageno-1]);
316    }
317   
318    function _getPageRotation ($obj) { // $obj = /Page
319        $obj = $this->pdf_resolve_object($this->c, $obj);
320        if (isset ($obj[1][1]['/Rotate'])) {
321            $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Rotate']);
322            if ($res[0] == PDF_TYPE_OBJECT)
323                return $res[1];
324            return $res;
325        } else {
326            if (!isset ($obj[1][1]['/Parent'])) {
327                return false;
328            } else {
329                $res = $this->_getPageRotation($obj[1][1]['/Parent']);
330                if ($res[0] == PDF_TYPE_OBJECT)
331                    return $res[1];
332                return $res;
333            }
334        }
335    }
336   
337    /**
338     * Read all /Page(es)
339     *
340     * @param object pdf_context
341     * @param array /Pages
342     * @param array the result-array
343     */
344    function read_pages (&$c, &$pages, &$result) {
345        // Get the kids dictionary
346        $kids = $this->pdf_resolve_object ($c, $pages[1][1]['/Kids']);
347
348        if (!is_array($kids))
349            $this->fpdi->Error("Cannot find /Kids in current /Page-Dictionary");
350        foreach ($kids[1] as $v) {
351            $pg = $this->pdf_resolve_object ($c, $v);
352            if ($pg[1][1]['/Type'][1] === '/Pages') {
353                // If one of the kids is an embedded
354                // /Pages array, resolve it as well.
355                $this->read_pages ($c, $pg, $result);
356            } else {
357                $result[] = $pg;
358            }
359        }
360    }
361
362   
363   
364    /**
365     * Get PDF-Version
366     *
367     * And reset the PDF Version used in FPDI if needed
368     */
369    function getPDFVersion() {
370        parent::getPDFVersion();
371       
372        if (isset($this->fpdi->importVersion) && $this->pdfVersion > $this->fpdi->importVersion) {
373            $this->fpdi->importVersion = $this->pdfVersion;
374        }
375    }
376   
377}
378
379?>
Note: See TracBrowser for help on using the repository browser.