Passed
Push — master ( f753cb...380f19 )
by Roberto
01:24
created

Fpdf::addPage()   F

Complexity

Conditions 11
Paths 1024

Size

Total Lines 69
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 13.5606

Importance

Changes 0
Metric Value
cc 11
eloc 46
nc 1024
nop 2
dl 0
loc 69
ccs 34
cts 47
cp 0.7234
crap 13.5606
rs 3.6486
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace NFePHP\DA\Legacy\FPDF;
4
5
class Fpdf
6
{
7
    const FPDF_VERSION = '1.6';
8
    
9
    public $page;               //current page number
10
    public $n;                  //current object number
11
    public $offsets;            //array of object offsets
12
    public $buffer;             //buffer holding in-memory PDF
13
    public $pages;              //array containing pages
14
    public $state;              //current document state
15
    public $compress;           //compression flag
16
    public $k;                  //scale factor (number of points in user unit)
17
    public $defOrientation;     //default orientation
18
    public $curOrientation;     //current orientation
19
    public $pageFormats;        //available page formats
20
    public $defPageFormat;      //default page format
21
    public $curPageFormat;      //current page format
22
    public $pageSizes;          //array storing non-default page sizes
23
    public $wPt;
24
    public $hPt;           //dimensions of current page in points
25
    public $w;
26
    public $h;               //dimensions of current page in user unit
27
    public $lMargin;            //left margin
28
    public $tMargin;            //top margin
29
    public $rMargin;            //right margin
30
    public $bMargin;            //page break margin
31
    public $cMargin;            //cell margin
32
    public $x;
33
    public $y;               //current position in user unit
34
    public $lasth;              //height of last printed cell
35
    public $lineWidth;          //line width in user unit
36
    public $coreFonts;          //array of standard font names
37
    public $fonts;              //array of used fonts
38
    public $fontFiles;          //array of font files
39
    public $diffs;              //array of encoding differences
40
    public $fontFamily;         //current font family
41
    public $fontStyle;          //current font style
42
    public $underline;          //underlining flag
43
    public $currentFont;        //current font info
44
    public $fontSizePt;         //current font size in points
45
    public $fontSize;           //current font size in user unit
46
    public $drawColor;          //commands for drawing color
47
    public $fillColor;          //commands for filling color
48
    public $textColor;          //commands for text color
49
    public $colorFlag;          //indicates whether fill and text colors are different
50
    public $ws;                 //word spacing
51
    public $images;             //array of used images
52
    public $PageLinks;          //array of links in pages
53
    public $links;              //array of internal links
54
    public $autoPageBreak;      //automatic page breaking
55
    public $pageBreakTrigger;   //threshold used to trigger page breaks
56
    public $inHeader;           //flag set when processing header
57
    public $inFooter;           //flag set when processing footer
58
    public $zoomMode;           //zoom display mode
59
    public $layoutMode;         //layout display mode
60
    public $title;              //title
61
    public $subject;            //subject
62
    public $author;             //author
63
    public $keywords;           //keywords
64
    public $creator;            //creator
65
    public $aliasNbPages;       //alias for total number of pages
66
    public $pdfVersion;         //PDF version number
67
    
68 1
    public function __construct($orientation = 'P', $unit = 'mm', $format = 'A4')
69
    {
70
        //Some checks
71 1
        $this->dochecks();
72
        //Initialization of properties
73 1
        $this->page = 0;
74 1
        $this->n = 2;
75 1
        $this->buffer = '';
76 1
        $this->pages = array();
77 1
        $this->pageSizes = array();
78 1
        $this->state = 0;
79 1
        $this->fonts = array();
80 1
        $this->fontFiles = array();
81 1
        $this->diffs = array();
82 1
        $this->images = array();
83 1
        $this->links = array();
84 1
        $this->inHeader = false;
85 1
        $this->inFooter = false;
86 1
        $this->lasth = 0;
87 1
        $this->fontFamily = '';
88 1
        $this->fontStyle = '';
89 1
        $this->fontSizePt = 12;
90 1
        $this->underline = false;
91 1
        $this->drawColor = '0 G';
92 1
        $this->fillColor = '0 g';
93 1
        $this->textColor = '0 g';
94 1
        $this->colorFlag = false;
95 1
        $this->ws = 0;
96
        //Standard fonts
97 1
        $this->coreFonts = [
98
            'courier'=>'Courier',
99
            'courierB'=>'Courier-Bold',
100
            'courierI'=>'Courier-Oblique',
101
            'courierBI'=>'Courier-BoldOblique',
102
            'helvetica'=>'Helvetica',
103
            'helveticaB'=>'Helvetica-Bold',
104
            'helveticaI'=>'Helvetica-Oblique',
105
            'helveticaBI'=>'Helvetica-BoldOblique',
106
            'times'=>'Times-Roman',
107
            'timesB'=>'Times-Bold',
108
            'timesI'=>'Times-Italic',
109
            'timesBI'=>'Times-BoldItalic',
110
            'symbol'=>'Symbol',
111
            'zapfdingbats'=>'ZapfDingbats'
112
        ];
113
        //Scale factor
114 1
        if ($unit == 'pt') {
115
            $this->k = 1;
116 1
        } elseif ($unit == 'mm') {
117 1
            $this->k = 72/25.4;
118
        } elseif ($unit == 'cm') {
119
            $this->k = 72/2.54;
120
        } elseif ($unit == 'in') {
121
            $this->k = 72;
122
        } else {
123
            $this->error('Incorrect unit: '.$unit);
124
        }
125
        //Page format
126 1
        $this->pageFormats = array(
127
            'a3' => array(841.89,1190.55),
128
            'a4' => array(595.28,841.89),
129
            'a5' => array(420.94,595.28),
130
            'letter' => array(612,792),
131
            'legal' => array(612,1008)
132
        );
133 1
        if (is_string($format)) {
134 1
            $format = $this->getpageformat($format);
135
        }
136 1
        $this->defPageFormat = $format;
137 1
        $this->curPageFormat = $format;
138
        //Page orientation
139 1
        $orientation = strtolower($orientation);
140 1
        if ($orientation == 'p' || $orientation == 'portrait') {
141 1
            $this->defOrientation='P';
142 1
            $this->w = $this->defPageFormat[0];
143 1
            $this->h = $this->defPageFormat[1];
144
        } elseif ($orientation == 'l' || $orientation == 'landscape') {
145
            $this->defOrientation = 'L';
146
            $this->w = $this->defPageFormat[1];
147
            $this->h = $this->defPageFormat[0];
148
        } else {
149
            $this->error('Incorrect orientation: '.$orientation);
150
        }
151 1
        $this->curOrientation = $this->defOrientation;
152 1
        $this->wPt = $this->w*$this->k;
153 1
        $this->hPt = $this->h*$this->k;
154
        //Page margins (1 cm)
155 1
        $margin = 28.35/$this->k;
156 1
        $this->setMargins($margin, $margin);
157
        //Interior cell margin (1 mm)
158 1
        $this->cMargin = $margin/10;
159
        //Line width (0.2 mm)
160 1
        $this->lineWidth = .567/$this->k;
161
        //Automatic page break
162 1
        $this->setAutoPageBreak(true, 2*$margin);
163
        //Full width display mode
164 1
        $this->setDisplayMode('fullwidth');
165
        //Enable compression
166 1
        $this->setCompression(true);
167
        //Set default PDF version number
168 1
        $this->pdfVersion='1.3';
169 1
    }
170
171 1
    public function setMargins($left, $top, $right = null)
172
    {
173
        //Set left, top and right margins
174 1
        $this->lMargin = $left;
175 1
        $this->tMargin = $top;
176 1
        if ($right === null) {
177 1
            $right = $left;
178
        }
179 1
        $this->rMargin=$right;
180 1
    }
181
182
    public function setLeftMargin($margin)
183
    {
184
        //Set left margin
185
        $this->lMargin = $margin;
186
        if ($this->page>0 && $this->x<$margin) {
187
            $this->x = $margin;
188
        }
189
    }
190
191
    public function setTopMargin($margin)
192
    {
193
        //Set top margin
194
        $this->tMargin = $margin;
195
    }
196
197
    public function setRightMargin($margin)
198
    {
199
        //Set right margin
200
        $this->rMargin = $margin;
201
    }
202
203 1
    public function setAutoPageBreak($auto, $margin = 0)
204
    {
205
        //Set auto page break mode and triggering margin
206 1
        $this->autoPageBreak = $auto;
207 1
        $this->bMargin = $margin;
208 1
        $this->pageBreakTrigger = $this->h-$margin;
209 1
    }
210
211 1
    public function setDisplayMode($zoom, $layout = 'continuous')
212
    {
213
        //Set display mode in viewer
214 1
        if ($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom)) {
215 1
            $this->zoomMode = $zoom;
216
        } else {
217
            $this->error('Incorrect zoom display mode: '.$zoom);
218
        }
219 1
        if ($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default') {
220 1
            $this->layoutMode = $layout;
221
        } else {
222
            $this->error('Incorrect layout display mode: '.$layout);
223
        }
224 1
    }
