Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
//
3
//  FPDI - Version 1.4.2
4
//
5
//    Copyright 2004-2011 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
 
20
define('FPDI_VERSION', '1.4.2');
21
 
22
// Check for TCPDF and remap TCPDF to FPDF
23
if (class_exists('TCPDF', false)) {
24
    require_once('fpdi2tcpdf_bridge.php');
25
}
26
 
27
require_once('fpdf_tpl.php');
28
require_once('fpdi_pdf_parser.php');
29
 
30
 
31
class FPDI extends FPDF_TPL {
32
    /**
33
     * Actual filename
34
     * @var string
35
     */
36
    var $current_filename;
37
 
38
    /**
39
     * Parser-Objects
40
     * @var array
41
     */
42
    var $parsers;
43
 
44
    /**
45
     * Current parser
46
     * @var object
47
     */
48
    var $current_parser;
49
 
50
    /**
51
     * object stack
52
     * @var array
53
     */
54
    var $_obj_stack;
55
 
56
    /**
57
     * done object stack
58
     * @var array
59
     */
60
    var $_don_obj_stack;
61
 
62
    /**
63
     * Current Object Id.
64
     * @var integer
65
     */
66
    var $_current_obj_id;
67
 
68
    /**
69
     * The name of the last imported page box
70
     * @var string
71
     */
72
    var $lastUsedPageBox;
73
 
74
    /**
75
     * Cache for imported pages/template ids
76
     * @var array
77
     */
78
    var $_importedPages = array();
79
 
80
    /**
81
     * Set a source-file
82
     *
83
     * @param string $filename a valid filename
84
     * @return int number of available pages
85
     */
86
    function setSourceFile($filename) {
87
        $this->current_filename = $filename;
88
 
89
        if (!isset($this->parsers[$filename]))
90
            $this->parsers[$filename] = $this->_getPdfParser($filename);
91
        $this->current_parser =& $this->parsers[$filename];
92
 
93
        return $this->parsers[$filename]->getPageCount();
94
    }
95
 
96
    /**
97
     * Returns a PDF parser object
98
     *
99
     * @param string $filename
100
     * @return fpdi_pdf_parser
101
     */
102
    function _getPdfParser($filename) {
103
    	return new fpdi_pdf_parser($filename, $this);
104
    }
105
 
106
    /**
107
     * Get the current PDF version
108
     *
109
     * @return string
110
     */
111
    function getPDFVersion() {
112
		return $this->PDFVersion;
113
	}
114
 
115
	/**
116
     * Set the PDF version
117
     *
118
     * @return string
119
     */
120
	function setPDFVersion($version = '1.3') {
121
		$this->PDFVersion = $version;
122
	}
123
 
124
    /**
125
     * Import a page
126
     *
127
     * @param int $pageno pagenumber
128
     * @return int Index of imported page - to use with fpdf_tpl::useTemplate()
129
     */
130
    function importPage($pageno, $boxName = '/CropBox') {
131
        if ($this->_intpl) {
132
            return $this->error('Please import the desired pages before creating a new template.');
133
        }
134
 
135
        $fn = $this->current_filename;
136
 
137
        // check if page already imported
138
        $pageKey = $fn . '-' . ((int)$pageno) . $boxName;
139
        if (isset($this->_importedPages[$pageKey]))
140
            return $this->_importedPages[$pageKey];
141
 
142
        $parser =& $this->parsers[$fn];
143
        $parser->setPageno($pageno);
144
 
145
        if (!in_array($boxName, $parser->availableBoxes))
146
            return $this->Error(sprintf('Unknown box: %s', $boxName));
147
 
148
        $pageboxes = $parser->getPageBoxes($pageno, $this->k);
149
 
150
        /**
151
         * MediaBox
152
         * CropBox: Default -> MediaBox
153
         * BleedBox: Default -> CropBox
154
         * TrimBox: Default -> CropBox
155
         * ArtBox: Default -> CropBox
156
         */
157
        if (!isset($pageboxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox'))
158
            $boxName = '/CropBox';
159
        if (!isset($pageboxes[$boxName]) && $boxName == '/CropBox')
160
            $boxName = '/MediaBox';
161
 
162
        if (!isset($pageboxes[$boxName]))
163
            return false;
164
 
165
        $this->lastUsedPageBox = $boxName;
166
 
167
        $box = $pageboxes[$boxName];
168
 
169
        $this->tpl++;
170
        $this->tpls[$this->tpl] = array();
171
        $tpl =& $this->tpls[$this->tpl];
172
        $tpl['parser'] =& $parser;
173
        $tpl['resources'] = $parser->getPageResources();
174
        $tpl['buffer'] = $parser->getContent();
175
        $tpl['box'] = $box;
176
 
177
        // To build an array that can be used by PDF_TPL::useTemplate()
178
        $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl], $box);
179
 
180
        // An imported page will start at 0,0 everytime. Translation will be set in _putformxobjects()
181
        $tpl['x'] = 0;
182
        $tpl['y'] = 0;
183
 
184
        // handle rotated pages
185
        $rotation = $parser->getPageRotation($pageno);
186
        $tpl['_rotationAngle'] = 0;
187
        if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) {
188
        	$steps = $angle / 90;
189
 
190
            $_w = $tpl['w'];
191
            $_h = $tpl['h'];
192
            $tpl['w'] = $steps % 2 == 0 ? $_w : $_h;
193
            $tpl['h'] = $steps % 2 == 0 ? $_h : $_w;
194
 
195
            if ($angle < 0)
196
            	$angle += 360;
197
 
198
        	$tpl['_rotationAngle'] = $angle * -1;
199
        }
200
 
201
        $this->_importedPages[$pageKey] = $this->tpl;
202
 
203
        return $this->tpl;
204
    }
