Passed
Push — master ( f47aed...e4694f )
by Roberto
05:27
created

Fpdf::putImages()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.5

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 8
ccs 3
cts 6
cp 0.5
crap 2.5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace NFePHP\DA\Legacy\FPDF;
4
5
/**
6
 * Classe origial adaptada para PHP 7.2
7
 * @author Americo Belmiro de Souza Neto
8
 * @email [email protected]
9
 */
10
11
class Fpdf
12
{
13
    const FPDF_VERSION = '1.6';
14
    
15
    public $page;               //current page number
16
    public $n;                  //current object number
17
    public $offsets;            //array of object offsets
18
    public $buffer;             //buffer holding in-memory PDF
19
    public $pages;              //array containing pages
20
    public $state;              //current document state
21
    public $compress;           //compression flag
22
    public $k;                  //scale factor (number of points in user unit)
23
    public $defOrientation;     //default orientation
24
    public $curOrientation;     //current orientation
25
    public $pageFormats;        //available page formats
26
    public $defPageFormat;      //default page format
27
    public $curPageFormat;      //current page format
28
    public $pageSizes;          //array storing non-default page sizes
29
    public $wPt;
30
    public $hPt;           //dimensions of current page in points
31
    public $w;
32
    public $h;               //dimensions of current page in user unit
33
    public $lMargin;            //left margin
34
    public $tMargin;            //top margin
35
    public $rMargin;            //right margin
36
    public $bMargin;            //page break margin
37
    public $cMargin;            //cell margin
38
    public $x;
39
    public $y;               //current position in user unit
40
    public $lasth;              //height of last printed cell
41
    public $lineWidth;          //line width in user unit
42
    public $coreFonts;          //array of standard font names
43
    public $fonts;              //array of used fonts
44
    public $fontFiles;          //array of font files
45
    public $diffs;              //array of encoding differences
46
    public $fontFamily;         //current font family
47
    public $fontStyle;          //current font style
48
    public $underline;          //underlining flag
49
    public $currentFont;        //current font info
50
    public $fontSizePt;         //current font size in points
51
    public $fontSize;           //current font size in user unit
52
    public $drawColor;          //commands for drawing color
53
    public $fillColor;          //commands for filling color
54
    public $textColor;          //commands for text color
55
    public $colorFlag;          //indicates whether fill and text colors are different
56
    public $ws;                 //word spacing
57
    public $images;             //array of used images
58
    public $PageLinks;          //array of links in pages
59
    public $links;              //array of internal links
60
    public $autoPageBreak;      //automatic page breaking
61
    public $pageBreakTrigger;   //threshold used to trigger page breaks
62
    public $inHeader;           //flag set when processing header
63
    public $inFooter;           //flag set when processing footer
64
    public $zoomMode;           //zoom display mode
65
    public $layoutMode;         //layout display mode
66
    public $title;              //title
67
    public $subject;            //subject
68
    public $author;             //author
69
    public $keywords;           //keywords
70
    public $creator;            //creator
71
    public $aliasNbPages;       //alias for total number of pages
72
    public $pdfVersion;         //PDF version number
73
    
74 1
    public function __construct($orientation = 'P', $unit = 'mm', $format = 'A4')
75
    {
76
        //Some checks
77 1
        $this->dochecks();
78
        //Initialization of properties
79 1
        $this->page = 0;
80 1
        $this->n = 2;
81 1
        $this->buffer = '';
82 1
        $this->pages = array();
83 1
        $this->pageSizes = array();
84 1
        $this->state = 0;
85 1
        $this->fonts = array();
86 1
        $this->fontFiles = array();
87 1
        $this->diffs = array();
88 1
        $this->images = array();
89 1
        $this->links = array();
90 1
        $this->inHeader = false;
91 1
        $this->inFooter = false;
92 1
        $this->lasth = 0;
93 1
        $this->fontFamily = '';
94 1
        $this->fontStyle = '';
95 1
        $this->fontSizePt = 12;
96 1
        $this->underline = false;
97 1
        $this->drawColor = '0 G';
98 1
        $this->fillColor = '0 g';
99 1
        $this->textColor = '0 g';
100 1
        $this->colorFlag = false;
101 1
        $this->ws = 0;
102
        //Standard fonts
103 1
        $this->coreFonts = [
104
            'courier'=>'Courier',
105
            'courierB'=>'Courier-Bold',
106
            'courierI'=>'Courier-Oblique',
107
            'courierBI'=>'Courier-BoldOblique',
108
            'helvetica'=>'Helvetica',
109
            'helveticaB'=>'Helvetica-Bold',
110
            'helveticaI'=>'Helvetica-Oblique',
111
            'helveticaBI'=>'Helvetica-BoldOblique',
112
            'times'=>'Times-Roman',
113
            'timesB'=>'Times-Bold',
114
            'timesI'=>'Times-Italic',
115
            'timesBI'=>'Times-BoldItalic',
116
            'symbol'=>'Symbol',
117
            'zapfdingbats'=>'ZapfDingbats'
118
        ];
119
        //Scale factor
120 1
        if ($unit == 'pt') {
121
            $this->k = 1;
122 1
        } elseif ($unit == 'mm') {
123 1
            $this->k = 72/25.4;
124
        } elseif ($unit == 'cm') {
125
            $this->k = 72/2.54;
126
        } elseif ($unit == 'in') {
127
            $this->k = 72;
128
        } else {
129
            $this->error('Incorrect unit: '.$unit);
130
        }
131
        //Page format
132 1
        $this->pageFormats = array(
133
            'a3' => array(841.89,1190.55),
134
            'a4' => array(595.28,841.89),
135
            'a5' => array(420.94,595.28),
136
            'letter' => array(612,792),
137
            'legal' => array(612,1008)
138
        );
139 1
        if (is_string($format)) {
140 1
            $format = $this->getpageformat($format);
141
        }
142 1
        $this->defPageFormat = $format;
143 1
        $this->curPageFormat = $format;
144
        //Page orientation
145 1
        $orientation = strtolower($orientation);
146 1
        if ($orientation == 'p' || $orientation == 'portrait') {
147 1
            $this->defOrientation='P';
148 1
            $this->w = $this->defPageFormat[0];
149 1
            $this->h = $this->defPageFormat[1];
150
        } elseif ($orientation == 'l' || $orientation == 'landscape') {
151
            $this->defOrientation = 'L';
152
            $this->w = $this->defPageFormat[1];
153
            $this->h = $this->defPageFormat[0];
154
        } else {
155
            $this->error('Incorrect orientation: '.$orientation);
156
        }
157 1
        $this->curOrientation = $this->defOrientation;
158 1
        $this->wPt = $this->w*$this->k;
159 1
        $this->hPt = $this->h*$this->k;
160
        //Page margins (1 cm)
161 1
        $margin = 28.35/$this->k;
162 1
        $this->setMargins($margin, $margin);
163
        //Interior cell margin (1 mm)
164 1
        $this->cMargin = $margin/10;
165
        //Line width (0.2 mm)
166 1
        $this->lineWidth = .567/$this->k;
167
        //Automatic page break
168 1
        $this->setAutoPageBreak(true, 2*$margin);
169
        //Full width display mode
170 1
        $this->setDisplayMode('fullwidth');
171
        //Enable compression
172 1
        $this->setCompression(true);
173
        //Set default PDF version number
174 1
        $this->pdfVersion='1.3';
175 1
    }
176
177 1
    public function setMargins($left, $top, $right = null)
178
    {
179
        //Set left, top and right margins
180 1
        $this->lMargin = $left;
181 1
        $this->tMargin = $top;
182 1
        if ($right === null) {
183 1
            $right = $left;
184
        }
185 1
        $this->rMargin=$right;
186 1
    }
187
188
    public function setLeftMargin($margin)
189
    {
190
        //Set left margin
191
        $this->lMargin = $margin;
192
        if ($this->page>0 && $this->x<$margin) {
193
            $this->x = $margin;
194
        }
195
    }
196
197
    public function setTopMargin($margin)
198
    {
199
        //Set top margin
200
        $this->tMargin = $margin;
201
    }
202
203
    public function setRightMargin($margin)
204
    {
205
        //Set right margin
206
        $this->rMargin = $margin;
207
    }
208
209 1
    public function setAutoPageBreak($auto, $margin = 0)
210
    {
211
        //Set auto page break mode and triggering margin
212 1
        $this->autoPageBreak = $auto;
213 1
        $this->bMargin = $margin;
214 1
        $this->pageBreakTrigger = $this->h-$margin;
215 1
    }
216
217 1
    public function setDisplayMode($zoom, $layout = 'continuous')
218
    {
219
        //Set display mode in viewer
220 1
        if ($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom)) {
221 1
            $this->zoomMode = $zoom;
222
        } else {
223
            $this->error('Incorrect zoom display mode: '.$zoom);
224
        }
225 1
        if ($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default') {
226 1
            $this->layoutMode = $layout;
227
        } else {
228
            $this->error('Incorrect layout display mode: '.$layout);
229
        }
230 1
    }