225
226 1
    public function setCompression($compress)
227
    {
228
        //Set page compression
229 1
        if (function_exists('gzcompress')) {
230 1
            $this->compress = $compress;
231
        } else {
232
            $this->compress = false;
233
        }
234 1
    }
235
236
    public function setTitle($title, $isUTF8 = false)
237
    {
238
        //Title of document
239
        if ($isUTF8) {
240
            $title = $this->utf8Toutf16($title);
241
        }
242
        $this->title = $title;
243
    }
244
245
    public function setSubject($subject, $isUTF8 = false)
246
    {
247
        //Subject of document
248
        if ($isUTF8) {
249
            $subject = $this->utf8Toutf16($subject);
250
        }
251
        $this->subject = $subject;
252
    }
253
254
    public function setAuthor($author, $isUTF8 = false)
255
    {
256
        //Author of document
257
        if ($isUTF8) {
258
            $author = $this->utf8Toutf16($author);
259
        }
260
        $this->author=$author;
261
    }
262
263
    public function setKeywords($keywords, $isUTF8 = false)
264
    {
265
        //Keywords of document
266
        if ($isUTF8) {
267
            $keywords = $this->utf8Toutf16($keywords);
268
        }
269
        $this->keywords = $keywords;
270
    }
271
272
    public function setCreator($creator, $isUTF8 = false)
273
    {
274
        //Creator of document
275
        if ($isUTF8) {
276
            $creator = $this->utf8Toutf16($creator);
277
        }
278
        $this->creator = $creator;
279
    }
280
281 1
    public function aliasNbPages($alias = '{nb}')
282
    {
283
        //Define an alias for total number of pages
284 1
        $this->aliasNbPages=$alias;
285 1
    }
286
287
    public function error($msg)
288
    {
289
        throw new \Exception($msg);
290
    }
291
292 1
    public function open()
293
    {
294
        //Begin document
295 1
        $this->state = 1;
296 1
    }
297
298 1
    public function close()
299
    {
300
        //Terminate document
301 1
        if ($this->state == 3) {
302
            return;
303
        }
304 1
        if ($this->page == 0) {
305
            $this->addPage();
306
        }
307
        //Page footer
308 1
        $this->inFooter = true;
309 1
        $this->footer();
310 1
        $this->inFooter = false;
311
        //Close page
312 1
        $this->endPage();
313
        //Close document
314 1
        $this->endDoc();
315 1
    }
316
317 1
    public function addPage($orientation = '', $format = '')
318
    {
319
        //Start a new page
320 1
        if ($this->state==0) {
321
            $this->open();
322
        }
323 1
        $family = $this->fontFamily;
324 1
        $style = $this->fontStyle.($this->underline ? 'U' : '');
325 1
        $size = $this->fontSizePt;
326 1
        $lw = $this->lineWidth;
327 1
        $dc = $this->drawColor;
328 1
        $fc = $this->fillColor;
329 1
        $tc = $this->textColor;
330 1
        $cf = $this->colorFlag;
331 1
        if ($this->page > 0) {
332
            //Page footer
333
            $this->inFooter = true;
334
            $this->footer();
335
            $this->inFooter = false;
336
            //Close page
337
            $this->endPage();
338
        }
339
        //Start new page
340 1
        $this->beginPage($orientation, $format);
341
        //Set line cap style to square
342 1
        $this->out('2 J');
343
        //Set line width
344 1
        $this->lineWidth = $lw;
345 1
        $this->out(sprintf('%.2F w', $lw*$this->k));
346
        //Set font
347 1
        if ($family) {
348
            $this->setFont($family, $style, $size);
349
        }
350
        //Set colors
351 1
        $this->drawColor = $dc;
352 1
        if ($dc!='0 G') {
353 1
            $this->out($dc);
354
        }
355 1
        $this->fillColor = $fc;
356 1
        if ($fc != '0 g') {
357 1
            $this->out($fc);
358
        }
359 1
        $this->textColor = $tc;
360 1
        $this->colorFlag = $cf;
361
        //Page header
362 1
        $this->inHeader = true;
363 1
        $this->Header();
364 1
        $this->inHeader = false;
365
        //Restore line width
366 1
        if ($this->lineWidth != $lw) {
367
            $this->lineWidth = $lw;
368
            $this->out(sprintf('%.2F w', $lw*$this->k));
369
        }
370
        //Restore font
371 1
        if ($family) {
372
            $this->setFont($family, $style, $size);
373
        }
374
        //Restore colors
375 1
        if ($this->drawColor != $dc) {
376
            $this->drawColor = $dc;
377
            $this->out($dc);
378
        }
379 1
        if ($this->fillColor != $fc) {
380
            $this->fillColor = $fc;
381
            $this->out($fc);
382
        }
383 1
        $this->textColor = $tc;
384 1
        $this->colorFlag = $cf;
385 1
    }
386
387 1
    public function header()
388
    {
389
        //To be implemented in your own inherited class
390 1
    }
391
392 1
    public function footer()
393
    {
394
        //To be implemented in your own inherited class
395 1
    }
396
397
    public function pageNo()
398
    {
399
        //Get current page number
400
        return $this->page;
401
    }
402
403 1
    public function setDrawColor($r, $g = null, $b = null)
404
    {
405
        //Set color for all stroking operations
406 1
        if (($r==0 && $g==0 && $b==0) || $g===null) {
407 1
            $this->drawColor = sprintf('%.3F G', $r/255);
408
        } else {
409
            $this->drawColor = sprintf('%.3F %.3F %.3F RG', $r/255, $g/255, $b/255);
410
        }
411 1
        if ($this->page > 0) {
412
            $this->out($this->drawColor);
413
        }
414 1
    }
415
416 1
    public function setFillColor($r, $g = null, $b = null)
417
    {
418
        //Set color for all filling operations
419 1
        if (($r==0 && $g==0 && $b==0) || $g===null) {
420 1
            $this->fillColor = sprintf('%.3F g', $r/255);
421
        } else {
422 1
            $this->fillColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255);
423
        }
424 1
        $this->colorFlag = ($this->fillColor != $this->textColor);
425 1
        if ($this->page > 0) {
426 1
            $this->out($this->fillColor);
427
        }
428 1
    }
429
430 1
    public function settextColor($r, $g = null, $b = null)
431
    {
432
        //Set color for text
433 1
        if (($r==0 && $g==0 && $b==0) || $g===null) {
434 1
            $this->textColor = sprintf('%.3F g', $r/255);
435
        } else {
436 1
            $this->textColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255);
437
        }
438 1
        $this->colorFlag = ($this->fillColor != $this->textColor);
439 1
    }
440
441 1
    public function getStringWidth($s)
442
    {
443
        //Get width of a string in the current font
444 1
        $s = (string)$s;
445 1
        $cw =& $this->currentFont['cw'];
446 1
        $w = 0;
447 1
        $l = strlen($s);
448 1
        for ($i=0; $i<$l; $i++) {
449 1
            $w += $cw[$s[$i]];
450
        }
451 1
        return $w*$this->fontSize/1000;
452
    }
453
454 1
    public function setLineWidth($width)
455
    {
456
        //Set line width
457 1
        $this->lineWidth = $width;
458 1
        if ($this->page > 0) {
459 1
            $this->out(sprintf('%.2F w', $width*$this->k));
460
        }
461 1
    }
462
463
    public function line($x1, $y1, $x2, $y2)
464
    {
465
        //Draw a line
466
        $this->out(
467
            sprintf(
468
                '%.2F %.2F m %.2F %.2F l S',
469
                $x1*$this->k,
470
                ($this->h-$y1)*$this->k,
471
                $x2*$this->k,
472
                ($this->h-$y2)*$this->k
473
            )
474
        );
475
    }
476
477 1
    public function rect($x, $y, $w, $h, $style = '')
478
    {
479
        //Draw a rectangle
480 1
        if ($style == 'F') {
481 1
            $op = 'f';
482
        } elseif ($style == 'FD' || $style == 'DF') {
483
            $op = 'B';
484
        } else {
485
            $op = 'S';
486
        }
487 1
        $this->out(
488
            sprintf(
489 1
                '%.2F %.2F %.2F %.2F re %s',
490 1
                $x*$this->k,
491 1
                ($this->h-$y)*$this->k,
492 1
                $w*$this->k,
493 1
                -$h*$this->k,
494
                $op
495
            )
496
        );
497 1
    }