205
 
206
    /**
207
     * Returns the last used page box
208
     *
209
     * @return string
210
     */
211
    function getLastUsedPageBox() {
212
        return $this->lastUsedPageBox;
213
    }
214
 
215
 
216
    function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0, $adjustPageSize = false) {
217
        if ($adjustPageSize == true && is_null($_x) && is_null($_y)) {
218
            $size = $this->getTemplateSize($tplidx, $_w, $_h);
219
            $orientation = $size['w'] > $size['h'] ? 'L' : 'P';
220
            $size = array($size['w'], $size['h']);
221
 
222
            if (is_subclass_of($this, 'TCPDF')) {
223
            	$this->setPageFormat($size, $orientation);
224
            } else {
225
            	$size = $this->_getpagesize($size);
226
 
227
            	if($orientation!=$this->CurOrientation || $size[0]!=$this->CurPageSize[0] || $size[1]!=$this->CurPageSize[1])
228
				{
229
					// New size or orientation
230
					if($orientation=='P')
231
					{
232
						$this->w = $size[0];
233
						$this->h = $size[1];
234
					}
235
					else
236
					{
237
						$this->w = $size[1];
238
						$this->h = $size[0];
239
					}
240
					$this->wPt = $this->w*$this->k;
241
					$this->hPt = $this->h*$this->k;
242
					$this->PageBreakTrigger = $this->h-$this->bMargin;
243
					$this->CurOrientation = $orientation;
244
					$this->CurPageSize = $size;
245
					$this->PageSizes[$this->page] = array($this->wPt, $this->hPt);
246
				}
247
            }
248
        }
249
 
250
        $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values
251
        $s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h);
252
        $this->_out('Q');
253
 
254
        return $s;
255
    }
256
 
257
    /**
258
     * Private method, that rebuilds all needed objects of source files
259
     */
260
    function _putimportedobjects() {
261
        if (is_array($this->parsers) && count($this->parsers) > 0) {
262
            foreach($this->parsers AS $filename => $p) {
263
                $this->current_parser =& $this->parsers[$filename];
264
                if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) {
265
                    while(($n = key($this->_obj_stack[$filename])) !== null) {
266
                        $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c, $this->_obj_stack[$filename][$n][1]);
267
 
268
                        $this->_newobj($this->_obj_stack[$filename][$n][0]);
269
 
270
                        if ($nObj[0] == PDF_TYPE_STREAM) {
271
							$this->pdf_write_value($nObj);
272
                        } else {
273
                            $this->pdf_write_value($nObj[1]);
274
                        }
275
 
276
                        $this->_out('endobj');
277
                        $this->_obj_stack[$filename][$n] = null; // free memory
278
                        unset($this->_obj_stack[$filename][$n]);
279
                        reset($this->_obj_stack[$filename]);
280
                    }
281
                }
282
            }
283
        }
284
    }
285
 
286
 
287
    /**
288
     * Private Method that writes the form xobjects
289
     */