231
232 1
    public function setCompression($compress)
233
    {
234
        //Set page compression
235 1
        if (function_exists('gzcompress')) {
236 1
            $this->compress = $compress;
237
        } else {
238
            $this->compress = false;
239
        }
240 1
    }
241
242
    public function setTitle($title, $isUTF8 = false)
243
    {
244
        //Title of document
245
        if ($isUTF8) {
246
            $title = $this->utf8Toutf16($title);
247
        }
248
        $this->title = $title;
249
    }
250
251
    public function setSubject($subject, $isUTF8 = false)
252
    {
253
        //Subject of document
254
        if ($isUTF8) {
255
            $subject = $this->utf8Toutf16($subject);
256
        }
257
        $this->subject = $subject;
258
    }
259
260
    public function setAuthor($author, $isUTF8 = false)
261
    {
262
        //Author of document
263
        if ($isUTF8) {
264
            $author = $this->utf8Toutf16($author);
265
        }
266
        $this->author=$author;
267
    }
268
269
    public function setKeywords($keywords, $isUTF8 = false)
270
    {
271
        //Keywords of document
272
        if ($isUTF8) {
273
            $keywords = $this->utf8Toutf16($keywords);
274
        }
275
        $this->keywords = $keywords;
276
    }
277
278
    public function setCreator($creator, $isUTF8 = false)
279
    {
280
        //Creator of document
281
        if ($isUTF8) {
282
            $creator = $this->utf8Toutf16($creator);
283
        }
284
        $this->creator = $creator;
285
    }
286
287 1
    public function aliasNbPages($alias = '{nb}')
288
    {
289
        //Define an alias for total number of pages
290 1
        $this->aliasNbPages=$alias;
291 1
    }
292
293
    public function error($msg)
294
    {
295
        throw new \Exception($msg);
296
    }
297
298 1
    public function open()
299
    {
300
        //Begin document
301 1
        $this->state = 1;
302 1
    }
303
304 1
    public function close()
305
    {
306
        //Terminate document
307 1
        if ($this->state == 3) {
308
            return;
309
        }
310 1
        if ($this->page == 0) {
311
            $this->addPage();
312
        }
313
        //Page footer
314 1
        $this->inFooter = true;
315 1
        $this->footer();
316 1
        $this->inFooter = false;
317
        //Close page
318 1
        $this->endPage();
319
        //Close document
320 1
        $this->endDoc();
321 1
    }
322
323 1
    public function addPage($orientation = '', $format = '')
324
    {
325
        //Start a new page
326 1
        if ($this->state==0) {
327
            $this->open();
328
        }
329 1
        $family = $this->fontFamily;
330 1
        $style = $this->fontStyle.($this->underline ? 'U' : '');
331 1
        $size = $this->fontSizePt;
332 1
        $lw = $this->lineWidth;
333 1
        $dc = $this->drawColor;
334 1
        $fc = $this->fillColor;
335 1
        $tc = $this->textColor;
336 1
        $cf = $this->colorFlag;
337 1
        if ($this->page > 0) {
338
            //Page footer
339
            $this->inFooter = true;
340
            $this->footer();
341
            $this->inFooter = false;
342
            //Close page
343
            $this->endPage();
344
        }
345
        //Start new page
346 1
        $this->beginPage($orientation, $format);
347
        //Set line cap style to square
348 1
        $this->out('2 J');
349
        //Set line width
350 1
        $this->lineWidth = $lw;
351 1
        $this->out(sprintf('%.2F w', $lw*$this->k));
352
        //Set font
353 1
        if ($family) {
354
            $this->setFont($family, $style, $size);
355
        }
356
        //Set colors
357 1
        $this->drawColor = $dc;
358 1
        if ($dc!='0 G') {
359 1
            $this->out($dc);
360
        }
361 1
        $this->fillColor = $fc;
362 1
        if ($fc != '0 g') {
363 1
            $this->out($fc);
364
        }
365 1
        $this->textColor = $tc;
366 1
        $this->colorFlag = $cf;
367
        //Page header
368 1
        $this->inHeader = true;
369 1
        $this->Header();
370 1
        $this->inHeader = false;
371
        //Restore line width
372 1
        if ($this->lineWidth != $lw) {
373
            $this->lineWidth = $lw;
374
            $this->out(sprintf('%.2F w', $lw*$this->k));
375
        }
376
        //Restore font
377 1
        if ($family) {
378
            $this->setFont($family, $style, $size);
379
        }
380
        //Restore colors
381 1
        if ($this->drawColor != $dc) {
382
            $this->drawColor = $dc;
383
            $this->out($dc);
384
        }
385 1
        if ($this->fillColor != $fc) {
386
            $this->fillColor = $fc;
387
            $this->out($fc);
388
        }
389 1
        $this->textColor = $tc;
390 1
        $this->colorFlag = $cf;
391 1
    }
392
393 1
    public function header()
394
    {
395
        //To be implemented in your own inherited class
396 1
    }
397
398 1
    public function footer()
399
    {
400
        //To be implemented in your own inherited class
401 1
    }
402
403
    public function pageNo()
404
    {
405
        //Get current page number
406
        return $this->page;
407
    }
408
409 1
    public function setDrawColor($r, $g = null, $b = null)
410
    {
411
        //Set color for all stroking operations
412 1
        if (($r==0 && $g==0 && $b==0) || $g===null) {
413 1
            $this->drawColor = sprintf('%.3F G', $r/255);
414
        } else {
415
            $this->drawColor = sprintf('%.3F %.3F %.3F RG', $r/255, $g/255, $b/255);
416
        }
417 1
        if ($this->page > 0) {
418
            $this->out($this->drawColor);
419
        }
420 1
    }
421
422 1
    public function setFillColor($r, $g = null, $b = null)
423
    {
424
        //Set color for all filling operations
425 1
        if (($r==0 && $g==0 && $b==0) || $g===null) {
426 1
            $this->fillColor = sprintf('%.3F g', $r/255);
427
        } else {
428 1
            $this->fillColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255);
429
        }
430 1
        $this->colorFlag = ($this->fillColor != $this->textColor);
431 1
        if ($this->page > 0) {
432 1
            $this->out($this->fillColor);
433
        }
434 1
    }
435
436 1
    public function settextColor($r, $g = null, $b = null)
437
    {
438
        //Set color for text
439 1
        if (($r==0 && $g==0 && $b==0) || $g===null) {
440 1
            $this->textColor = sprintf('%.3F g', $r/255);
441
        } else {
442 1
            $this->textColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255);
443
        }
444 1
        $this->colorFlag = ($this->fillColor != $this->textColor);
445 1
    }
446
447 1
    public function getStringWidth($s)
448
    {
449
        //Get width of a string in the current font
450 1
        $s = (string)$s;
451 1
        $cw =& $this->currentFont['cw'];
452 1
        $w = 0;
453 1
        $l = strlen($s);
454 1
        for ($i=0; $i<$l; $i++) {
455 1
            $w += $cw[$s[$i]];
456
        }
457 1
        return $w*$this->fontSize/1000;
458
    }
459
460 1
    public function setLineWidth($width)
461
    {
462
        //Set line width
463 1
        $this->lineWidth = $width;
464 1
        if ($this->page > 0) {
465 1
            $this->out(sprintf('%.2F w', $width*$this->k));
466
        }
467 1
    }
468
469
    public function line($x1, $y1, $x2, $y2)
470
    {
471
        //Draw a line
472
        $this->out(
473
            sprintf(
474
                '%.2F %.2F m %.2F %.2F l S',
475
                $x1*$this->k,
476
                ($this->h-$y1)*$this->k,
477
                $x2*$this->k,
478
                ($this->h-$y2)*$this->k
479
            )
480
        );
481
    }
482
483 1
    public function rect($x, $y, $w, $h, $style = '')
484
    {
485
        //Draw a rectangle
486 1
        if ($style == 'F') {
487 1
            $op = 'f';
488
        } elseif ($style == 'FD' || $style == 'DF') {
489
            $op = 'B';
490
        } else {
491
            $op = 'S';
492
        }
493 1
        $this->out(
494
            sprintf(
495 1
                '%.2F %.2F %.2F %.2F re %s',
496 1
                $x*$this->k,
497 1
                ($this->h-$y)*$this->k,
498 1
                $w*$this->k,
499 1
                -$h*$this->k,
500
                $op
501
            )
502
        );
503 1
    }