498
499
    public function addFont($family, $style = '', $file = '')
500
    {
501
        //Add a TrueType or Type1 font
502
        $family = strtolower($family);
503
        if ($file == '') {
504
            $file = str_replace(' ', '', $family).strtolower($style).'.php';
505
        }
506
        if ($family=='arial') {
507
            $family='helvetica';
508
        }
509
        $style = strtoupper($style);
510
        if ($style == 'IB') {
511
            $style = 'BI';
512
        }
513
        $fontkey = $family.$style;
514
        if (isset($this->fonts[$fontkey])) {
515
            return;
516
        }
517
        include $this->getFontPath().$file;
518
        if (!isset($name)) {
0 ignored issues
show
Bug introduced by
The variable $name seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
519
            $this->error('Could not include font definition file');
520
        }
521
        $i = count($this->fonts)+1;
522
        $this->fonts[$fontkey] = [
523
            'i'=>$i,
524
            'type'=>$type,
0 ignored issues
show
Bug introduced by
The variable $type does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
525
            'name'=>$name,
0 ignored issues
show
Bug introduced by
The variable $name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
526
            'desc'=>$desc,
0 ignored issues
show
Bug introduced by
The variable $desc does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
527
            'up'=>$up,
0 ignored issues
show
Bug introduced by
The variable $up does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
528
            'ut'=>$ut,
0 ignored issues
show
Bug introduced by
The variable $ut does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
529
            'cw'=>$cw,
0 ignored issues
show
Bug introduced by
The variable $cw does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
530
            'enc'=>$enc,
0 ignored issues
show
Bug introduced by
The variable $enc does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
531
            'file'=>$file
532
        ];
533
        if ($diff) {
534
            //Search existing encodings
535
            $d = 0;
536
            $nb = count($this->diffs);
537
            for ($i=1; $i<=$nb; $i++) {
538
                if ($this->diffs[$i] == $diff) {
0 ignored issues
show
Bug introduced by
The variable $diff does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
539
                    $d = $i;
540
                    break;
541
                }
542
            }
543
            if ($d == 0) {
544
                $d = $nb+1;
545
                $this->diffs[$d] = $diff;
546
            }
547
            $this->fonts[$fontkey]['diff'] = $d;
548
        }
549
        if ($file) {
550
            if ($type=='TrueType') {
551
                $this->fontFiles[$file] = array('length1'=>$originalsize);
0 ignored issues
show
Bug introduced by
The variable $originalsize does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
552
            } else {
553
                $this->fontFiles[$file] = array('length1'=>$size1, 'length2'=>$size2);
0 ignored issues
show
Bug introduced by
The variable $size1 does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $size2 does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
554
            }
555
        }
556
    }
557
558 1
    public function setFont($family, $style = '', $size = 0)
559
    {
560
        //Select a font; size given in points
561 1
        global $fpdf_charwidths;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
562 1
        $family = strtolower($family);
563 1
        if ($family == '') {
564
            $family = $this->fontFamily;
565
        }
566 1
        if ($family == 'arial') {
567
            $family = 'helvetica';
568 1
        } elseif ($family == 'symbol' || $family == 'zapfdingbats') {
569
            $style = '';
570
        }
571 1
        $style = strtoupper($style);
572 1
        if (strpos($style, 'U') !== false) {
573
            $this->underline = true;
574
            $style = str_replace('U', '', $style);
575
        } else {
576 1
            $this->underline = false;
577
        }
578 1
        if ($style == 'IB') {
579
            $style = 'BI';
580
        }
581 1
        if ($size == 0) {
582
            $size = $this->fontSizePt;
583
        }
584
        //Test if font is already selected
585 1
        if ($this->fontFamily==$family && $this->fontStyle==$style && $this->fontSizePt==$size) {
586 1
            return;
587
        }
588
        //Test if used for the first time
589 1
        $fontkey = $family.$style;
590 1
        if (!isset($this->fonts[$fontkey])) {
591
            //Check if one of the standard fonts
592 1
            if (isset($this->coreFonts[$fontkey])) {
593 1
                if (!isset($fpdf_charwidths[$fontkey])) {
594
                    //Load metric file
595 1
                    $file=$family;
596 1
                    if ($family=='times' || $family=='helvetica') {
597 1
                        $file .= strtolower($style);
598
                    }
599 1
                    include $this->getFontPath().$file.'.php';
600 1
                    if (!isset($fpdf_charwidths[$fontkey])) {
601
                        $this->error('Could not include font metric file');
602
                    }
603
                }
604 1
                $i = count($this->fonts)+1;
605 1
                $name = $this->coreFonts[$fontkey];
606 1
                $cw = $fpdf_charwidths[$fontkey];
607 1
                $this->fonts[$fontkey] = ['i'=>$i, 'type'=>'core', 'name'=>$name, 'up'=>-100, 'ut'=>50, 'cw'=>$cw];
608
            } else {
609
                $this->error('Undefined font: '.$family.' '.$style);
610
            }
611
        }
612
        //Select it
613 1
        $this->fontFamily = $family;
614 1
        $this->fontStyle = $style;
615 1
        $this->fontSizePt = $size;
616 1
        $this->fontSize = $size/$this->k;
617 1
        $this->currentFont =& $this->fonts[$fontkey];
618 1
        if ($this->page > 0) {
619 1
            $this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt));
620
        }
621 1
    }
622
623
    public function setFontSize($size)
624
    {
625
        //Set font size in points
626
        if ($this->fontSizePt == $size) {
627
            return;
628
        }
629
        $this->fontSizePt = $size;
630
        $this->fontSize = $size/$this->k;
631
        if ($this->page > 0) {
632
            $this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt));
633
        }
634
    }
635
636
    public function addlink()
637
    {
638
        //Create a new internal link
639
        $n = count($this->links)+1;
640
        $this->links[$n] = array(0, 0);
641
        return $n;
642
    }
643
644
    public function setlink($link, $y = 0, $page = -1)
645
    {
646
        //Set destination of internal link
647
        if ($y == -1) {
648
            $y = $this->y;
649
        }
650
        if ($page == -1) {
651
            $page = $this->page;
652
        }
653
        $this->links[$link] = array($page, $y);
654
    }
655
656
    public function link($x, $y, $w, $h, $link)
657
    {
658
        //Put a link on the page
659
        $this->PageLinks[$this->page][] = [
660
            $x*$this->k,
661
            $this->hPt-$y*$this->k,
662
            $w*$this->k,
663
            $h*$this->k,
664
            $link
665
        ];
666
    }
667
668 1
    public function text($x, $y, $txt)
669
    {
670
        //Output a string
671 1
        $s = sprintf('BT %.2F %.2F Td (%s) Tj ET', $x*$this->k, ($this->h-$y)*$this->k, $this->escape($txt));
672 1
        if ($this->underline && $txt!='') {
673
            $s .= ' '.$this->doUnderLine($x, $y, $txt);
674
        }
675 1
        if ($this->colorFlag) {
676 1
            $s = 'q '.$this->textColor.' '.$s.' Q';
677
        }
678 1
        $this->out($s);
679 1
    }
680
681
    public function acceptPageBreak()
682
    {
683
        //Accept automatic page break or not
684
        return $this->autoPageBreak;
685
    }
686
687
    public function cell($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = false, $link = '')
688
    {
689
        //Output a cell
690
        $k = $this->k;
691
        if ($this->y+$h > $this->PageBreakTrigger
0 ignored issues
show
Bug introduced by
The property PageBreakTrigger does not seem to exist. Did you mean pageBreakTrigger?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
692
            && !$this->InHeader
0 ignored issues
show
Bug introduced by
The property InHeader does not seem to exist. Did you mean inHeader?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
693
            && !$this->InFooter
0 ignored issues
show
Bug introduced by
The property InFooter does not seem to exist. Did you mean inFooter?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
694
            && $this->acceptPageBreak()
695
        ) {
696
            //Automatic page break
697
            $x = $this->x;
698
            $ws = $this->ws;
699
            if ($ws > 0) {
700
                $this->ws = 0;
701
                $this->out('0 Tw');
702
            }
703
            $this->addPage($this->curOrientation, $this->curPageFormat);
0 ignored issues
show
Documentation introduced by
$this->curPageFormat is of type array<integer,integer|do...,"1":"integer|double"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
704
            $this->x = $x;
705
            if ($ws > 0) {
706
                $this->ws = $ws;
707
                $this->out(sprintf('%.3F Tw', $ws*$k));
708
            }
709
        }
710
        if ($w == 0) {
711
            $w = $this->w-$this->rMargin-$this->x;
712
        }
713
        $s='';
714
        if ($fill || $border==1) {
715
            if ($fill) {
716
                $op=($border==1) ? 'B' : 'f';
717
            } else {
718
                $op='S';
719
            }
720
            $s=sprintf('%.2F %.2F %.2F %.2F re %s ', $this->x*$k, ($this->h-$this->y)*$k, $w*$k, -$h*$k, $op);
721
        }
722
        if (is_string($border)) {
723
            $x = $this->x;
724
            $y = $this->y;
725
            if (strpos($border, 'L') !== false) {
726
                $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x*$k, ($this->h-$y)*$k, $x*$k, ($this->h-($y+$h))*$k);
727
            }
728
            if (strpos($border, 'T') !== false) {
729
                $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x*$k, ($this->h-$y)*$k, ($x+$w)*$k, ($this->h-$y)*$k);
730
            }