290
    function _putformxobjects() {
291
        $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
292
	    reset($this->tpls);
293
        foreach($this->tpls AS $tplidx => $tpl) {
294
            $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
295
    		$this->_newobj();
296
    		$cN = $this->n; // TCPDF/Protection: rem current "n"
297
 
298
    		$this->tpls[$tplidx]['n'] = $this->n;
299
    		$this->_out('<<' . $filter . '/Type /XObject');
300
            $this->_out('/Subtype /Form');
301
            $this->_out('/FormType 1');
302
 
303
            $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
304
                (isset($tpl['box']['llx']) ? $tpl['box']['llx'] : $tpl['x']) * $this->k,
305
                (isset($tpl['box']['lly']) ? $tpl['box']['lly'] : -$tpl['y']) * $this->k,
306
                (isset($tpl['box']['urx']) ? $tpl['box']['urx'] : $tpl['w'] + $tpl['x']) * $this->k,
307
                (isset($tpl['box']['ury']) ? $tpl['box']['ury'] : $tpl['h'] - $tpl['y']) * $this->k
308
            ));
309
 
310
            $c = 1;
311
            $s = 0;
312
            $tx = 0;
313
            $ty = 0;
314
 
315
            if (isset($tpl['box'])) {
316
                $tx = -$tpl['box']['llx'];
317
                $ty = -$tpl['box']['lly'];
318
 
319
                if ($tpl['_rotationAngle'] <> 0) {
320
                    $angle = $tpl['_rotationAngle'] * M_PI/180;
321
                    $c=cos($angle);
322
                    $s=sin($angle);
323
 
324
                    switch($tpl['_rotationAngle']) {
325
                        case -90:
326
                           $tx = -$tpl['box']['lly'];
327
                           $ty = $tpl['box']['urx'];
328
                           break;
329
                        case -180:
330
                            $tx = $tpl['box']['urx'];
331
                            $ty = $tpl['box']['ury'];
332
                            break;
333
                        case -270:
334
                        	$tx = $tpl['box']['ury'];
335
                            $ty = -$tpl['box']['llx'];
336
                            break;
337
                    }
338
                }
339
            } else if ($tpl['x'] != 0 || $tpl['y'] != 0) {
340
                $tx = -$tpl['x'] * 2;
341
                $ty = $tpl['y'] * 2;
342
            }
343
 
344
            $tx *= $this->k;
345
            $ty *= $this->k;
346
 
347
            if ($c != 1 || $s != 0 || $tx != 0 || $ty != 0) {
348
                $this->_out(sprintf('/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]',
349
                    $c, $s, -$s, $c, $tx, $ty
350
                ));
351
            }
352
 
353
            $this->_out('/Resources ');
354
 
355
            if (isset($tpl['resources'])) {
356
                $this->current_parser =& $tpl['parser'];
357
                $this->pdf_write_value($tpl['resources']); // "n" will be changed
358
            } else {
359
                $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
360
            	if (isset($this->_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) {
361
                	$this->_out('/Font <<');
362
                    foreach($this->_res['tpl'][$tplidx]['fonts'] as $font)
363
                		$this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
364
                	$this->_out('>>');
365
                }
366
            	if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) ||
367
            	   isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls']))
368
            	{
369
                    $this->_out('/XObject <<');
370
                    if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) {
371
                        foreach($this->_res['tpl'][$tplidx]['images'] as $image)
372
                  			$this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
373
                    }
374
                    if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) {
375
                        foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl)
376
                            $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R');
377
                    }
378
                    $this->_out('>>');
379
            	}
380
            	$this->_out('>>');
381
            }
382
 
383
            $nN = $this->n; // TCPDF: rem new "n"
384
            $this->n = $cN; // TCPDF: reset to current "n"
385
            if (is_subclass_of($this, 'TCPDF')) {
386
            	$p = $this->_getrawstream($p);
387
            	$this->_out('/Length ' . strlen($p) . ' >>');
388
            	$this->_out("stream\n" . $p . "\nendstream");
389
            } else {
390
	            $this->_out('/Length ' . strlen($p) . ' >>');
391
	    		$this->_putstream($p);
392
            }
393
    		$this->_out('endobj');
394
    		$this->n = $nN; // TCPDF: reset to new "n"
395
        }
396
 
397
        $this->_putimportedobjects();
398
    }
399
 
400
    /**
401
     * Rewritten to handle existing own defined objects
402
     */
403
    function _newobj($obj_id = false, $onlynewobj = false) {
404
        if (!$obj_id) {
405
            $obj_id = ++$this->n;
406
        }
407
 
408
        //Begin a new object
409
        if (!$onlynewobj) {
410
            $this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer);
411
            $this->_out($obj_id . ' 0 obj');
412
            $this->_current_obj_id = $obj_id; // for later use with encryption
413
        }
414
 
415
        return $obj_id;
416
    }
417
 
418
    /**
419
     * Writes a value
420
     * Needed to rebuild the source document
421
     *
422
     * @param mixed $value A PDF-Value. Structure of values see cases in this method
423
     */