504
505
    public function addFont($family, $style = '', $file = '')
506
    {
507
        //Add a TrueType or Type1 font
508
        $family = strtolower($family);
509
        if ($file == '') {
510
            $file = str_replace(' ', '', $family).strtolower($style).'.php';
511
        }
512
        if ($family=='arial') {
513
            $family='helvetica';
514
        }
515
        $style = strtoupper($style);
516
        if ($style == 'IB') {
517
            $style = 'BI';
518
        }
519
        $fontkey = $family.$style;
520
        if (isset($this->fonts[$fontkey])) {
521
            return;
522
        }
523
        include $this->getFontPath().$file;
524
        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...
525
            $this->error('Could not include font definition file');
526
        }
527
        $i = count($this->fonts)+1;
528
        $this->fonts[$fontkey] = [
529
            'i'=>$i,
530
            '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...
531
            '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...
532
            '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...
533
            '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...
534
            '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...
535
            '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...
536
            '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...
537
            'file'=>$file
538
        ];
539
        if ($diff) {
540
            //Search existing encodings
541
            $d = 0;
542
            $nb = count($this->diffs);
543
            for ($i=1; $i<=$nb; $i++) {
544
                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...
545
                    $d = $i;
546
                    break;
547
                }
548
            }
549
            if ($d == 0) {
550
                $d = $nb+1;
551
                $this->diffs[$d] = $diff;
552
            }
553
            $this->fonts[$fontkey]['diff'] = $d;
554
        }
555
        if ($file) {
556
            if ($type=='TrueType') {
557
                $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...
558
            } else {
559
                $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...
560
            }
561
        }
562
    }
563
564 1
    public function setFont($family, $style = '', $size = 0)
565
    {
566
        //Select a font; size given in points
567 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...
568 1
        $family = strtolower($family);
569 1
        if ($family == '') {
570
            $family = $this->fontFamily;
571
        }
572 1
        if ($family == 'arial') {
573
            $family = 'helvetica';
574 1
        } elseif ($family == 'symbol' || $family == 'zapfdingbats') {
575
            $style = '';
576
        }
577 1
        $style = strtoupper($style);
578 1
        if (strpos($style, 'U') !== false) {
579
            $this->underline = true;
580
            $style = str_replace('U', '', $style);
581
        } else {
582 1
            $this->underline = false;
583
        }
584 1
        if ($style == 'IB') {
585
            $style = 'BI';
586
        }
587 1
        if ($size == 0) {
588
            $size = $this->fontSizePt;
589
        }
590
        //Test if font is already selected
591 1
        if ($this->fontFamily==$family && $this->fontStyle==$style && $this->fontSizePt==$size) {
592 1
            return;
593
        }
594
        //Test if used for the first time
595 1
        $fontkey = $family.$style;
596 1
        if (!isset($this->fonts[$fontkey])) {
597
            //Check if one of the standard fonts
598 1
            if (isset($this->coreFonts[$fontkey])) {
599 1
                if (!isset($fpdf_charwidths[$fontkey])) {
600
                    //Load metric file
601 1
                    $file=$family;
602 1
                    if ($family=='times' || $family=='helvetica') {
603 1
                        $file .= strtolower($style);
604
                    }
605 1
                    include $this->getFontPath().$file.'.php';
606 1
                    if (!isset($fpdf_charwidths[$fontkey])) {
607
                        $this->error('Could not include font metric file');
608
                    }
609
                }
610 1
                $i = count($this->fonts)+1;
611 1
                $name = $this->coreFonts[$fontkey];
612 1
                $cw = $fpdf_charwidths[$fontkey];
613 1
                $this->fonts[$fontkey] = ['i'=>$i, 'type'=>'core', 'name'=>$name, 'up'=>-100, 'ut'=>50, 'cw'=>$cw];
614
            } else {
615
                $this->error('Undefined font: '.$family.' '.$style);
616
            }
617
        }
618
        //Select it
619 1
        $this->fontFamily = $family;
620 1
        $this->fontStyle = $style;
621 1
        $this->fontSizePt = $size;
622 1
        $this->fontSize = $size/$this->k;
623 1
        $this->currentFont =& $this->fonts[$fontkey];
624 1
        if ($this->page > 0) {
625 1
            $this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt));
626
        }
627 1
    }
628
629
    public function setFontSize($size)
630
    {
631
        //Set font size in points
632
        if ($this->fontSizePt == $size) {
633
            return;
634
        }
635
        $this->fontSizePt = $size;
636
        $this->fontSize = $size/$this->k;
637
        if ($this->page > 0) {
638
            $this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt));
639
        }
640
    }
641
642
    public function addlink()
643
    {
644
        //Create a new internal link
645
        $n = count($this->links)+1;
646
        $this->links[$n] = array(0, 0);
647
        return $n;
648
    }
649
650
    public function setlink($link, $y = 0, $page = -1)
651
    {
652
        //Set destination of internal link
653
        if ($y == -1) {
654
            $y = $this->y;
655
        }
656
        if ($page == -1) {
657
            $page = $this->page;
658
        }
659
        $this->links[$link] = array($page, $y);
660
    }
661
662
    public function link($x, $y, $w, $h, $link)
663
    {
664
        //Put a link on the page
665
        $this->PageLinks[$this->page][] = [
666
            $x*$this->k,
667
            $this->hPt-$y*$this->k,
668
            $w*$this->k,
669
            $h*$this->k,
670
            $link
671
        ];
672
    }
673
674 1
    public function text($x, $y, $txt)
675
    {
676
        //Output a string
677 1
        $s = sprintf('BT %.2F %.2F Td (%s) Tj ET', $x*$this->k, ($this->h-$y)*$this->k, $this->escape($txt));
678 1
        if ($this->underline && $txt!='') {
679
            $s .= ' '.$this->doUnderLine($x, $y, $txt);
680
        }
681 1
        if ($this->colorFlag) {
682 1
            $s = 'q '.$this->textColor.' '.$s.' Q';
683
        }
684 1
        $this->out($s);
685 1
    }
686
687
    public function acceptPageBreak()
688
    {
689
        //Accept automatic page break or not
690
        return $this->autoPageBreak;
691
    }
692
693
    public function cell($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = false, $link = '')
694
    {
695
        //Output a cell
696
        $k = $this->k;
697
        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...
698
            && !$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...
699
            && !$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...
700
            && $this->acceptPageBreak()
701
        ) {
702
            //Automatic page break
703
            $x = $this->x;
704
            $ws = $this->ws;
705
            if ($ws > 0) {
706
                $this->ws = 0;
707
                $this->out('0 Tw');
708
            }
709
            $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...
710
            $this->x = $x;
711
            if ($ws > 0) {
712
                $this->ws = $ws;
713
                $this->out(sprintf('%.3F Tw', $ws*$k));
714
            }
715
        }
716
        if ($w == 0) {
717
            $w = $this->w-$this->rMargin-$this->x;
718
        }
719
        $s='';
720
        if ($fill || $border==1) {
721
            if ($fill) {
722
                $op=($border==1) ? 'B' : 'f';
723
            } else {
724
                $op='S';
725
            }
726
            $s=sprintf('%.2F %.2F %.2F %.2F re %s ', $this->x*$k, ($this->h-$this->y)*$k, $w*$k, -$h*$k, $op);
727
        }
728
        if (is_string($border)) {
729
            $x = $this->x;
730
            $y = $this->y;
731
            if (strpos($border, 'L') !== false) {
732
                $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x*$k, ($this->h-$y)*$k, $x*$k, ($this->h-($y+$h))*$k);
733
            }
734
            if (strpos($border, 'T') !== false) {
735
                $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x*$k, ($this->h-$y)*$k, ($x+$w)*$k, ($this->h-$y)*$k);
736
            }
737
            if (strpos($border, 'R') !== false) {
738
                $s .= sprintf(
739
                    '%.2F %.2F m %.2F %.2F l S ',
740
                    ($x+$w)*$k,
741
                    ($this->h-$y)*$k,
742
                    ($x+$w)*$k,
743
                    ($this->h-($y+$h))*$k
744
                );
745
            }
746
            if (strpos($border, 'B') !== false) {
747
                $s .= sprintf(
748
                    '%.2F %.2F m %.2F %.2F l S ',
749
                    $x*$k,
750
                    ($this->h-($y+$h))*$k,
751
                    ($x+$w)*$k,
752
                    ($this->h-($y+$h))*$k
753
                );
754
            }
755
        }