731
            if (strpos($border, 'R') !== false) {
732
                $s .= sprintf(
733
                    '%.2F %.2F m %.2F %.2F l S ',
734
                    ($x+$w)*$k,
735
                    ($this->h-$y)*$k,
736
                    ($x+$w)*$k,
737
                    ($this->h-($y+$h))*$k
738
                );
739
            }
740
            if (strpos($border, 'B') !== false) {
741
                $s .= sprintf(
742
                    '%.2F %.2F m %.2F %.2F l S ',
743
                    $x*$k,
744
                    ($this->h-($y+$h))*$k,
745
                    ($x+$w)*$k,
746
                    ($this->h-($y+$h))*$k
747
                );
748
            }
749
        }
750
        if ($txt !== '') {
751
            if ($align == 'R') {
752
                $dx = $w-$this->cMargin-$this->getStringWidth($txt);
753
            } elseif ($align == 'C') {
754
                $dx = ($w-$this->getStringWidth($txt))/2;
755
            } else {
756
                $dx = $this->cMargin;
757
            }
758
            if ($this->colorFlag) {
759
                $s .= 'q '.$this->textColor.' ';
760
            }
761
            $txt2 = str_replace(')', '\\)', str_replace('(', '\\(', str_replace('\\', '\\\\', $txt)));
762
            $s .= sprintf(
763
                'BT %.2F %.2F Td (%s) Tj ET',
764
                ($this->x+$dx)*$k,
765
                ($this->h-($this->y+.5*$h+.3*$this->fontSize))*$k,
766
                $txt2
767
            );
768
            if ($this->underline) {
769
                $s .= ' '.$this->doUnderLine($this->x+$dx, $this->y+.5*$h+.3*$this->fontSize, $txt);
770
            }
771
            if ($this->colorFlag) {
772
                $s.=' Q';
773
            }
774
            if ($link) {
775
                $this->link(
776
                    $this->x+$dx,
777
                    $this->y+.5*$h-.5*$this->fontSize,
778
                    $this->getStringWidth($txt),
779
                    $this->fontSize,
780
                    $link
781
                );
782
            }
783
        }
784
        if ($s) {
785
            $this->out($s);
786
        }
787
        $this->lasth = $h;
788
        if ($ln > 0) {
789
            //Go to next line
790
            $this->y += $h;
791
            if ($ln == 1) {
792
                $this->x = $this->lMargin;
793
            }
794
        } else {
795
            $this->x += $w;
796
        }
797
    }
798
799
    public function multicell($w, $h, $txt, $border = 0, $align = 'J', $fill = false)
800
    {
801
        //Output text with automatic or explicit line breaks
802
        $cw =& $this->currentFont['cw'];
803
        if ($w == 0) {
804
            $w = $this->w-$this->rMargin-$this->x;
805
        }
806
        $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
807
        $s = str_replace("\r", '', $txt);
808
        $nb = strlen($s);
809
        if ($nb>0 && $s[$nb-1] == "\n") {
810
            $nb--;
811
        }
812
        $b = 0;
813
        if ($border) {
814
            if ($border == 1) {
815
                $border = 'LTRB';
816
                $b = 'LRT';
817
                $b2 = 'LR';
818
            } else {
819
                $b2 = '';
820
                if (strpos($border, 'L') !== false) {
821
                    $b2 .= 'L';
822
                }
823
                if (strpos($border, 'R') !== false) {
824
                    $b2 .= 'R';
825
                }
826
                $b=(strpos($border, 'T') !== false) ? $b2.'T' : $b2;
827
            }
828
        }
829
        $sep = -1;
830
        $i = 0;
831
        $j = 0;
832
        $l = 0;
833
        $ns = 0;
834
        $nl = 1;
835
        while ($i<$nb) {
836
            //Get next character
837
            $c = $s[$i];
838
            if ($c == "\n") {
839
                //Explicit line break
840
                if ($this->ws > 0) {
841
                    $this->ws = 0;
842
                    $this->out('0 Tw');
843
                }
844
                $this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
845
                $i++;
846
                $sep = -1;
847
                $j = $i;
848
                $l = 0;
849
                $ns = 0;
850
                $nl++;
851
                if ($border && $nl == 2) {
852
                    $b=$b2;
0 ignored issues
show
Bug introduced by
The variable $b2 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
853
                }
854
                continue;
855
            }
856
            if ($c == ' ') {
857
                $sep = $i;
858
                $ls = $l;
859
                $ns++;
860
            }
861
            $l += $cw[$c];
862
            if ($l > $wmax) {
863
                //Automatic line break
864
                if ($sep == -1) {
865
                    if ($i == $j) {
866
                        $i++;
867
                    }
868
                    if ($this->ws > 0) {
869
                        $this->ws = 0;
870
                        $this->out('0 Tw');
871
                    }
872
                    $this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
873
                } else {
874
                    if ($align=='J') {
875
                        $this->ws = ($ns>1) ? ($wmax-$ls)/1000*$this->fontSize/($ns-1) : 0;
0 ignored issues
show
Bug introduced by
The variable $ls does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
876
                        $this->out(sprintf('%.3F Tw', $this->ws*$this->k));
877
                    }
878
                    $this->cell($w, $h, substr($s, $j, $sep-$j), $b, 2, $align, $fill);
879
                    $i = $sep+1;
880
                }
881
                $sep = -1;
882
                $j = $i;
883
                $l = 0;
884
                $ns = 0;
885
                $nl++;
886
                if ($border && $nl == 2) {
887
                    $b = $b2;
888
                }
889
            } else {
890
                $i++;
891
            }
892
        }
893
        //Last chunk
894
        if ($this->ws > 0) {
895
            $this->ws = 0;
896
            $this->out('0 Tw');
897
        }
898
        if ($border && strpos($border, 'B')!==false) {
899
            $b .= 'B';
900
        }
901
        $this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
902
        $this->x = $this->lMargin;
903
    }
904
905
    public function write($h, $txt, $link = '')