424
    function pdf_write_value(&$value)
425
    {
426
        if (is_subclass_of($this, 'TCPDF')) {
427
            parent::pdf_write_value($value);
428
        }
429
 
430
        switch ($value[0]) {
431
 
432
    		case PDF_TYPE_TOKEN:
433
                $this->_straightOut($value[1] . ' ');
434
    			break;
435
		    case PDF_TYPE_NUMERIC:
436
    		case PDF_TYPE_REAL:
437
                if (is_float($value[1]) && $value[1] != 0) {
438
    			    $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' ');
439
    			} else {
440
        			$this->_straightOut($value[1] . ' ');
441
    			}
442
    			break;
443
 
444
    		case PDF_TYPE_ARRAY:
445
 
446
    			// An array. Output the proper
447
    			// structure and move on.
448
 
449
    			$this->_straightOut('[');
450
                for ($i = 0; $i < count($value[1]); $i++) {
451
    				$this->pdf_write_value($value[1][$i]);
452
    			}
453
 
454
    			$this->_out(']');
455
    			break;
456
 
457
    		case PDF_TYPE_DICTIONARY:
458
 
459
    			// A dictionary.
460
    			$this->_straightOut('<<');
461
 
462
    			reset ($value[1]);
463
 
464
    			while (list($k, $v) = each($value[1])) {
465
    				$this->_straightOut($k . ' ');
466
    				$this->pdf_write_value($v);
467
    			}
468
 
469
    			$this->_straightOut('>>');
470
    			break;
471
 
472
    		case PDF_TYPE_OBJREF:
473
 
474
    			// An indirect object reference
475
    			// Fill the object stack if needed
476
    			$cpfn =& $this->current_parser->filename;
477
 
478
    			if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) {
479
    			    $this->_newobj(false, true);
480
    			    $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value);
481
                    $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!!
482
                }
483
                $objid = $this->_don_obj_stack[$cpfn][$value[1]][0];
484
 
485
    			$this->_out($objid . ' 0 R');
486
    			break;
487
 
488
    		case PDF_TYPE_STRING:
489
 
490
    			// A string.
491
                $this->_straightOut('(' . $value[1] . ')');
492
 
493
    			break;
494
 
495
    		case PDF_TYPE_STREAM:
496
 
497
    			// A stream. First, output the
498
    			// stream dictionary, then the
499
    			// stream data itself.
500
                $this->pdf_write_value($value[1]);
501
    			$this->_out('stream');
502
    			$this->_out($value[2][1]);
503
    			$this->_out('endstream');
504
    			break;
505
 
506
            case PDF_TYPE_HEX:
507
                $this->_straightOut('<' . $value[1] . '>');
508
                break;
509
 
510
            case PDF_TYPE_BOOLEAN:
511
    		    $this->_straightOut($value[1] ? 'true ' : 'false ');
512
    		    break;
513
 
514
    		case PDF_TYPE_NULL:
515
                // The null object.
516
 
517
    			$this->_straightOut('null ');
518
    			break;
519
    	}
520
    }
521
 
522
 
523
    /**
524
     * Modified so not each call will add a newline to the output.
525
     */
526
    function _straightOut($s) {
527
        if (!is_subclass_of($this, 'TCPDF')) {
528
            if($this->state==2)
529
        		$this->pages[$this->page] .= $s;
530
        	else
531
        		$this->buffer .= $s;
532
        } else {
533
            if ($this->state == 2) {
534
				if (isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) {
535
					// puts data before page footer
536
					$page = substr($this->getPageBuffer($this->page), 0, -$this->footerlen[$this->page]);
537
					$footer = substr($this->getPageBuffer($this->page), -$this->footerlen[$this->page]);
538
					$this->setPageBuffer($this->page, $page . ' ' . $s . "\n" . $footer);
539
				} else {
540
					$this->setPageBuffer($this->page, $s, true);
541
				}
542
			} else {
543
				$this->setBuffer($s);
544
			}
545
        }
546
    }
547
 
548
    /**
549
     * rewritten to close opened parsers
550
     *
551
     */
552
    function _enddoc() {
553
        parent::_enddoc();
554
        $this->_closeParsers();
555
    }
556
 
557
    /**
558
     * close all files opened by parsers
559
     */
560
    function _closeParsers() {
561
        if ($this->state > 2 && count($this->parsers) > 0) {
562
          	foreach ($this->parsers as $k => $_){
563
            	$this->parsers[$k]->closeFile();
564
            	$this->parsers[$k] = null;
565
            	unset($this->parsers[$k]);
566
            }
567
            return true;
568
        }
569
        return false;
570
    }
571
}