756
        if ($txt !== '') {
757
            if ($align == 'R') {
758
                $dx = $w-$this->cMargin-$this->getStringWidth($txt);
759
            } elseif ($align == 'C') {
760
                $dx = ($w-$this->getStringWidth($txt))/2;
761
            } else {
762
                $dx = $this->cMargin;
763
            }
764
            if ($this->colorFlag) {
765
                $s .= 'q '.$this->textColor.' ';
766
            }
767
            $txt2 = str_replace(')', '\\)', str_replace('(', '\\(', str_replace('\\', '\\\\', $txt)));
768
            $s .= sprintf(
769
                'BT %.2F %.2F Td (%s) Tj ET',
770
                ($this->x+$dx)*$k,
771
                ($this->h-($this->y+.5*$h+.3*$this->fontSize))*$k,
772
                $txt2
773
            );
774
            if ($this->underline) {
775
                $s .= ' '.$this->doUnderLine($this->x+$dx, $this->y+.5*$h+.3*$this->fontSize, $txt);
776
            }
777
            if ($this->colorFlag) {
778
                $s.=' Q';
779
            }
780
            if ($link) {
781
                $this->link(
782
                    $this->x+$dx,
783
                    $this->y+.5*$h-.5*$this->fontSize,
784
                    $this->getStringWidth($txt),
785
                    $this->fontSize,
786
                    $link
787
                );
788
            }
789
        }
790
        if ($s) {
791
            $this->out($s);
792
        }
793
        $this->lasth = $h;
794
        if ($ln > 0) {
795
            //Go to next line
796
            $this->y += $h;
797
            if ($ln == 1) {
798
                $this->x = $this->lMargin;
799
            }
800
        } else {
801
            $this->x += $w;
802
        }
803
    }
804
805
    public function multicell($w, $h, $txt, $border = 0, $align = 'J', $fill = false)
806
    {
807
        //Output text with automatic or explicit line breaks
808
        $cw =& $this->currentFont['cw'];
809
        if ($w == 0) {
810
            $w = $this->w-$this->rMargin-$this->x;
811
        }
812
        $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
813
        $s = str_replace("\r", '', $txt);
814
        $nb = strlen($s);
815
        if ($nb>0 && $s[$nb-1] == "\n") {
816
            $nb--;
817
        }
818
        $b = 0;
819
        if ($border) {
820
            if ($border == 1) {
821
                $border = 'LTRB';
822
                $b = 'LRT';
823
                $b2 = 'LR';
824
            } else {
825
                $b2 = '';
826
                if (strpos($border, 'L') !== false) {
827
                    $b2 .= 'L';
828
                }
829
                if (strpos($border, 'R') !== false) {
830
                    $b2 .= 'R';
831
                }
832
                $b=(strpos($border, 'T') !== false) ? $b2.'T' : $b2;
833
            }
834
        }
835
        $sep = -1;
836
        $i = 0;
837
        $j = 0;
838
        $l = 0;
839
        $ns = 0;
840
        $nl = 1;
841
        while ($i<$nb) {
842
            //Get next character
843
            $c = $s[$i];
844
            if ($c == "\n") {
845
                //Explicit line break
846
                if ($this->ws > 0) {
847
                    $this->ws = 0;
848
                    $this->out('0 Tw');
849
                }
850
                $this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
851
                $i++;
852
                $sep = -1;
853
                $j = $i;
854
                $l = 0;
855
                $ns = 0;
856
                $nl++;
857
                if ($border && $nl == 2) {
858
                    $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...
859
                }
860
                continue;
861
            }
862
            if ($c == ' ') {
863
                $sep = $i;
864
                $ls = $l;
865
                $ns++;
866
            }
867
            $l += $cw[$c];
868
            if ($l > $wmax) {
869
                //Automatic line break
870
                if ($sep == -1) {
871
                    if ($i == $j) {
872
                        $i++;
873
                    }
874
                    if ($this->ws > 0) {
875
                        $this->ws = 0;
876
                        $this->out('0 Tw');
877
                    }
878
                    $this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
879
                } else {
880
                    if ($align=='J') {
881
                        $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...
882
                        $this->out(sprintf('%.3F Tw', $this->ws*$this->k));
883
                    }
884
                    $this->cell($w, $h, substr($s, $j, $sep-$j), $b, 2, $align, $fill);
885
                    $i = $sep+1;
886
                }
887
                $sep = -1;
888
                $j = $i;
889
                $l = 0;
890
                $ns = 0;
891
                $nl++;
892
                if ($border && $nl == 2) {
893
                    $b = $b2;
894
                }
895
            } else {
896
                $i++;
897
            }
898
        }
899
        //Last chunk
900
        if ($this->ws > 0) {
901
            $this->ws = 0;
902
            $this->out('0 Tw');
903
        }
904
        if ($border && strpos($border, 'B')!==false) {
905
            $b .= 'B';
906
        }
907
        $this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
908
        $this->x = $this->lMargin;
909
    }
910
911
    public function write($h, $txt, $link = '')
912
    {
913
        //Output text in flowing mode
914
        $cw =& $this->currentFont['cw'];
915
        $w = $this->w-$this->rMargin-$this->x;
916
        $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
917
        $s = str_replace("\r", '', $txt);
918
        $nb = strlen($s);
919
        $sep = -1;
920
        $i = 0;
921
        $j = 0;
922
        $l = 0;
923
        $nl = 1;
924
        while ($i < $nb) {
925
            //Get next character
926
            $c=$s[$i];
927
            if ($c=="\n") {
928
                //Explicit line break
929
                $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...
930
                $i++;
931
                $sep = -1;
932
                $j = $i;
933
                $l = 0;
934
                if ($nl == 1) {
935
                    $this->x = $this->lMargin;
936
                    $w = $this->w-$this->rMargin-$this->x;
937
                    $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
938
                }
939
                $nl++;
940
                continue;
941
            }
942
            if ($c == ' ') {
943
                $sep = $i;
944
            }
945
            $l += $cw[$c];
946
            if ($l > $wmax) {
947
                //Automatic line break
948
                if ($sep == -1) {
949
                    if ($this->x > $this->lMargin) {
950
                        //Move to next line
951
                        $this->x = $this->lMargin;
952
                        $this->y += $h;
953
                        $w = $this->w-$this->rMargin-$this->x;
954
                        $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
955
                        $i++;
956
                        $nl++;
957
                        continue;
958
                    }
959
                    if ($i == $j) {
960
                        $i++;
961
                    }
962
                    $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...
963
                } else {
964
                    $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...
965
                    $i = $sep+1;
966
                }
967
                $sep = -1;
968
                $j = $i;
969
                $l = 0;
970
                if ($nl == 1) {
971
                    $this->x = $this->lMargin;
972
                    $w = $this->w-$this->rMargin-$this->x;
973
                    $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
974
                }
975
                $nl++;
976
            } else {
977
                $i++;
978
            }
979
        }
980
        //Last chunk
981
        if ($i != $j) {
982
            $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...
983
        }
984
    }
985
986
    public function ln($h = null)
987
    {
988
        //Line feed; default value is last cell height
989
        $this->x = $this->lMargin;
990
        if ($h === null) {
991
            $this->y += $this->lasth;
992
        } else {
993
            $this->y += $h;
994
        }
995
    }
996
997
    public function image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '')
998
    {
999
        //Put an image on the page
1000
        if (!isset($this->images[$file])) {
1001
            //First use of this image, get info
1002
            if ($type == '') {
1003
                $pos = strrpos($file, '.');
1004
                if (!$pos) {
1005
                    $this->error('Image file has no extension and no type was specified: '.$file);
1006
                }
1007
                $type = substr($file, $pos+1);
1008
            }
1009
            $type = strtolower($type);
1010
            if ($type == 'jpeg') {
1011
                $type = 'jpg';
1012
            }
1013
            $mtd = 'parse'.strtoupper($type);
1014
            if (!method_exists($this, $mtd)) {
1015
                $this->error('Unsupported image type: '.$type);
1016
            }
1017
            $info = $this->$mtd($file);
1018
            $info['i'] = count($this->images)+1;
1019
            $this->images[$file] = $info;
1020
        } else {
1021
            $info = $this->images[$file];
1022
        }
1023
        //Automatic width and height calculation if needed
1024
        if ($w == 0 && $h == 0) {
1025
            //Put image at 72 dpi
1026
            $w = $info['w']/$this->k;
1027
            $h = $info['h']/$this->k;
1028
        } elseif ($w == 0) {
1029
            $w = $h*$info['w']/$info['h'];
1030
        } elseif ($h == 0) {
1031
            $h = $w*$info['h']/$info['w'];
1032
        }
1033
        //Flowing mode
1034
        if ($y === null) {
1035
            if ($this->y+$h > $this->pageBreakTrigger
1036
                && !$this->inHeader
1037
                && !$this->inFooter
1038
                && $this->acceptPageBreak()
1039
            ) {
1040
                //Automatic page break
1041
                $x2 = $this->x;
1042
                $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...
1043
                $this->x = $x2;
1044
            }
1045
            $y = $this->y;
1046
            $this->y += $h;
1047
        }
1048
        if ($x === null) {
1049
            $x = $this->x;
1050
        }
1051
        $this->out(
1052
            sprintf(
1053
                'q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q',
1054
                $w*$this->k,
1055
                $h*$this->k,
1056
                $x*$this->k,
1057
                ($this->h-($y+$h))*$this->k,
1058
                $info['i']
1059
            )
1060
        );
1061
        if ($link) {
1062
            $this->link($x, $y, $w, $h, $link);
1063
        }
1064
    }