906
    {
907
        //Output text in flowing mode
908
        $cw =& $this->currentFont['cw'];
909
        $w = $this->w-$this->rMargin-$this->x;
910
        $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
911
        $s = str_replace("\r", '', $txt);
912
        $nb = strlen($s);
913
        $sep = -1;
914
        $i = 0;
915
        $j = 0;
916
        $l = 0;
917
        $nl = 1;
918
        while ($i < $nb) {
919
            //Get next character
920
            $c=$s[$i];
921
            if ($c=="\n") {
922
                //Explicit line break
923
                $this->cell($w, $h, substr($s, $j, $i-$j), 0, 2, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
924
                $i++;
925
                $sep = -1;
926
                $j = $i;
927
                $l = 0;
928
                if ($nl == 1) {
929
                    $this->x = $this->lMargin;
930
                    $w = $this->w-$this->rMargin-$this->x;
931
                    $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
932
                }
933
                $nl++;
934
                continue;
935
            }
936
            if ($c == ' ') {
937
                $sep = $i;
938
            }
939
            $l += $cw[$c];
940
            if ($l > $wmax) {
941
                //Automatic line break
942
                if ($sep == -1) {
943
                    if ($this->x > $this->lMargin) {
944
                        //Move to next line
945
                        $this->x = $this->lMargin;
946
                        $this->y += $h;
947
                        $w = $this->w-$this->rMargin-$this->x;
948
                        $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
949
                        $i++;
950
                        $nl++;
951
                        continue;
952
                    }
953
                    if ($i == $j) {
954
                        $i++;
955
                    }
956
                    $this->cell($w, $h, substr($s, $j, $i-$j), 0, 2, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
957
                } else {
958
                    $this->cell($w, $h, substr($s, $j, $sep-$j), 0, 2, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
959
                    $i = $sep+1;
960
                }
961
                $sep = -1;
962
                $j = $i;
963
                $l = 0;
964
                if ($nl == 1) {
965
                    $this->x = $this->lMargin;
966
                    $w = $this->w-$this->rMargin-$this->x;
967
                    $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
968
                }
969
                $nl++;
970
            } else {
971
                $i++;
972
            }
973
        }
974
        //Last chunk
975
        if ($i != $j) {
976
            $this->cell($l/1000*$this->fontSize, $h, substr($s, $j), 0, 0, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
977
        }
978
    }
979
980
    public function ln($h = null)
981
    {
982
        //Line feed; default value is last cell height
983
        $this->x = $this->lMargin;
984
        if ($h === null) {
985
            $this->y += $this->lasth;
986
        } else {
987
            $this->y += $h;
988
        }
989
    }
990
991
    public function image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '')
992
    {
993
        //Put an image on the page
994
        if (!isset($this->images[$file])) {
995
            //First use of this image, get info
996
            if ($type == '') {
997
                $pos = strrpos($file, '.');
998
                if (!$pos) {
999
                    $this->error('Image file has no extension and no type was specified: '.$file);
1000
                }
1001
                $type = substr($file, $pos+1);
1002
            }
1003
            $type = strtolower($type);
1004
            if ($type == 'jpeg') {
1005
                $type = 'jpg';
1006
            }
1007
            $mtd = 'parse'.strtoupper($type);
1008
            if (!method_exists($this, $mtd)) {
1009
                $this->error('Unsupported image type: '.$type);
1010
            }
1011
            $info = $this->$mtd($file);
1012
            $info['i'] = count($this->images)+1;
1013
            $this->images[$file] = $info;
1014
        } else {
1015
            $info = $this->images[$file];
1016
        }
1017
        //Automatic width and height calculation if needed
1018
        if ($w == 0 && $h == 0) {
1019
            //Put image at 72 dpi
1020
            $w = $info['w']/$this->k;
1021
            $h = $info['h']/$this->k;
1022
        } elseif ($w == 0) {
1023
            $w = $h*$info['w']/$info['h'];
1024
        } elseif ($h == 0) {
1025
            $h = $w*$info['h']/$info['w'];
1026
        }
1027
        //Flowing mode
1028
        if ($y === null) {
1029
            if ($this->y+$h > $this->pageBreakTrigger
1030
                && !$this->inHeader
1031
                && !$this->inFooter
1032
                && $this->acceptPageBreak()
1033
            ) {
1034
                //Automatic page break
1035
                $x2 = $this->x;
1036
                $this->addPage($this->curOrientation, $this->curPageFormat);
0 ignored issues
show
Documentation introduced by
$this->curPageFormat is of type array<integer,integer|do...,"1":"integer|double"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1037
                $this->x = $x2;
1038
            }
1039
            $y = $this->y;
1040
            $this->y += $h;
1041
        }
1042
        if ($x === null) {
1043
            $x = $this->x;
1044
        }
1045
        $this->out(
1046
            sprintf(
1047
                'q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q',
1048
                $w*$this->k,
1049
                $h*$this->k,
1050
                $x*$this->k,
1051
                ($this->h-($y+$h))*$this->k,
1052
                $info['i']
1053
            )
1054
        );
1055
        if ($link) {
1056
            $this->link($x, $y, $w, $h, $link);
1057
        }
1058
    }
1059
1060
    public function getX()
1061
    {
1062
        //Get x position
1063
        return $this->x;
1064
    }
1065
1066
    public function setX($x)
1067
    {
1068
        //Set x position
1069
        if ($x >= 0) {
1070
            $this->x = $x;
1071
        } else {
1072
            $this->x = $this->w+$x;
1073
        }
1074
    }
1075
1076
    public function getY()
1077
    {
1078
        //Get y position
1079
        return $this->y;
1080
    }
1081
1082
    public function setY($y)
1083
    {
1084
        //Set y position and reset x
1085
        $this->x = $this->lMargin;
1086
        if ($y >= 0) {
1087
            $this->y = $y;
1088
        } else {
1089
            $this->y = $this->h+$y;
1090
        }
1091
    }
1092
1093
    public function setXY($x, $y)
1094
    {
1095
        //Set x and y positions
1096
        $this->setY($y);
1097
        $this->setX($x);
1098
    }
1099
    
1100
    public function getPdf()
1101
    {
1102
        if ($this->state < 3) {
1103
            $this->close();
1104
        }
1105
        return $this->buffer;
1106
    }
1107
    
1108 1
    public function output($name = '', $dest = '')
1109
    {
1110
        //Output PDF to some destination
1111 1
        if ($this->state < 3) {
1112 1
            $this->close();
1113
        }
1114 1
        $dest = strtoupper($dest);
1115 1
        if ($dest == '') {
1116
            if ($name == '') {
1117
                $name = 'doc.pdf';
1118
                $dest = 'I';
1119
            } else {
1120
                $dest = 'F';
1121
            }
1122
        }
1123
        switch ($dest) {
1124 1
            case 'I':
1125
                //Send to standard output
1126
                if (ob_get_length()) {
1127
                    $this->error('Some data has already been output, can\'t send PDF file');
1128
                }
1129
                if (php_sapi_name() != 'cli') {
1130
                    //We send to a browser
1131
                    header('Content-Type: application/pdf');
1132
                    if (headers_sent()) {
1133
                        $this->error('Some data has already been output, can\'t send PDF file');
1134
                    }
1135
                    header('Content-Length: '.strlen($this->buffer));
1136
                    header('Content-Disposition: inline; filename="'.$name.'"');
1137
                    header('Cache-Control: private, max-age=0, must-revalidate');
1138
                    header('Pragma: public');
1139
                    ini_set('zlib.output_compression', '0');
1140
                }
1141
                echo $this->buffer;
1142
                break;
1143 1
            case 'D':
1144
                //Download file
1145
                if (ob_get_length()) {
1146
                    $this->error('Some data has already been output, can\'t send PDF file');
1147
                }
1148
                header('Content-Type: application/x-download');
1149
                if (headers_sent()) {
1150
                    $this->error('Some data has already been output, can\'t send PDF file');
1151
                }
1152
                header('Content-Length: '.strlen($this->buffer));
1153
                header('Content-Disposition: attachment; filename="'.$name.'"');
1154
                header('Cache-Control: private, max-age=0, must-revalidate');
1155
                header('Pragma: public');
1156
                ini_set('zlib.output_compression', '0');
1157
                echo $this->buffer;
1158
                break;
1159 1
            case 'F':
1160
                //Save to local file
1161 1
                $f=fopen($name, 'wb');
1162 1
                if (!$f) {
1163
                    $this->error('Unable to create output file: '.$name);
1164
                }
1165 1
                fwrite($f, $this->buffer, strlen($this->buffer));
1166 1
                fclose($f);
1167 1
                break;
1168
            case 'S':
1169
                //Return as a string
1170
                return $this->buffer;
1171
            default:
1172
                $this->error('Incorrect output destination: '.$dest);
1173
        }
1174 1
        return '';
1175
    }
1176
1177 1
    protected function dochecks()
1178
    {
1179
        //Check availability of %F
1180 1
        if (sprintf('%.1F', 1.0)!='1.0') {
1181
            $this->error('This version of PHP is not supported');
1182
        }
1183
        //Check mbstring overloading
1184 1
        if (ini_get('mbstring.func_overload') & 2) {
1185
            $this->error('mbstring overloading must be disabled');
1186
        }
1187
        //Disable runtime magic quotes
1188 1
        if (get_magic_quotes_runtime()) {
1189
            @set_magic_quotes_runtime(0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1190
        }
1191 1
    }
1192
1193 1
    protected function getpageformat($format)
1194
    {
1195 1
        $format=strtolower($format);
1196 1
        if (!isset($this->pageFormats[$format])) {
1197
            $this->error('Unknown page format: '.$format);
1198
        }
1199 1
        $a=$this->pageFormats[$format];
1200 1
        return array($a[0]/$this->k, $a[1]/$this->k);
1201
    }
1202
1203 1
    protected function getFontPath()
1204
    {
1205 1
        if (!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font')) {
1206
            define('FPDF_FONTPATH', dirname(__FILE__).'/font/');
1207
        }
1208 1
        return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
1209
    }
1210
1211 1
    protected function beginPage($orientation, $format)
1212
    {
1213 1
        $this->page++;
1214 1
        $this->pages[$this->page] = '';
1215 1
        $this->state = 2;
1216 1
        $this->x = $this->lMargin;
1217 1
        $this->y = $this->tMargin;
1218 1
        $this->fontFamily = '';
1219
        //Check page size
1220 1
        if ($orientation == '') {
1221
            $orientation = $this->defOrientation;
1222
        } else {
1223 1
            $orientation = strtoupper($orientation[0]);
1224
        }
1225 1
        if ($format == '') {
1226
            $format = $this->defPageFormat;
1227
        } else {
1228 1
            if (is_string($format)) {
1229 1
                $format=$this->getpageformat($format);
1230
            }
1231
        }
1232 1
        if ($orientation != $this->curOrientation
1233 1
            || $format[0]!=$this->curPageFormat[0]
1234 1
            || $format[1]!=$this->curPageFormat[1]
1235
        ) {
1236
            //New size
1237
            if ($orientation == 'P') {
1238
                $this->w = $format[0];
1239
                $this->h = $format[1];
1240
            } else {
1241
                $this->w = $format[1];
1242
                $this->h = $format[0];
1243
            }
1244
            $this->wPt = $this->w*$this->k;
1245
            $this->hPt = $this->h*$this->k;
1246
            $this->pageBreakTrigger = $this->h-$this->bMargin;
1247
            $this->curOrientation = $orientation;
1248
            $this->curPageFormat = $format;
1249
        }
1250 1
        if ($orientation != $this->defOrientation
1251 1
            || $format[0] != $this->defPageFormat[0]
1252 1
            || $format[1] != $this->defPageFormat[1]
1253
        ) {
1254
            $this->PageSizes[$this->page] = array($this->wPt, $this->hPt);
0 ignored issues
show
Bug introduced by
The property PageSizes does not seem to exist. Did you mean pageSizes?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1255
        }
1256 1
    }
1257
1258 1
    protected function endPage()
1259
    {
1260 1
        $this->state = 1;
1261 1
    }
1262
1263 1
    protected function escape($s)
1264
    {
1265
        //Escape special characters in strings
1266 1
        $s = str_replace('\\', '\\\\', $s);
1267 1
        $s = str_replace('(', '\\(', $s);
1268 1
        $s = str_replace(')', '\\)', $s);
1269 1
        $s = str_replace("\r", '\\r', $s);
1270 1
        return $s;
1271
    }
1272
1273 1
    protected function textString($s)
1274
    {
1275
        //Format a text string
1276 1
        return '('.$this->escape($s).')';
1277
    }
1278
1279
    protected function utf8Toutf16($s)
1280
    {
1281
        //Convert UTF-8 to UTF-16BE with BOM
1282
        $res = "\xFE\xFF";
1283
        $nb = strlen($s);
1284
        $i = 0;
1285
        while ($i < $nb) {
1286
            $c1 = ord($s[$i++]);
1287
            if ($c1 >= 224) {
1288
                //3-byte character
1289
                $c2 = ord($s[$i++]);
1290
                $c3 = ord($s[$i++]);
1291
                $res .= chr((($c1 & 0x0F)<<4) + (($c2 & 0x3C)>>2));
1292
                $res .= chr((($c2 & 0x03)<<6) + ($c3 & 0x3F));
1293
            } elseif ($c1 >= 192) {
1294
                //2-byte character
1295
                $c2 = ord($s[$i++]);
1296
                $res .= chr(($c1 & 0x1C)>>2);
1297
                $res .= chr((($c1 & 0x03)<<6) + ($c2 & 0x3F));
1298
            } else {
1299
                //Single-byte character
1300
                $res .= "\0".chr($c1);
1301
            }
1302
        }
1303
        return $res;
1304
    }
1305
1306
    protected function doUnderLine($x, $y, $txt)
1307
    {
1308
        //Underline text
1309
        $up = $this->currentFont['up'];
1310
        $ut = $this->currentFont['ut'];
1311
        $w = $this->getStringWidth($txt)+$this->ws*substr_count($txt, ' ');
1312
        return sprintf(
1313
            '%.2F %.2F %.2F %.2F re f',
1314
            $x*$this->k,
1315
            ($this->h-($y-$up/1000*$this->fontSize))*$this->k,
1316
            $w*$this->k,
1317
            -$ut/1000*$this->fontSizePt
1318
        );
1319
    }
1320
1321
    protected function parseJPG($file)
1322
    {
1323
        //Extract info from a JPEG file
1324
        $a = getImageSize($file);
1325
        if (!$a) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $a of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1326
            $this->error('Missing or incorrect image file: '.$file);
1327
        }
1328
        if ($a[2]!=2) {
1329
            $this->error('Not a JPEG file: '.$file);
1330
        }
1331
        if (!isset($a['channels']) || $a['channels'] == 3) {
1332
            $colspace = 'DeviceRGB';
1333
        } elseif ($a['channels'] == 4) {
1334
            $colspace = 'DeviceCMYK';
1335
        } else {
1336
            $colspace='DeviceGray';
1337
        }
1338
        $bpc = isset($a['bits']) ? $a['bits'] : 8;
1339
        //Read whole file
1340
        $f = fopen($file, 'rb');
1341
        $data = '';
1342
        while (!feof($f)) {
1343
            $data .= fread($f, 8192);
1344
        }
1345
        fclose($f);
1346
        return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data);
1347
    }
1348
1349
    protected function parsePNG($file)
1350
    {
1351
        //Extract info from a PNG file
1352
        $f = fopen($file, 'rb');
1353
        if (!$f) {
1354
            $this->error('Can\'t open image file: '.$file);
1355
        }
1356
        //Check signature
1357
        if ($this->readstream($f, 8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
1358
            $this->error('Not a PNG file: '.$file);
1359
        }
1360
        //Read header chunk
1361
        $this->readstream($f, 4);
1362
        if ($this->readstream($f, 4)!='IHDR') {
1363
            $this->error('Incorrect PNG file: '.$file);
1364
        }
1365
        $w = $this->readint($f);
1366
        $h = $this->readint($f);
1367
        $bpc = ord($this->readstream($f, 1));
1368
        if ($bpc>8) {
1369
            $this->error('16-bit depth not supported: '.$file);
1370
        }
1371
        $ct = ord($this->readstream($f, 1));
1372
        if ($ct == 0) {
1373
            $colspace = 'DeviceGray';
1374
        } elseif ($ct == 2) {
1375
            $colspace = 'DeviceRGB';
1376
        } elseif ($ct == 3) {
1377
            $colspace = 'Indexed';
1378
        } else {
1379
            $this->error('Alpha channel not supported: '.$file);
1380
        }
1381
        if (ord($this->readstream($f, 1)) != 0) {
1382
            $this->error('Unknown compression method: '.$file);
1383
        }
1384
        if (ord($this->readstream($f, 1)) != 0) {
1385
            $this->error('Unknown filter method: '.$file);
1386
        }
1387
        if (ord($this->readstream($f, 1)) != 0) {
1388
            $this->error('Interlacing not supported: '.$file);
1389
        }
1390
        $this->readstream($f, 4);
1391
        $parms = '/DecodeParms <</Predictor 15 /Colors '
1392
            . ($ct==2 ? 3 : 1)
1393
            . ' /BitsPerComponent '
1394
            . $bpc
1395
            . ' /Columns '
1396
            . $w
1397
            . '>>';
1398
        //Scan chunks looking for palette, transparency and image data
1399
        $pal = '';
1400
        $trns = '';
1401
        $data = '';
1402
        do {
1403
            $n = $this->readint($f);
1404
            $type = $this->readstream($f, 4);
1405
            if ($type == 'PLTE') {
1406
                //Read palette
1407
                $pal = $this->readstream($f, $n);
1408
                $this->readstream($f, 4);
1409
            } elseif ($type == 'tRNS') {
1410
                //Read transparency info
1411
                $t = $this->readstream($f, $n);
1412
                if ($ct == 0) {
1413
                    $trns = array(ord(substr($t, 1, 1)));
1414
                } elseif ($ct == 2) {
1415
                    $trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1)));
1416
                } else {
1417
                    $pos = strpos($t, chr(0));
1418
                    if ($pos !== false) {
1419
                        $trns = array($pos);
1420
                    }
1421
                }
1422
                $this->readstream($f, 4);
1423
            } elseif ($type == 'IDAT') {
1424
                //Read image data block
1425
                $data .= $this->readstream($f, $n);
1426
                $this->readstream($f, 4);
1427
            } elseif ($type == 'IEND') {
1428
                break;
1429
            } else {
1430
                $this->readstream($f, $n+4);
1431
            }
1432
        } while ($n);
1433
        if ($colspace == 'Indexed' && empty($pal)) {
0 ignored issues
show
Bug introduced by
The variable $colspace does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1434
            $this->error('Missing palette in '.$file);
1435
        }
1436
        fclose($f);
1437
        return [
1438
            'w'=>$w,
1439
            'h'=>$h,
1440
            'cs'=>$colspace,
1441
            'bpc'=>$bpc,
1442
            'f'=>'FlateDecode',
1443
            'parms'=>$parms,
1444
            'pal'=>$pal,
1445
            'trns'=>$trns,
1446
            'data'=>$data
1447
        ];
1448
    }
