Projet

Général

Profil

Paste
Télécharger (18,6 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / libraries / fpdi-version / fpdi.php @ 76df55b7

1
<?php
2
//
3
//  FPDI - Version 1.4.4
4
//
5
//    Copyright 2004-2013 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.4');
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
            } elseif ($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
            $this->_out('/Group <</Type/Group/S/Transparency>>');
384
            
385
            $nN = $this->n; // TCPDF: rem new "n"
386
            $this->n = $cN; // TCPDF: reset to current "n"
387
            if (is_subclass_of($this, 'TCPDF')) {
388
                    $p = $this->_getrawstream($p);
389
                    $this->_out('/Length ' . strlen($p) . ' >>');
390
                    $this->_out("stream\n" . $p . "\nendstream");
391
            } else {
392
                    $this->_out('/Length ' . strlen($p) . ' >>');
393
                            $this->_putstream($p);
394
            }
395
                    $this->_out('endobj');
396
                    $this->n = $nN; // TCPDF: reset to new "n"
397
        }
398
        
399
        $this->_putimportedobjects();
400
    }
401

    
402
    /**
403
     * Rewritten to handle existing own defined objects
404
     */
405
    function _newobj($obj_id = false, $onlynewobj = false) {
406
        if (!$obj_id) {
407
            $obj_id = ++$this->n;
408
        }
409

    
410
        //Begin a new object
411
        if (!$onlynewobj) {
412
            $this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer);
413
            $this->_out($obj_id . ' 0 obj');
414
            $this->_current_obj_id = $obj_id; // for later use with encryption
415
        }
416
        
417
        return $obj_id;
418
    }
419

    
420
    /**
421
     * Writes a value
422
     * Needed to rebuild the source document
423
     *
424
     * @param mixed $value A PDF-Value. Structure of values see cases in this method
425
     */
426
    function pdf_write_value(&$value)
427
    {
428
        if (is_subclass_of($this, 'TCPDF')) {
429
            parent::pdf_write_value($value);
430
        }
431
        
432
        switch ($value[0]) {
433

    
434
                    case PDF_TYPE_TOKEN:
435
                $this->_straightOut($value[1] . ' ');
436
                            break;
437
                    case PDF_TYPE_NUMERIC:
438
                    case PDF_TYPE_REAL:
439
                if (is_float($value[1]) && $value[1] != 0) {
440
                                $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' ');
441
                            } else {
442
                                $this->_straightOut($value[1] . ' ');
443
                            }
444
                            break;
445
                            
446
                    case PDF_TYPE_ARRAY:
447

    
448
                            // An array. Output the proper
449
                            // structure and move on.
450

    
451
                            $this->_straightOut('[');
452
                for ($i = 0; $i < count($value[1]); $i++) {
453
                                    $this->pdf_write_value($value[1][$i]);
454
                            }
455

    
456
                            $this->_out(']');
457
                            break;
458

    
459
                    case PDF_TYPE_DICTIONARY:
460

    
461
                            // A dictionary.
462
                            $this->_straightOut('<<');
463

    
464
                            reset ($value[1]);
465

    
466
                            while (list($k, $v) = each($value[1])) {
467
                                    $this->_straightOut($k . ' ');
468
                                    $this->pdf_write_value($v);
469
                            }
470

    
471
                            $this->_straightOut('>>');
472
                            break;
473

    
474
                    case PDF_TYPE_OBJREF:
475

    
476
                            // An indirect object reference
477
                            // Fill the object stack if needed
478
                            $cpfn =& $this->current_parser->filename;
479
                            
480
                            if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) {
481
                                $this->_newobj(false, true);
482
                                $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value);
483
                    $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!!
484
                }
485
                $objid = $this->_don_obj_stack[$cpfn][$value[1]][0];
486

    
487
                            $this->_out($objid . ' 0 R');
488
                            break;
489

    
490
                    case PDF_TYPE_STRING:
491

    
492
                            // A string.
493
                $this->_straightOut('(' . $value[1] . ')');
494

    
495
                            break;
496

    
497
                    case PDF_TYPE_STREAM:
498

    
499
                            // A stream. First, output the
500
                            // stream dictionary, then the
501
                            // stream data itself.
502
                $this->pdf_write_value($value[1]);
503
                            $this->_out('stream');
504
                            $this->_out($value[2][1]);
505
                            $this->_out('endstream');
506
                            break;
507
                            
508
            case PDF_TYPE_HEX:
509
                $this->_straightOut('<' . $value[1] . '>');
510
                break;
511

    
512
            case PDF_TYPE_BOOLEAN:
513
                        $this->_straightOut($value[1] ? 'true ' : 'false ');
514
                        break;
515
            
516
                    case PDF_TYPE_NULL:
517
                // The null object.
518

    
519
                            $this->_straightOut('null ');
520
                            break;
521
            }
522
    }
523
    
524
    
525
    /**
526
     * Modified so not each call will add a newline to the output.
527
     */
528
    function _straightOut($s) {
529
        if (!is_subclass_of($this, 'TCPDF')) {
530
            if($this->state==2)
531
                        $this->pages[$this->page] .= $s;
532
                else
533
                        $this->buffer .= $s;
534
        } else {
535
            if ($this->state == 2) {
536
                                if ($this->inxobj) {
537
                                        // we are inside an XObject template
538
                                        $this->xobjects[$this->xobjid]['outdata'] .= $s;
539
                                } elseif ((!$this->InFooter) AND isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) {
540
                                        // puts data before page footer
541
                                        $pagebuff = $this->getPageBuffer($this->page);
542
                                        $page = substr($pagebuff, 0, -$this->footerlen[$this->page]);
543
                                        $footer = substr($pagebuff, -$this->footerlen[$this->page]);
544
                                        $this->setPageBuffer($this->page, $page.$s.$footer);
545
                                        // update footer position
546
                                        $this->footerpos[$this->page] += strlen($s);
547
                                } else {
548
                                        // set page data
549
                                        $this->setPageBuffer($this->page, $s, true);
550
                                }
551
                        } elseif ($this->state > 0) {
552
                                // set general data
553
                                $this->setBuffer($s);
554
                        }
555
        }
556
    }
557

    
558
    /**
559
     * rewritten to close opened parsers
560
     *
561
     */
562
    function _enddoc() {
563
        parent::_enddoc();
564
        $this->_closeParsers();
565
    }
566
    
567
    /**
568
     * close all files opened by parsers
569
     */
570
    function _closeParsers() {
571
        if ($this->state > 2 && count($this->parsers) > 0) {
572
                  $this->cleanUp();
573
            return true;
574
        }
575
        return false;
576
    }
577
    
578
    /**
579
     * Removes cylced references and closes the file handles of the parser objects
580
     */
581
    function cleanUp() {
582
            foreach ($this->parsers as $k => $_){
583
                $this->parsers[$k]->cleanUp();
584
                $this->parsers[$k] = null;
585
                unset($this->parsers[$k]);
586
        }
587
    }
588
}