1065
1066
    public function getX()
1067
    {
1068
        //Get x position
1069
        return $this->x;
1070
    }
1071
1072
    public function setX($x)
1073
    {
1074
        //Set x position
1075
        if ($x >= 0) {
1076
            $this->x = $x;
1077
        } else {
1078
            $this->x = $this->w+$x;
1079
        }
1080
    }
1081
1082
    public function getY()
1083
    {
1084
        //Get y position
1085
        return $this->y;
1086
    }
1087
1088
    public function setY($y)
1089
    {
1090
        //Set y position and reset x
1091
        $this->x = $this->lMargin;
1092
        if ($y >= 0) {
1093
            $this->y = $y;
1094
        } else {
1095
            $this->y = $this->h+$y;
1096
        }
1097
    }
1098
1099
    public function setXY($x, $y)
1100
    {
1101
        //Set x and y positions
1102
        $this->setY($y);
1103
        $this->setX($x);
1104
    }
1105
    
1106
    public function getPdf()
1107
    {
1108
        if ($this->state < 3) {
1109
            $this->close();
1110
        }
1111
        return $this->buffer;
1112
    }
1113
    
1114 1
    public function output($name = '', $dest = '')
1115
    {
1116
        //Output PDF to some destination
1117 1
        if ($this->state < 3) {
1118 1
            $this->close();
1119
        }
1120 1
        $dest = strtoupper($dest);
1121 1
        if ($dest == '') {
1122
            if ($name == '') {
1123
                $name = 'doc.pdf';
1124
                $dest = 'I';
1125
            } else {
1126
                $dest = 'F';
1127
            }
1128
        }
1129
        switch ($dest) {
1130 1
            case 'I':
1131
                //Send to standard output
1132
                if (ob_get_length()) {
1133
                    $this->error('Some data has already been output, can\'t send PDF file');
1134
                }
1135
                if (php_sapi_name() != 'cli') {
1136
                    //We send to a browser
1137
                    header('Content-Type: application/pdf');
1138
                    if (headers_sent()) {
1139
                        $this->error('Some data has already been output, can\'t send PDF file');
1140
                    }
1141
                    header('Content-Length: '.strlen($this->buffer));
1142
                    header('Content-Disposition: inline; filename="'.$name.'"');
1143
                    header('Cache-Control: private, max-age=0, must-revalidate');
1144
                    header('Pragma: public');
1145
                    ini_set('zlib.output_compression', '0');
1146
                }
1147
                echo $this->buffer;
1148
                break;
1149 1
            case 'D':
1150
                //Download file
1151
                if (ob_get_length()) {
1152
                    $this->error('Some data has already been output, can\'t send PDF file');
1153
                }
1154
                header('Content-Type: application/x-download');
1155
                if (headers_sent()) {
1156
                    $this->error('Some data has already been output, can\'t send PDF file');
1157
                }
1158
                header('Content-Length: '.strlen($this->buffer));
1159
                header('Content-Disposition: attachment; filename="'.$name.'"');
1160
                header('Cache-Control: private, max-age=0, must-revalidate');
1161
                header('Pragma: public');
1162
                ini_set('zlib.output_compression', '0');
1163
                echo $this->buffer;
1164
                break;
1165 1
            case 'F':
1166
                //Save to local file
1167 1
                $f=fopen($name, 'wb');
1168 1
                if (!$f) {
1169
                    $this->error('Unable to create output file: '.$name);
1170
                }
1171 1
                fwrite($f, $this->buffer, strlen($this->buffer));
1172 1
                fclose($f);
1173 1
                break;
1174
            case 'S':
1175
                //Return as a string
1176
                return $this->buffer;
1177
            default:
1178
                $this->error('Incorrect output destination: '.$dest);
1179
        }
1180 1
        return '';
1181
    }
1182
1183 1
    protected function dochecks()
1184
    {
1185
        //Check availability of %F
1186 1
        if (sprintf('%.1F', 1.0)!='1.0') {
1187
            $this->error('This version of PHP is not supported');
1188
        }
1189
        //Check mbstring overloading
1190 1
        if (ini_get('mbstring.func_overload') & 2) {
1191
            $this->error('mbstring overloading must be disabled');
1192
        }
1193
        //Disable runtime magic quotes
1194 1
        if (get_magic_quotes_runtime()) {
1195
            @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...
1196
        }
1197 1
    }
1198
1199 1
    protected function getpageformat($format)
1200
    {
1201 1
        $format=strtolower($format);
1202 1
        if (!isset($this->pageFormats[$format])) {
1203
            $this->error('Unknown page format: '.$format);
1204
        }
1205 1
        $a=$this->pageFormats[$format];
1206 1
        return array($a[0]/$this->k, $a[1]/$this->k);
1207
    }
1208
1209 1
    protected function getFontPath()
1210
    {
1211 1
        if (!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font')) {
1212
            define('FPDF_FONTPATH', dirname(__FILE__).'/font/');
1213
        }
1214 1
        return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
1215
    }
1216
1217 1
    protected function beginPage($orientation, $format)
1218
    {
1219 1
        $this->page++;
1220 1
        $this->pages[$this->page] = '';
1221 1
        $this->state = 2;
1222 1
        $this->x = $this->lMargin;
1223 1
        $this->y = $this->tMargin;
1224 1
        $this->fontFamily = '';
1225
        //Check page size
1226 1
        if ($orientation == '') {
1227
            $orientation = $this->defOrientation;
1228
        } else {
1229 1
            $orientation = strtoupper($orientation[0]);
1230
        }
1231 1
        if ($format == '') {
1232
            $format = $this->defPageFormat;
1233
        } else {
1234 1
            if (is_string($format)) {
1235 1
                $format=$this->getpageformat($format);
1236
            }
1237
        }
1238 1
        if ($orientation != $this->curOrientation
1239 1
            || $format[0]!=$this->curPageFormat[0]
1240 1
            || $format[1]!=$this->curPageFormat[1]
1241
        ) {
1242
            //New size
1243
            if ($orientation == 'P') {
1244
                $this->w = $format[0];
1245
                $this->h = $format[1];
1246
            } else {
1247
                $this->w = $format[1];
1248
                $this->h = $format[0];
1249
            }
1250
            $this->wPt = $this->w*$this->k;
1251
            $this->hPt = $this->h*$this->k;
1252
            $this->pageBreakTrigger = $this->h-$this->bMargin;
1253
            $this->curOrientation = $orientation;
1254
            $this->curPageFormat = $format;
1255
        }
1256 1
        if ($orientation != $this->defOrientation
1257 1
            || $format[0] != $this->defPageFormat[0]
1258 1
            || $format[1] != $this->defPageFormat[1]
1259
        ) {
1260
            $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...
1261
        }
1262 1
    }
1263
1264 1
    protected function endPage()
1265
    {
1266 1
        $this->state = 1;
1267 1
    }
1268
1269 1
    protected function escape($s)
1270
    {
1271
        //Escape special characters in strings
1272 1
        $s = str_replace('\\', '\\\\', $s);
1273 1
        $s = str_replace('(', '\\(', $s);
1274 1
        $s = str_replace(')', '\\)', $s);
1275 1
        $s = str_replace("\r", '\\r', $s);
1276 1
        return $s;
1277
    }
1278
1279 1
    protected function textString($s)
1280
    {
1281
        //Format a text string
1282 1
        return '('.$this->escape($s).')';
1283
    }
1284
1285
    protected function utf8Toutf16($s)