1449
1450
    protected function readstream($f, $n)
1451
    {
1452
        //Read n bytes from stream
1453
        $res='';
1454
        while ($n > 0 && !feof($f)) {
1455
            $s=fread($f, $n);
1456
            if ($s === false) {
1457
                $this->error('Error while reading stream');
1458
            }
1459
            $n -= strlen($s);
1460
            $res .= $s;
1461
        }
1462
        if ($n > 0) {
1463
            $this->error('Unexpected end of stream');
1464
        }
1465
        return $res;
1466
    }
1467
1468
    protected function readint($f)
1469
    {
1470
        //Read a 4-byte integer from stream
1471
        $a = unpack('Ni', $this->readstream($f, 4));
1472
        return $a['i'];
1473
    }
1474
1475
    protected function parseGIF($file)
1476
    {
1477
        //Extract info from a GIF file (via PNG conversion)
1478
        if (!function_exists('imagepng')) {
1479
            $this->error('GD extension is required for GIF support');
1480
        }
1481
        if (!function_exists('imagecreatefromgif')) {
1482
            $this->error('GD has no GIF read support');
1483
        }
1484
        $im = imagecreatefromgif($file);
1485
        if (!$im) {
1486
            $this->error('Missing or incorrect image file: '.$file);
1487
        }
1488
        imageinterlace($im, 0);
1489
        $tmp = tempnam('.', 'gif');
1490
        if (!$tmp) {
1491
            $this->error('Unable to create a temporary file');
1492
        }
1493
        if (!imagepng($im, $tmp)) {
1494
            $this->error('Error while saving to temporary file');
1495
        }
1496
        imagedestroy($im);
1497
        $info=$this->parsePNG($tmp);
1498
        unlink($tmp);
1499
        return $info;
1500
    }