1286
    {
1287
        //Convert UTF-8 to UTF-16BE with BOM
1288
        $res = "\xFE\xFF";
1289
        $nb = strlen($s);
1290
        $i = 0;
1291
        while ($i < $nb) {
1292
            $c1 = ord($s[$i++]);
1293
            if ($c1 >= 224) {
1294
                //3-byte character
1295
                $c2 = ord($s[$i++]);
1296
                $c3 = ord($s[$i++]);
1297
                $res .= chr((($c1 & 0x0F)<<4) + (($c2 & 0x3C)>>2));
1298
                $res .= chr((($c2 & 0x03)<<6) + ($c3 & 0x3F));
1299
            } elseif ($c1 >= 192) {
1300
                //2-byte character
1301
                $c2 = ord($s[$i++]);
1302
                $res .= chr(($c1 & 0x1C)>>2);
1303
                $res .= chr((($c1 & 0x03)<<6) + ($c2 & 0x3F));
1304
            } else {
1305
                //Single-byte character
1306
                $res .= "\0".chr($c1);
1307
            }
1308
        }
1309
        return $res;
1310
    }
1311
1312
    protected function doUnderLine($x, $y, $txt)
1313
    {
1314
        //Underline text
1315
        $up = $this->currentFont['up'];
1316
        $ut = $this->currentFont['ut'];
1317
        $w = $this->getStringWidth($txt)+$this->ws*substr_count($txt, ' ');
1318
        return sprintf(
1319
            '%.2F %.2F %.2F %.2F re f',
1320
            $x*$this->k,
1321
            ($this->h-($y-$up/1000*$this->fontSize))*$this->k,
1322
            $w*$this->k,
1323
            -$ut/1000*$this->fontSizePt
1324
        );
1325
    }
1326
1327
    protected function parseJPG($file)
1328
    {
1329
        //Extract info from a JPEG file
1330
        $a = getImageSize($file);
1331
        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...
1332
            $this->error('Missing or incorrect image file: '.$file);
1333
        }
1334
        if ($a[2]!=2) {
1335
            $this->error('Not a JPEG file: '.$file);
1336
        }
1337
        if (!isset($a['channels']) || $a['channels'] == 3) {
1338
            $colspace = 'DeviceRGB';
1339
        } elseif ($a['channels'] == 4) {
1340
            $colspace = 'DeviceCMYK';
1341
        } else {
1342
            $colspace='DeviceGray';
1343
        }
1344
        $bpc = isset($a['bits']) ? $a['bits'] : 8;
1345
        //Read whole file
1346
        $f = fopen($file, 'rb');
1347
        $data = '';
1348
        while (!feof($f)) {
1349
            $data .= fread($f, 8192);
1350
        }
1351
        fclose($f);
1352
        return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data);
1353
    }
1354
1355
    protected function parsePNG($file)
1356
    {
1357
        //Extract info from a PNG file
1358
        $f = fopen($file, 'rb');
1359
        if (!$f) {
1360
            $this->error('Can\'t open image file: '.$file);
1361
        }
1362
        //Check signature
1363
        if ($this->readstream($f, 8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
1364
            $this->error('Not a PNG file: '.$file);
1365
        }
1366
        //Read header chunk
1367
        $this->readstream($f, 4);
1368
        if ($this->readstream($f, 4)!='IHDR') {
1369
            $this->error('Incorrect PNG file: '.$file);
1370
        }
1371
        $w = $this->readint($f);
1372
        $h = $this->readint($f);
1373
        $bpc = ord($this->readstream($f, 1));
1374
        if ($bpc>8) {
1375
            $this->error('16-bit depth not supported: '.$file);
1376
        }
1377
        $ct = ord($this->readstream($f, 1));
1378
        if ($ct == 0) {
1379
            $colspace = 'DeviceGray';
1380
        } elseif ($ct == 2) {
1381
            $colspace = 'DeviceRGB';
1382
        } elseif ($ct == 3) {
1383
            $colspace = 'Indexed';
1384
        } else {
1385
            $this->error('Alpha channel not supported: '.$file);
1386
        }
1387
        if (ord($this->readstream($f, 1)) != 0) {
1388
            $this->error('Unknown compression method: '.$file);
1389
        }
1390
        if (ord($this->readstream($f, 1)) != 0) {
1391
            $this->error('Unknown filter method: '.$file);
1392
        }
1393
        if (ord($this->readstream($f, 1)) != 0) {
1394
            $this->error('Interlacing not supported: '.$file);
1395
        }
1396
        $this->readstream($f, 4);
1397
        $parms = '/DecodeParms <</Predictor 15 /Colors '
1398
            . ($ct==2 ? 3 : 1)
1399
            . ' /BitsPerComponent '
1400
            . $bpc
1401
            . ' /Columns '
1402
            . $w
1403
            . '>>';
1404
        //Scan chunks looking for palette, transparency and image data
1405
        $pal = '';
1406
        $trns = '';
1407
        $data = '';
1408
        do {
1409
            $n = $this->readint($f);
1410
            $type = $this->readstream($f, 4);
1411
            if ($type == 'PLTE') {
1412
                //Read palette
1413
                $pal = $this->readstream($f, $n);
1414
                $this->readstream($f, 4);
1415
            } elseif ($type == 'tRNS') {
1416
                //Read transparency info
1417
                $t = $this->readstream($f, $n);
1418
                if ($ct == 0) {
1419
                    $trns = array(ord(substr($t, 1, 1)));
1420
                } elseif ($ct == 2) {
1421
                    $trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1)));
1422
                } else {
1423
                    $pos = strpos($t, chr(0));
1424
                    if ($pos !== false) {
1425
                        $trns = array($pos);
1426
                    }
1427
                }
1428
                $this->readstream($f, 4);
1429
            } elseif ($type == 'IDAT') {
1430
                //Read image data block
1431
                $data .= $this->readstream($f, $n);
1432
                $this->readstream($f, 4);
1433
            } elseif ($type == 'IEND') {
1434
                break;
1435
            } else {
1436
                $this->readstream($f, $n+4);
1437
            }
1438
        } while ($n);
1439
        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...
1440
            $this->error('Missing palette in '.$file);
1441
        }
1442
        fclose($f);
1443
        return [
1444
            'w'=>$w,
1445
            'h'=>$h,
1446
            'cs'=>$colspace,
1447
            'bpc'=>$bpc,
1448
            'f'=>'FlateDecode',
1449
            'parms'=>$parms,
1450
            'pal'=>$pal,
1451
            'trns'=>$trns,
1452
            'data'=>$data
1453
        ];
1454
    }
1455
1456
    protected function readstream($f, $n)
1457
    {
1458
        //Read n bytes from stream
1459
        $res='';
1460
        while ($n > 0 && !feof($f)) {
1461
            $s=fread($f, $n);
1462
            if ($s === false) {
1463
                $this->error('Error while reading stream');
1464
            }
1465
            $n -= strlen($s);
1466
            $res .= $s;
1467
        }
1468
        if ($n > 0) {
1469
            $this->error('Unexpected end of stream');
1470
        }
1471
        return $res;
1472
    }
1473
1474
    protected function readint($f)
1475
    {
1476
        //Read a 4-byte integer from stream
1477
        $a = unpack('Ni', $this->readstream($f, 4));
1478
        return $a['i'];
1479
    }
1480
1481
    protected function parseGIF($file)
1482
    {
1483
        //Extract info from a GIF file (via PNG conversion)
1484
        if (!function_exists('imagepng')) {
1485
            $this->error('GD extension is required for GIF support');
1486
        }
1487
        if (!function_exists('imagecreatefromgif')) {
1488
            $this->error('GD has no GIF read support');
1489
        }
1490
        $im = imagecreatefromgif($file);
1491
        if (!$im) {
1492
            $this->error('Missing or incorrect image file: '.$file);
1493
        }
1494
        imageinterlace($im, 0);
1495
        $tmp = tempnam('.', 'gif');
1496
        if (!$tmp) {
1497
            $this->error('Unable to create a temporary file');
1498
        }
1499
        if (!imagepng($im, $tmp)) {
1500
            $this->error('Error while saving to temporary file');
1501
        }
1502
        imagedestroy($im);
1503
        $info=$this->parsePNG($tmp);
1504
        unlink($tmp);
1505
        return $info;
1506
    }
1507
1508 1
    protected function newObj()
1509
    {
1510
        //Begin a new object
1511 1
        $this->n++;
1512 1
        $this->offsets[$this->n] = strlen($this->buffer);
1513 1
        $this->out($this->n.' 0 obj');
1514 1
    }
1515
1516 1
    protected function putStream($s)
1517
    {
1518 1
        $this->out('stream');
1519 1
        $this->out($s);
1520 1
        $this->out('endstream');
1521 1
    }
1522
1523 1
    protected function out($s)
1524
    {
1525
        //Add a line to the document
1526 1
        if ($this->state == 2) {
1527 1
            $this->pages[$this->page].=$s."\n";
1528
        } else {
1529 1
            $this->buffer .= $s."\n";
1530
        }
1531 1
    }
1532
1533 1
    protected function putPages()
1534
    {
1535 1
        $nb = $this->page;
1536 1
        if (!empty($this->aliasNbPages)) {
1537
            //Replace number of pages
1538 1
            for ($n=1; $n<=$nb; $n++) {
1539 1
                $this->pages[$n] = str_replace($this->aliasNbPages, $nb, $this->pages[$n]);
1540
            }
1541
        }
1542 1
        if ($this->defOrientation == 'P') {
1543 1
            $wPt = $this->defPageFormat[0]*$this->k;
1544 1
            $hPt = $this->defPageFormat[1]*$this->k;
1545
        } else {
1546
            $wPt = $this->defPageFormat[1]*$this->k;
1547
            $hPt = $this->defPageFormat[0]*$this->k;
1548
        }
1549 1
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1550 1
        for ($n=1; $n<=$nb; $n++) {
1551
            //Page
1552 1
            $this->newObj();
1553 1
            $this->out('<</Type /Page');
1554 1
            $this->out('/Parent 1 0 R');
1555 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...
1556
                $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...
1557
            }
1558 1
            $this->out('/Resources 2 0 R');
1559 1
            if (isset($this->PageLinks[$n])) {
1560
                //Links
1561
                $annots = '/Annots [';
1562
                foreach ($this->PageLinks[$n] as $pl) {
1563
                    $rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0]+$pl[2], $pl[1]-$pl[3]);
1564
                    $annots .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
1565
                    if (is_string($pl[4])) {
1566
                        $annots .= '/A <</S /URI /URI '.$this->textString($pl[4]).'>>>>';
1567
                    } else {
1568
                        $l = $this->links[$pl[4]];
1569
                        $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...
1570
                        $annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>', 1+2*$l[0], $h-$l[1]*$this->k);
1571
                    }
1572
                }
1573
                $this->out($annots.']');
1574
            }
1575 1
            $this->out('/Contents '.($this->n+1).' 0 R>>');
1576 1
            $this->out('endobj');
1577
            //Page content
1578 1
            $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
1579 1
            $this->newObj();
1580 1
            $this->out('<<'.$filter.'/Length '.strlen($p).'>>');
1581 1
            $this->putStream($p);
1582 1
            $this->out('endobj');
1583
        }
1584
        //Pages root
1585 1
        $this->offsets[1]=strlen($this->buffer);
1586 1
        $this->out('1 0 obj');
1587 1
        $this->out('<</Type /Pages');
1588 1
        $kids = '/Kids [';
1589 1
        for ($i=0; $i<$nb; $i++) {
1590 1
            $kids .= (3+2*$i).' 0 R ';
1591
        }
1592 1
        $this->out($kids.']');
1593 1
        $this->out('/Count '.$nb);
1594 1
        $this->out(sprintf('/MediaBox [0 0 %.2F %.2F]', $wPt, $hPt));
1595 1
        $this->out('>>');
1596 1
        $this->out('endobj');
1597 1
    }
1598
1599 1
    protected function putFonts()
1600
    {
1601 1
        $nf = $this->n;
1602 1
        foreach ($this->diffs as $diff) {
1603
            //Encodings
1604
            $this->newObj();
1605
            $this->out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
1606
            $this->out('endobj');
1607
        }
1608 1
        foreach ($this->fontFiles as $file => $info) {
1609
            //Font file embedding
1610
            $this->newObj();
1611
            $this->fontFiles[$file]['n']=$this->n;
1612
            $font='';
1613
            $f = fopen($this->getFontPath().$file, 'rb', 1);
1614
            if (!$f) {
1615
                $this->error('Font file not found');
1616
            }
1617
            while (!feof($f)) {
1618
                $font.=fread($f, 8192);
1619
            }
1620
            fclose($f);
1621
            $compressed = (substr($file, -2)=='.z');
1622
            if (!$compressed && isset($info['length2'])) {
1623
                $header = (ord($font[0])==128);
1624
                if ($header) {
1625
                    //Strip first binary header
1626
                    $font = substr($font, 6);
1627
                }
1628
                if ($header && ord($font[$info['length1']]) == 128) {
1629
                    //Strip second binary header
1630
                    $font = substr($font, 0, $info['length1']).substr($font, $info['length1']+6);
1631
                }
1632
            }
1633
            $this->out('<</Length '.strlen($font));
1634
            if ($compressed) {
1635
                $this->out('/Filter /FlateDecode');
1636
            }
1637
            $this->out('/Length1 '.$info['length1']);
1638
            if (isset($info['length2'])) {
1639
                $this->out('/Length2 '.$info['length2'].' /Length3 0');
1640
            }
1641
            $this->out('>>');
1642
            $this->putStream($font);
1643
            $this->out('endobj');
1644
        }
1645 1
        foreach ($this->fonts as $k => $font) {
1646
            //Font objects
1647 1
            $this->fonts[$k]['n']=$this->n+1;
1648 1
            $type = $font['type'];
1649 1
            $name = $font['name'];
1650 1
            if ($type == 'core') {
1651
                //Standard font
1652 1
                $this->newObj();
1653 1
                $this->out('<</Type /Font');
1654 1
                $this->out('/BaseFont /'.$name);
1655 1
                $this->out('/Subtype /Type1');
1656 1
                if ($name != 'Symbol' && $name != 'ZapfDingbats') {
1657 1
                    $this->out('/Encoding /WinAnsiEncoding');
1658
                }
1659 1
                $this->out('>>');
1660 1
                $this->out('endobj');
1661
            } elseif ($type=='Type1' || $type=='TrueType') {
1662
                //Additional Type1 or TrueType font
1663
                $this->newObj();
1664
                $this->out('<</Type /Font');
1665
                $this->out('/BaseFont /'.$name);
1666
                $this->out('/Subtype /'.$type);
1667
                $this->out('/FirstChar 32 /LastChar 255');
1668
                $this->out('/Widths '.($this->n+1).' 0 R');
1669
                $this->out('/FontDescriptor '.($this->n+2).' 0 R');
1670
                if ($font['enc']) {
1671
                    if (isset($font['diff'])) {
1672
                        $this->out('/Encoding '.($nf+$font['diff']).' 0 R');
1673
                    } else {
1674
                        $this->out('/Encoding /WinAnsiEncoding');
1675
                    }
1676
                }
1677
                $this->out('>>');
1678
                $this->out('endobj');
1679
                //Widths
1680
                $this->newObj();
1681
                $cw =& $font['cw'];
1682
                $s = '[';
1683
                for ($i=32; $i<=255; $i++) {
1684
                    $s .= $cw[chr($i)].' ';
1685
                }
1686
                $this->out($s.']');
1687
                $this->out('endobj');
1688
                //Descriptor
1689
                $this->newObj();
1690
                $s='<</Type /FontDescriptor /FontName /'.$name;
1691
                foreach ($font['desc'] as $k => $v) {
1692
                    $s .= ' /'.$k.' '.$v;
1693
                }
1694
                $file=$font['file'];
1695
                if ($file) {
1696
                    $s .= ' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->fontFiles[$file]['n'].' 0 R';
1697
                }
1698
                $this->out($s.'>>');
1699
                $this->out('endobj');
1700
            } else {
1701
                //Allow for additional types
1702
                $mtd='_put'.strtolower($type);
1703
                if (!method_exists($this, $mtd)) {
1704
                    $this->error('Unsupported font type: '.$type);
1705
                }
1706 1
                $this->$mtd($font);
1707
            }
1708
        }
1709 1
    }
1710
    
1711 1
    protected function putImages()
1712
    {
1713 1
        foreach (array_keys($this->images) as $file) {
1714
            $this->putimage($this->images[$file]);
1715
            unset($this->images[$file]['data']);
1716
            unset($this->images[$file]['smask']);
1717
        }
1718 1
    }
1719
    
1720
    protected function putimage(&$info)
1721
    {
1722
        $this->newobj();
1723
        $info['n'] = $this->n;
1724
        $this->out('<</Type /XObject');
1725
        $this->out('/Subtype /Image');
1726
        $this->out('/Width '.$info['w']);
1727
        $this->out('/Height '.$info['h']);
1728
        if ($info['cs']=='Indexed') {
1729
            $this->out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
1730
        } else {
1731
            $this->out('/ColorSpace /'.$info['cs']);
1732
            if ($info['cs']=='DeviceCMYK') {
1733
                $this->out('/Decode [1 0 1 0 1 0 1 0]');
1734
            }
1735
        }
1736
        $this->out('/BitsPerComponent '.$info['bpc']);
1737
        if (isset($info['f'])) {
1738
            $this->out('/Filter /'.$info['f']);
1739
        }
1740
        if (isset($info['dp'])) {
1741
            $this->out('/DecodeParms <<'.$info['dp'].'>>');
1742
        }
1743
        if (isset($info['trns']) && is_array($info['trns'])) {
1744
            $trns = '';
1745
            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...
1746
                $trns .= $info['trns'][$i].' '.$info['trns'][$i].' ';
1747
            }
1748
            $this->out('/Mask ['.$trns.']');
1749
        }