1501
1502 1
    protected function newObj()
1503
    {
1504
        //Begin a new object
1505 1
        $this->n++;
1506 1
        $this->offsets[$this->n] = strlen($this->buffer);
1507 1
        $this->out($this->n.' 0 obj');
1508 1
    }
1509
1510 1
    protected function putStream($s)
1511
    {
1512 1
        $this->out('stream');
1513 1
        $this->out($s);
1514 1
        $this->out('endstream');
1515 1
    }
1516
1517 1
    protected function out($s)
1518
    {
1519
        //Add a line to the document
1520 1
        if ($this->state == 2) {
1521 1
            $this->pages[$this->page].=$s."\n";
1522
        } else {
1523 1
            $this->buffer .= $s."\n";
1524
        }
1525 1
    }
1526
1527 1
    protected function putPages()
1528
    {
1529 1
        $nb = $this->page;
1530 1
        if (!empty($this->aliasNbPages)) {
1531
            //Replace number of pages
1532 1
            for ($n=1; $n<=$nb; $n++) {
1533 1
                $this->pages[$n] = str_replace($this->aliasNbPages, $nb, $this->pages[$n]);
1534
            }
1535
        }
1536 1
        if ($this->defOrientation == 'P') {
1537 1
            $wPt = $this->defPageFormat[0]*$this->k;
1538 1
            $hPt = $this->defPageFormat[1]*$this->k;
1539
        } else {
1540
            $wPt = $this->defPageFormat[1]*$this->k;
1541
            $hPt = $this->defPageFormat[0]*$this->k;
1542
        }
1543 1
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1544 1
        for ($n=1; $n<=$nb; $n++) {
1545
            //Page
1546 1
            $this->newObj();
1547 1
            $this->out('<</Type /Page');
1548 1
            $this->out('/Parent 1 0 R');
1549 1
            if (isset($this->PageSizes[$n])) {
0 ignored issues
show
Bug introduced by
The property PageSizes does not seem to exist. Did you mean pageSizes?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1550
                $this->out(sprintf('/MediaBox [0 0 %.2F %.2F]', $this->PageSizes[$n][0], $this->PageSizes[$n][1]));
0 ignored issues
show
Bug introduced by
The property PageSizes does not seem to exist. Did you mean pageSizes?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1551
            }
1552 1
            $this->out('/Resources 2 0 R');
1553 1
            if (isset($this->PageLinks[$n])) {
1554
                //Links
1555
                $annots = '/Annots [';
1556
                foreach ($this->PageLinks[$n] as $pl) {
1557
                    $rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0]+$pl[2], $pl[1]-$pl[3]);
1558
                    $annots .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
1559
                    if (is_string($pl[4])) {
1560
                        $annots .= '/A <</S /URI /URI '.$this->textString($pl[4]).'>>>>';
1561
                    } else {
1562
                        $l = $this->links[$pl[4]];
1563
                        $h = isset($this->PageSizes[$l[0]]) ? $this->PageSizes[$l[0]][1] : $hPt;
0 ignored issues
show
Bug introduced by
The property PageSizes does not seem to exist. Did you mean pageSizes?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1564
                        $annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>', 1+2*$l[0], $h-$l[1]*$this->k);
1565
                    }
1566
                }
1567
                $this->out($annots.']');
1568
            }
1569 1
            $this->out('/Contents '.($this->n+1).' 0 R>>');
1570 1
            $this->out('endobj');
1571
            //Page content
1572 1
            $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
1573 1
            $this->newObj();
1574 1
            $this->out('<<'.$filter.'/Length '.strlen($p).'>>');
1575 1
            $this->putStream($p);
1576 1
            $this->out('endobj');
1577
        }
1578
        //Pages root
1579 1
        $this->offsets[1]=strlen($this->buffer);
1580 1
        $this->out('1 0 obj');
1581 1
        $this->out('<</Type /Pages');
1582 1
        $kids = '/Kids [';
1583 1
        for ($i=0; $i<$nb; $i++) {
1584 1
            $kids .= (3+2*$i).' 0 R ';
1585
        }
1586 1
        $this->out($kids.']');
1587 1
        $this->out('/Count '.$nb);
1588 1
        $this->out(sprintf('/MediaBox [0 0 %.2F %.2F]', $wPt, $hPt));
1589 1
        $this->out('>>');
1590 1
        $this->out('endobj');
1591 1
    }
1592
1593 1
    protected function putFonts()
1594
    {
1595 1
        $nf = $this->n;
1596 1
        foreach ($this->diffs as $diff) {
1597
            //Encodings
1598
            $this->newObj();
1599
            $this->out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
1600
            $this->out('endobj');
1601
        }
1602 1
        foreach ($this->fontFiles as $file => $info) {
1603
            //Font file embedding
1604
            $this->newObj();
1605
            $this->fontFiles[$file]['n']=$this->n;
1606
            $font='';
1607
            $f = fopen($this->getFontPath().$file, 'rb', 1);
1608
            if (!$f) {
1609
                $this->error('Font file not found');
1610
            }
1611
            while (!feof($f)) {
1612
                $font.=fread($f, 8192);
1613
            }
1614
            fclose($f);
1615
            $compressed = (substr($file, -2)=='.z');
1616
            if (!$compressed && isset($info['length2'])) {
1617
                $header = (ord($font[0])==128);
1618
                if ($header) {
1619
                    //Strip first binary header
1620
                    $font = substr($font, 6);
1621
                }
1622
                if ($header && ord($font[$info['length1']]) == 128) {
1623
                    //Strip second binary header
1624
                    $font = substr($font, 0, $info['length1']).substr($font, $info['length1']+6);
1625
                }
1626
            }
1627
            $this->out('<</Length '.strlen($font));
1628
            if ($compressed) {
1629
                $this->out('/Filter /FlateDecode');
1630
            }
1631
            $this->out('/Length1 '.$info['length1']);
1632
            if (isset($info['length2'])) {
1633
                $this->out('/Length2 '.$info['length2'].' /Length3 0');
1634
            }
1635
            $this->out('>>');
1636
            $this->putStream($font);
1637
            $this->out('endobj');
1638
        }
1639 1
        foreach ($this->fonts as $k => $font) {
1640
            //Font objects
1641 1
            $this->fonts[$k]['n']=$this->n+1;
1642 1
            $type = $font['type'];
1643 1
            $name = $font['name'];
1644 1
            if ($type == 'core') {
1645
                //Standard font
1646 1
                $this->newObj();
1647 1
                $this->out('<</Type /Font');
1648 1
                $this->out('/BaseFont /'.$name);
1649 1
                $this->out('/Subtype /Type1');
1650 1
                if ($name != 'Symbol' && $name != 'ZapfDingbats') {
1651 1
                    $this->out('/Encoding /WinAnsiEncoding');
1652
                }
1653 1
                $this->out('>>');
1654 1
                $this->out('endobj');
1655
            } elseif ($type=='Type1' || $type=='TrueType') {
1656
                //Additional Type1 or TrueType font
1657
                $this->newObj();
1658
                $this->out('<</Type /Font');
1659
                $this->out('/BaseFont /'.$name);
1660
                $this->out('/Subtype /'.$type);
1661
                $this->out('/FirstChar 32 /LastChar 255');
1662
                $this->out('/Widths '.($this->n+1).' 0 R');
1663
                $this->out('/FontDescriptor '.($this->n+2).' 0 R');
1664
                if ($font['enc']) {
1665
                    if (isset($font['diff'])) {
1666
                        $this->out('/Encoding '.($nf+$font['diff']).' 0 R');
1667
                    } else {
1668
                        $this->out('/Encoding /WinAnsiEncoding');
1669
                    }
1670
                }
1671
                $this->out('>>');
1672
                $this->out('endobj');
1673
                //Widths
1674
                $this->newObj();
1675
                $cw =& $font['cw'];
1676
                $s = '[';
1677
                for ($i=32; $i<=255; $i++) {
1678
                    $s .= $cw[chr($i)].' ';
1679
                }
1680
                $this->out($s.']');
1681
                $this->out('endobj');
1682
                //Descriptor
1683
                $this->newObj();
1684
                $s='<</Type /FontDescriptor /FontName /'.$name;
1685
                foreach ($font['desc'] as $k => $v) {
1686
                    $s .= ' /'.$k.' '.$v;
1687
                }
1688
                $file=$font['file'];
1689
                if ($file) {
1690
                    $s .= ' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->fontFiles[$file]['n'].' 0 R';
1691
                }
1692
                $this->out($s.'>>');
1693
                $this->out('endobj');
1694
            } else {
1695
                //Allow for additional types
1696
                $mtd='_put'.strtolower($type);
1697
                if (!method_exists($this, $mtd)) {
1698
                    $this->error('Unsupported font type: '.$type);
1699
                }
1700 1
                $this->$mtd($font);
1701
            }
1702
        }
1703 1
    }