1750
        if (isset($info['smask'])) {
1751
            $this->out('/SMask '.($this->n+1).' 0 R');
1752
        }
1753
        $this->out('/Length '.strlen($info['data']).'>>');
1754
        $this->putstream($info['data']);
1755
        $this->out('endobj');
1756
    // Soft mask
1757
        if (isset($info['smask'])) {
1758
            $dp = '/Predictor 15 /Colors 1 /BitsPerComponent 8 /Columns '.$info['w'];
1759
            $smask = [
1760
                'w'=>$info['w'],
1761
                'h'=>$info['h'],
1762
                'cs'=>'DeviceGray',
1763
                'bpc'=>8,
1764
                'f'=>$info['f'],
1765
                'dp'=>$dp,
1766
                'data'=>$info['smask']
1767
            ];
1768
            $this->putimage($smask);
1769
        }
1770
    // Palette
1771
        if ($info['cs']=='Indexed') {
1772
            $this->putstreamobject($info['pal']);
0 ignored issues
show
Bug introduced by
The method putstreamobject() does not exist on NFePHP\DA\Legacy\FPDF\Fpdf. Did you maybe mean putStream()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1773
        }
1774
    }
1775
    
1776
1777
    /*protected function putImages()
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1778
    {
1779
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1780
        reset($this->images);
1781
        foreach (list($file,$info) as each($this->images)) {
1782
            $this->newObj();
1783
            $this->images[$file]['n'] = $this->n;
1784
            $this->out('<</Type /XObject');
1785
            $this->out('/Subtype /Image');
1786
            $this->out('/Width '.$info['w']);
1787
            $this->out('/Height '.$info['h']);
1788
            if ($info['cs']=='Indexed') {
1789
                $this->out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
1790
            } else {
1791
                $this->out('/ColorSpace /'.$info['cs']);
1792
                if ($info['cs']=='DeviceCMYK') {
1793
                    $this->out('/Decode [1 0 1 0 1 0 1 0]');
1794
                }
1795
            }
1796
            $this->out('/BitsPerComponent '.$info['bpc']);
1797
            if (isset($info['f'])) {
1798
                $this->out('/Filter /'.$info['f']);
1799
            }
1800
            if (isset($info['parms'])) {
1801
                $this->out($info['parms']);
1802
            }
1803
            if (isset($info['trns']) && is_array($info['trns'])) {
1804
                $trns = '';
1805
                for ($i=0; $i<count($info['trns']); $i++) {
1806
                    $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
1807
                }
1808
                $this->out('/Mask ['.$trns.']');
1809
            }
1810
            $this->out('/Length '.strlen($info['data']).'>>');
1811
            $this->putStream($info['data']);
1812
            unset($this->images[$file]['data']);
1813
            $this->out('endobj');
1814
            //Palette
1815
            if ($info['cs'] == 'Indexed') {
1816
                $this->newObj();
1817
                $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
1818
                $this->out('<<'.$filter.'/Length '.strlen($pal).'>>');
1819
                $this->putStream($pal);
1820
                $this->out('endobj');
1821
            }
1822
        }
1823
    }*/
1824
1825 1
    protected function putXobjectDict()
1826
    {
1827 1
        foreach ($this->images as $image) {
1828
            $this->out('/I'.$image['i'].' '.$image['n'].' 0 R');
1829
        }
1830 1
    }
1831
1832 1
    protected function putResourceDict()
1833
    {
1834 1
        $this->out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
1835 1
        $this->out('/Font <<');
1836 1
        foreach ($this->fonts as $font) {
1837 1
            $this->out('/F'.$font['i'].' '.$font['n'].' 0 R');
1838
        }
1839 1
        $this->out('>>');
1840 1
        $this->out('/XObject <<');
1841 1
        $this->putXobjectDict();
1842 1
        $this->out('>>');
1843 1
    }
1844
1845 1
    protected function putResources()
1846
    {
1847 1
        $this->putFonts();
1848 1
        $this->putImages();
1849
        //Resource dictionary
1850 1
        $this->offsets[2] = strlen($this->buffer);
1851 1
        $this->out('2 0 obj');
1852 1
        $this->out('<<');
1853 1
        $this->putResourceDict();
1854 1
        $this->out('>>');
1855 1
        $this->out('endobj');
1856 1
    }
1857
1858 1
    protected function putInfo()
1859
    {
1860 1
        $this->out('/Producer '.$this->textString('FPDF '. self::FPDF_VERSION));
1861 1
        if (!empty($this->title)) {
1862
            $this->out('/Title '.$this->textString($this->title));
1863
        }
1864 1
        if (!empty($this->subject)) {
1865
            $this->out('/Subject '.$this->textString($this->subject));
1866
        }
1867 1
        if (!empty($this->author)) {
1868
            $this->out('/Author '.$this->textString($this->author));
1869
        }
1870 1
        if (!empty($this->keywords)) {
1871
            $this->out('/Keywords '.$this->textString($this->keywords));
1872
        }
1873 1
        if (!empty($this->creator)) {
1874
            $this->out('/Creator '.$this->textString($this->creator));
1875
        }
1876 1
        $this->out('/CreationDate '.$this->textString('D:'.@date('YmdHis')));
1877 1
    }
1878
1879 1
    protected function putCatalog()
1880
    {
1881 1
        $this->out('/Type /Catalog');
1882 1
        $this->out('/Pages 1 0 R');
1883 1
        if ($this->zoomMode=='fullpage') {
1884
            $this->out('/OpenAction [3 0 R /Fit]');
1885 1
        } elseif ($this->zoomMode=='fullwidth') {
1886 1
            $this->out('/OpenAction [3 0 R /FitH null]');
1887
        } elseif ($this->zoomMode=='real') {
1888
            $this->out('/OpenAction [3 0 R /XYZ null null 1]');
1889
        } elseif (!is_string($this->zoomMode)) {
1890
            $this->out('/OpenAction [3 0 R /XYZ null null '.($this->zoomMode/100).']');
1891
        }
1892 1
        if ($this->layoutMode=='single') {
1893
            $this->out('/PageLayout /SinglePage');
1894 1
        } elseif ($this->layoutMode=='continuous') {
1895 1
            $this->out('/PageLayout /OneColumn');
1896
        } elseif ($this->layoutMode=='two') {
1897
            $this->out('/PageLayout /TwoColumnLeft');
1898
        }
1899 1
    }
1900
1901 1
    protected function putHeader()
1902
    {
1903 1
        $this->out('%PDF-'.$this->pdfVersion);
1904 1
    }
1905
1906 1
    protected function putTrailer()
1907
    {
1908 1
        $this->out('/Size '.($this->n+1));
1909 1
        $this->out('/Root '.$this->n.' 0 R');
1910 1
        $this->out('/Info '.($this->n-1).' 0 R');
1911 1
    }
1912
1913 1
    protected function endDoc()
1914
    {
1915 1
        $this->putHeader();
1916 1
        $this->putPages();
1917 1
        $this->putResources();
1918
        //Info
1919 1
        $this->newObj();
1920 1
        $this->out('<<');
1921 1
        $this->putInfo();
1922 1
        $this->out('>>');
1923 1
        $this->out('endobj');
1924
        //Catalog
1925 1
        $this->newObj();
1926 1
        $this->out('<<');
1927 1
        $this->putCatalog();
1928 1
        $this->out('>>');
1929 1
        $this->out('endobj');
1930
        //Cross-ref
1931 1
        $o=strlen($this->buffer);
1932 1
        $this->out('xref');
1933 1
        $this->out('0 '.($this->n+1));
1934 1
        $this->out('0000000000 65535 f ');
1935 1
        for ($i=1; $i<=$this->n; $i++) {
1936 1
            $this->out(sprintf('%010d 00000 n ', $this->offsets[$i]));
1937
        }
1938
        //Trailer
1939 1
        $this->out('trailer');
1940 1
        $this->out('<<');
1941 1
        $this->putTrailer();
1942 1
        $this->out('>>');
1943 1
        $this->out('startxref');
1944 1
        $this->out($o);
1945 1
        $this->out('%%EOF');
1946 1
        $this->state=3;
1947 1
    }
1948
}
1949