1704
1705 1
    protected function putImages()
1706
    {
1707 1
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1708 1
        reset($this->images);
1709 1
        while (list($file,$info) = each($this->images)) {
1710
            $this->newObj();
1711
            $this->images[$file]['n'] = $this->n;
1712
            $this->out('<</Type /XObject');
1713
            $this->out('/Subtype /Image');
1714
            $this->out('/Width '.$info['w']);
1715
            $this->out('/Height '.$info['h']);
1716
            if ($info['cs']=='Indexed') {
1717
                $this->out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
1718
            } else {
1719
                $this->out('/ColorSpace /'.$info['cs']);
1720
                if ($info['cs']=='DeviceCMYK') {
1721
                    $this->out('/Decode [1 0 1 0 1 0 1 0]');
1722
                }
1723
            }
1724
            $this->out('/BitsPerComponent '.$info['bpc']);
1725
            if (isset($info['f'])) {
1726
                $this->out('/Filter /'.$info['f']);
1727
            }
1728
            if (isset($info['parms'])) {
1729
                $this->out($info['parms']);
1730
            }
1731
            if (isset($info['trns']) && is_array($info['trns'])) {
1732
                $trns = '';
1733
                for ($i=0; $i<count($info['trns']); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1734
                    $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
1735
                }
1736
                $this->out('/Mask ['.$trns.']');
1737
            }
1738
            $this->out('/Length '.strlen($info['data']).'>>');
1739
            $this->putStream($info['data']);
1740
            unset($this->images[$file]['data']);
1741
            $this->out('endobj');
1742
            //Palette
1743
            if ($info['cs'] == 'Indexed') {
1744
                $this->newObj();
1745
                $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
1746
                $this->out('<<'.$filter.'/Length '.strlen($pal).'>>');
1747
                $this->putStream($pal);
1748
                $this->out('endobj');
1749
            }
1750
        }
1751 1
    }
1752
1753 1
    protected function putXobjectDict()
1754
    {
1755 1
        foreach ($this->images as $image) {
1756
            $this->out('/I'.$image['i'].' '.$image['n'].' 0 R');
1757
        }
1758 1
    }
1759
1760 1
    protected function putResourceDict()
1761
    {
1762 1
        $this->out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
1763 1
        $this->out('/Font <<');
1764 1
        foreach ($this->fonts as $font) {
1765 1
            $this->out('/F'.$font['i'].' '.$font['n'].' 0 R');
1766
        }
1767 1
        $this->out('>>');
1768 1
        $this->out('/XObject <<');
1769 1
        $this->putXobjectDict();
1770 1
        $this->out('>>');
1771 1
    }
1772
1773 1
    protected function putResources()
1774
    {
1775 1
        $this->putFonts();
1776 1
        $this->putImages();
1777
        //Resource dictionary
1778 1
        $this->offsets[2] = strlen($this->buffer);
1779 1
        $this->out('2 0 obj');
1780 1
        $this->out('<<');
1781 1
        $this->putResourceDict();
1782 1
        $this->out('>>');
1783 1
        $this->out('endobj');
1784 1
    }
1785
1786 1
    protected function putInfo()
1787
    {
1788 1
        $this->out('/Producer '.$this->textString('FPDF '. self::FPDF_VERSION));
1789 1
        if (!empty($this->title)) {
1790
            $this->out('/Title '.$this->textString($this->title));
1791
        }
1792 1
        if (!empty($this->subject)) {
1793
            $this->out('/Subject '.$this->textString($this->subject));
1794
        }
1795 1
        if (!empty($this->author)) {
1796
            $this->out('/Author '.$this->textString($this->author));
1797
        }
1798 1
        if (!empty($this->keywords)) {
1799
            $this->out('/Keywords '.$this->textString($this->keywords));
1800
        }
1801 1
        if (!empty($this->creator)) {
1802
            $this->out('/Creator '.$this->textString($this->creator));
1803
        }
1804 1
        $this->out('/CreationDate '.$this->textString('D:'.@date('YmdHis')));
1805 1
    }
1806
1807 1
    protected function putCatalog()
1808
    {
1809 1
        $this->out('/Type /Catalog');
1810 1
        $this->out('/Pages 1 0 R');
1811 1
        if ($this->zoomMode=='fullpage') {
1812
            $this->out('/OpenAction [3 0 R /Fit]');
1813 1
        } elseif ($this->zoomMode=='fullwidth') {
1814 1
            $this->out('/OpenAction [3 0 R /FitH null]');
1815
        } elseif ($this->zoomMode=='real') {
1816
            $this->out('/OpenAction [3 0 R /XYZ null null 1]');
1817
        } elseif (!is_string($this->zoomMode)) {
1818
            $this->out('/OpenAction [3 0 R /XYZ null null '.($this->zoomMode/100).']');
1819
        }
1820 1
        if ($this->layoutMode=='single') {
1821
            $this->out('/PageLayout /SinglePage');
1822 1
        } elseif ($this->layoutMode=='continuous') {
1823 1
            $this->out('/PageLayout /OneColumn');
1824
        } elseif ($this->layoutMode=='two') {
1825
            $this->out('/PageLayout /TwoColumnLeft');
1826
        }
1827 1
    }
1828
1829 1
    protected function putHeader()
1830
    {
1831 1
        $this->out('%PDF-'.$this->pdfVersion);
1832 1
    }
1833
1834 1
    protected function putTrailer()
1835
    {
1836 1
        $this->out('/Size '.($this->n+1));
1837 1
        $this->out('/Root '.$this->n.' 0 R');
1838 1
        $this->out('/Info '.($this->n-1).' 0 R');
1839 1
    }
1840
1841 1
    protected function endDoc()
1842
    {
1843 1
        $this->putHeader();
1844 1
        $this->putPages();
1845 1
        $this->putResources();
1846
        //Info
1847 1
        $this->newObj();
1848 1
        $this->out('<<');
1849 1
        $this->putInfo();
1850 1
        $this->out('>>');
1851 1
        $this->out('endobj');
1852
        //Catalog
1853 1
        $this->newObj();
1854 1
        $this->out('<<');
1855 1
        $this->putCatalog();
1856 1
        $this->out('>>');
1857 1
        $this->out('endobj');
1858
        //Cross-ref
1859 1
        $o=strlen($this->buffer);
1860 1
        $this->out('xref');
1861 1
        $this->out('0 '.($this->n+1));
1862 1
        $this->out('0000000000 65535 f ');
1863 1
        for ($i=1; $i<=$this->n; $i++) {
1864 1
            $this->out(sprintf('%010d 00000 n ', $this->offsets[$i]));
1865
        }
1866
        //Trailer
1867 1
        $this->out('trailer');
1868 1
        $this->out('<<');
1869 1
        $this->putTrailer();
1870 1
        $this->out('>>');
1871 1
        $this->out('startxref');
1872 1
        $this->out($o);
1873 1
        $this->out('%%EOF');
1874 1
        $this->state=3;
1875 1
    }
1876
}
1877