Passed
Pull Request — master (#114)
by Roberto
06:37
created

Fpdf1::__construct()   D

Complexity

Conditions 10
Paths 30

Size

Total Lines 102
Code Lines 82

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 0
Metric Value
cc 10
eloc 82
nc 30
nop 3
dl 0
loc 102
ccs 0
cts 89
cp 0
crap 110
rs 4.8196
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
namespace NFePHP\DA\Legacy\FPDF;
4
5
/**
6
 * Classe origial adaptada para PHP 7.2
7
 * @author Americo Belmiro de Souza Neto
8
 * @email [email protected]
9
 */
10
11
class Fpdf1
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
    public function __construct($orientation = 'P', $unit = 'mm', $format = 'A4')
75
    {
76
        //Some checks
77
        $this->dochecks();
78
        //Initialization of properties
79
        $this->page = 0;
80
        $this->n = 2;
81
        $this->buffer = '';
82
        $this->pages = array();
83
        $this->pageSizes = array();
84
        $this->state = 0;
85
        $this->fonts = array();
86
        $this->fontFiles = array();
87
        $this->diffs = array();
88
        $this->images = array();
89
        $this->links = array();
90
        $this->inHeader = false;
91
        $this->inFooter = false;
92
        $this->lasth = 0;
93
        $this->fontFamily = '';
94
        $this->fontStyle = '';
95
        $this->fontSizePt = 12;
96
        $this->underline = false;
97
        $this->drawColor = '0 G';
98
        $this->fillColor = '0 g';
99
        $this->textColor = '0 g';
100
        $this->colorFlag = false;
101
        $this->ws = 0;
102
        //Standard fonts
103
        $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
        if ($unit == 'pt') {
121
            $this->k = 1;
122
        } elseif ($unit == 'mm') {
123
            $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
        $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
        if (is_string($format)) {
140
            $format = $this->getpageformat($format);
141
        }
142
        $this->defPageFormat = $format;
143
        $this->curPageFormat = $format;
144
        //Page orientation
145
        $orientation = strtolower($orientation);
146
        if ($orientation == 'p' || $orientation == 'portrait') {
147
            $this->defOrientation='P';
148
            $this->w = $this->defPageFormat[0];
149
            $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
        $this->curOrientation = $this->defOrientation;
158
        $this->wPt = $this->w*$this->k;
159
        $this->hPt = $this->h*$this->k;
160
        //Page margins (1 cm)
161
        $margin = 28.35/$this->k;
162
        $this->setMargins($margin, $margin);
163
        //Interior cell margin (1 mm)
164
        $this->cMargin = $margin/10;
165
        //Line width (0.2 mm)
166
        $this->lineWidth = .567/$this->k;
167
        //Automatic page break
168
        $this->setAutoPageBreak(true, 2*$margin);
169
        //Full width display mode
170
        $this->setDisplayMode('fullwidth');
171
        //Enable compression
172
        $this->setCompression(true);
173
        //Set default PDF version number
174
        $this->pdfVersion='1.3';
175
    }
176
177
    public function setMargins($left, $top, $right = null)
178
    {
179
        //Set left, top and right margins
180
        $this->lMargin = $left;
181
        $this->tMargin = $top;
182
        if ($right === null) {
183
            $right = $left;
184
        }
185
        $this->rMargin=$right;
186
    }
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
    public function setAutoPageBreak($auto, $margin = 0)
210
    {
211
        //Set auto page break mode and triggering margin
212
        $this->autoPageBreak = $auto;
213
        $this->bMargin = $margin;
214
        $this->pageBreakTrigger = $this->h-$margin;
215
    }
216
217
    public function setDisplayMode($zoom, $layout = 'continuous')
218
    {
219
        //Set display mode in viewer
220
        if ($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom)) {
221
            $this->zoomMode = $zoom;
222
        } else {
223
            $this->error('Incorrect zoom display mode: '.$zoom);
224
        }
225
        if ($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default') {
226
            $this->layoutMode = $layout;
227
        } else {
228
            $this->error('Incorrect layout display mode: '.$layout);
229
        }
230
    }
231
232
    public function setCompression($compress)
233
    {
234
        //Set page compression
235
        if (function_exists('gzcompress')) {
236
            $this->compress = $compress;
237
        } else {
238
            $this->compress = false;
239
        }
240
    }
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
    public function aliasNbPages($alias = '{nb}')
288
    {
289
        //Define an alias for total number of pages
290
        $this->aliasNbPages=$alias;
291
    }
292
293
    public function error($msg)
294
    {
295
        throw new \Exception($msg);
296
    }
297
298
    public function open()
299
    {
300
        //Begin document
301
        $this->state = 1;
302
    }
303
304
    public function close()
305
    {
306
        //Terminate document
307
        if ($this->state == 3) {
308
            return;
309
        }
310
        if ($this->page == 0) {
311
            $this->addPage();
312
        }
313
        //Page footer
314
        $this->inFooter = true;
315
        $this->footer();
316
        $this->inFooter = false;
317
        //Close page
318
        $this->endPage();
319
        //Close document
320
        $this->endDoc();
321
    }
322
323
    public function addPage($orientation = '', $format = '')
324
    {
325
        //Start a new page
326
        if ($this->state==0) {
327
            $this->open();
328
        }
329
        $family = $this->fontFamily;
330
        $style = $this->fontStyle.($this->underline ? 'U' : '');
331
        $size = $this->fontSizePt;
332
        $lw = $this->lineWidth;
333
        $dc = $this->drawColor;
334
        $fc = $this->fillColor;
335
        $tc = $this->textColor;
336
        $cf = $this->colorFlag;
337
        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
        $this->beginPage($orientation, $format);
347
        //Set line cap style to square
348
        $this->out('2 J');
349
        //Set line width
350
        $this->lineWidth = $lw;
351
        $this->out(sprintf('%.2F w', $lw*$this->k));
352
        //Set font
353
        if ($family) {
354
            $this->setFont($family, $style, $size);
355
        }
356
        //Set colors
357
        $this->drawColor = $dc;
358
        if ($dc!='0 G') {
359
            $this->out($dc);
360
        }
361
        $this->fillColor = $fc;
362
        if ($fc != '0 g') {
363
            $this->out($fc);
364
        }
365
        $this->textColor = $tc;
366
        $this->colorFlag = $cf;
367
        //Page header
368
        $this->inHeader = true;
369
        $this->Header();
370
        $this->inHeader = false;
371
        //Restore line width
372
        if ($this->lineWidth != $lw) {
373
            $this->lineWidth = $lw;
374
            $this->out(sprintf('%.2F w', $lw*$this->k));
375
        }
376
        //Restore font
377
        if ($family) {
378
            $this->setFont($family, $style, $size);
379
        }
380
        //Restore colors
381
        if ($this->drawColor != $dc) {
382
            $this->drawColor = $dc;
383
            $this->out($dc);
384
        }
385
        if ($this->fillColor != $fc) {
386
            $this->fillColor = $fc;
387
            $this->out($fc);
388
        }
389
        $this->textColor = $tc;
390
        $this->colorFlag = $cf;
391
    }
392
393
    public function header()
394
    {
395
        //To be implemented in your own inherited class
396
    }
397
398
    public function footer()
399
    {
400
        //To be implemented in your own inherited class
401
    }
402
403
    public function pageNo()
404
    {
405
        //Get current page number
406
        return $this->page;
407
    }
408
409
    public function setDrawColor($r, $g = null, $b = null)
410
    {
411
        //Set color for all stroking operations
412
        if (($r==0 && $g==0 && $b==0) || $g===null) {
413
            $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
        if ($this->page > 0) {
418
            $this->out($this->drawColor);
419
        }
420
    }
421
422
    public function setFillColor($r, $g = null, $b = null)
423
    {
424
        //Set color for all filling operations
425
        if (($r==0 && $g==0 && $b==0) || $g===null) {
426
            $this->fillColor = sprintf('%.3F g', $r/255);
427
        } else {
428
            $this->fillColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255);
429
        }
430
        $this->colorFlag = ($this->fillColor != $this->textColor);
431
        if ($this->page > 0) {
432
            $this->out($this->fillColor);
433
        }
434
    }
435
436
    public function settextColor($r, $g = null, $b = null)
437
    {
438
        //Set color for text
439
        if (($r==0 && $g==0 && $b==0) || $g===null) {
440
            $this->textColor = sprintf('%.3F g', $r/255);
441
        } else {
442
            $this->textColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255);
443
        }
444
        $this->colorFlag = ($this->fillColor != $this->textColor);
445
    }
446
447
    public function getStringWidth($s)
448
    {
449
        //Get width of a string in the current font
450
        $s = (string)$s;
451
        $cw =& $this->currentFont['cw'];
452
        $w = 0;
453
        $l = strlen($s);
454
        for ($i=0; $i<$l; $i++) {
455
            $w += $cw[$s[$i]];
456
        }
457
        return $w*$this->fontSize/1000;
458
    }
459
460
    public function setLineWidth($width)
461
    {
462
        //Set line width
463
        $this->lineWidth = $width;
464
        if ($this->page > 0) {
465
            $this->out(sprintf('%.2F w', $width*$this->k));
466
        }
467
    }
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
    public function rect($x, $y, $w, $h, $style = '')
484
    {
485
        //Draw a rectangle
486
        if ($style == 'F') {
487
            $op = 'f';
488
        } elseif ($style == 'FD' || $style == 'DF') {
489
            $op = 'B';
490
        } else {
491
            $op = 'S';
492
        }
493
        $this->out(
494
            sprintf(
495
                '%.2F %.2F %.2F %.2F re %s',
496
                $x*$this->k,
497
                ($this->h-$y)*$this->k,
498
                $w*$this->k,
499
                -$h*$this->k,
500
                $op
501
            )
502
        );
503
    }
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
    public function setFont($family, $style = '', $size = 0)
565
    {
566
        //Select a font; size given in points
567
        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
        $family = strtolower($family);
569
        if ($family == '') {
570
            $family = $this->fontFamily;
571
        }
572
        if ($family == 'arial') {
573
            $family = 'helvetica';
574
        } elseif ($family == 'symbol' || $family == 'zapfdingbats') {
575
            $style = '';
576
        }
577
        $style = strtoupper($style);
578
        if (strpos($style, 'U') !== false) {
579
            $this->underline = true;
580
            $style = str_replace('U', '', $style);
581
        } else {
582
            $this->underline = false;
583
        }
584
        if ($style == 'IB') {
585
            $style = 'BI';
586
        }
587
        if ($size == 0) {
588
            $size = $this->fontSizePt;
589
        }
590
        //Test if font is already selected
591
        if ($this->fontFamily==$family && $this->fontStyle==$style && $this->fontSizePt==$size) {
592
            return;
593
        }
594
        //Test if used for the first time
595
        $fontkey = $family.$style;
596
        if (!isset($this->fonts[$fontkey])) {
597
            //Check if one of the standard fonts
598
            if (isset($this->coreFonts[$fontkey])) {
599
                if (!isset($fpdf_charwidths[$fontkey])) {
600
                    //Load metric file
601
                    $file=$family;
602
                    if ($family=='times' || $family=='helvetica') {
603
                        $file .= strtolower($style);
604
                    }
605
                    include $this->getFontPath().$file.'.php';
606
                    if (!isset($fpdf_charwidths[$fontkey])) {
607
                        $this->error('Could not include font metric file');
608
                    }
609
                }
610
                $i = count($this->fonts)+1;
611
                $name = $this->coreFonts[$fontkey];
612
                $cw = $fpdf_charwidths[$fontkey];
613
                $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
        $this->fontFamily = $family;
620
        $this->fontStyle = $style;
621
        $this->fontSizePt = $size;
622
        $this->fontSize = $size/$this->k;
623
        $this->currentFont =& $this->fonts[$fontkey];
624
        if ($this->page > 0) {
625
            $this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt));
626
        }
627
    }
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
    public function text($x, $y, $txt)
675
    {
676
        //Output a string
677
        $s = sprintf('BT %.2F %.2F Td (%s) Tj ET', $x*$this->k, ($this->h-$y)*$this->k, $this->escape($txt));
678
        if ($this->underline && $txt!='') {
679
            $s .= ' '.$this->doUnderLine($x, $y, $txt);
680
        }
681
        if ($this->colorFlag) {
682
            $s = 'q '.$this->textColor.' '.$s.' Q';
683
        }
684
        $this->out($s);
685
    }
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
    public function output($name = '', $dest = '')
1115
    {
1116
        //Output PDF to some destination
1117
        if ($this->state < 3) {
1118
            $this->close();
1119
        }
1120
        $dest = strtoupper($dest);
1121
        if ($dest == '') {
1122
            if ($name == '') {
1123
                $name = 'doc.pdf';
1124
                $dest = 'I';
1125
            } else {
1126
                $dest = 'F';
1127
            }
1128
        }
1129
        switch ($dest) {
1130
            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
            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
            case 'F':
1166
                //Save to local file
1167
                $f=fopen($name, 'wb');
1168
                if (!$f) {
1169
                    $this->error('Unable to create output file: '.$name);
1170
                }
1171
                fwrite($f, $this->buffer, strlen($this->buffer));
1172
                fclose($f);
1173
                break;
1174
            case 'S':
1175
                //Return as a string
1176
                return $this->buffer;
1177
            default:
1178
                $this->error('Incorrect output destination: '.$dest);
1179
        }
1180
        return '';
1181
    }
1182
1183
    protected function dochecks()
1184
    {
1185
        //Check availability of %F
1186
        if (sprintf('%.1F', 1.0)!='1.0') {
1187
            $this->error('This version of PHP is not supported');
1188
        }
1189
        //Check mbstring overloading
1190
        if (ini_get('mbstring.func_overload') & 2) {
1191
            $this->error('mbstring overloading must be disabled');
1192
        }
1193
    }
1194
1195
    protected function getpageformat($format)
1196
    {
1197
        $format=strtolower($format);
1198
        if (!isset($this->pageFormats[$format])) {
1199
            $this->error('Unknown page format: '.$format);
1200
        }
1201
        $a=$this->pageFormats[$format];
1202
        return array($a[0]/$this->k, $a[1]/$this->k);
1203
    }
1204
1205
    protected function getFontPath()
1206
    {
1207
        if (!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font')) {
1208
            define('FPDF_FONTPATH', dirname(__FILE__).'/font/');
1209
        }
1210
        return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
1211
    }
1212
1213
    protected function beginPage($orientation, $format)
1214
    {
1215
        $this->page++;
1216
        $this->pages[$this->page] = '';
1217
        $this->state = 2;
1218
        $this->x = $this->lMargin;
1219
        $this->y = $this->tMargin;
1220
        $this->fontFamily = '';
1221
        //Check page size
1222
        if ($orientation == '') {
1223
            $orientation = $this->defOrientation;
1224
        } else {
1225
            $orientation = strtoupper($orientation[0]);
1226
        }
1227
        if ($format == '') {
1228
            $format = $this->defPageFormat;
1229
        } else {
1230
            if (is_string($format)) {
1231
                $format=$this->getpageformat($format);
1232
            }
1233
        }
1234
        if ($orientation != $this->curOrientation
1235
            || $format[0]!=$this->curPageFormat[0]
1236
            || $format[1]!=$this->curPageFormat[1]
1237
        ) {
1238
            //New size
1239
            if ($orientation == 'P') {
1240
                $this->w = $format[0];
1241
                $this->h = $format[1];
1242
            } else {
1243
                $this->w = $format[1];
1244
                $this->h = $format[0];
1245
            }
1246
            $this->wPt = $this->w*$this->k;
1247
            $this->hPt = $this->h*$this->k;
1248
            $this->pageBreakTrigger = $this->h-$this->bMargin;
1249
            $this->curOrientation = $orientation;
1250
            $this->curPageFormat = $format;
1251
        }
1252
        if ($orientation != $this->defOrientation
1253
            || $format[0] != $this->defPageFormat[0]
1254
            || $format[1] != $this->defPageFormat[1]
1255
        ) {
1256
            $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...
1257
        }
1258
    }
1259
1260
    protected function endPage()
1261
    {
1262
        $this->state = 1;
1263
    }
1264
1265
    protected function escape($s)
1266
    {
1267
        //Escape special characters in strings
1268
        $s = str_replace('\\', '\\\\', $s);
1269
        $s = str_replace('(', '\\(', $s);
1270
        $s = str_replace(')', '\\)', $s);
1271
        $s = str_replace("\r", '\\r', $s);
1272
        return $s;
1273
    }
1274
1275
    protected function textString($s)
1276
    {
1277
        //Format a text string
1278
        return '('.$this->escape($s).')';
1279
    }
1280
1281
    protected function utf8Toutf16($s)
1282
    {
1283
        //Convert UTF-8 to UTF-16BE with BOM
1284
        $res = "\xFE\xFF";
1285
        $nb = strlen($s);
1286
        $i = 0;
1287
        while ($i < $nb) {
1288
            $c1 = ord($s[$i++]);
1289
            if ($c1 >= 224) {
1290
                //3-byte character
1291
                $c2 = ord($s[$i++]);
1292
                $c3 = ord($s[$i++]);
1293
                $res .= chr((($c1 & 0x0F)<<4) + (($c2 & 0x3C)>>2));
1294
                $res .= chr((($c2 & 0x03)<<6) + ($c3 & 0x3F));
1295
            } elseif ($c1 >= 192) {
1296
                //2-byte character
1297
                $c2 = ord($s[$i++]);
1298
                $res .= chr(($c1 & 0x1C)>>2);
1299
                $res .= chr((($c1 & 0x03)<<6) + ($c2 & 0x3F));
1300
            } else {
1301
                //Single-byte character
1302
                $res .= "\0".chr($c1);
1303
            }
1304
        }
1305
        return $res;
1306
    }
1307
1308
    protected function doUnderLine($x, $y, $txt)
1309
    {
1310
        //Underline text
1311
        $up = $this->currentFont['up'];
1312
        $ut = $this->currentFont['ut'];
1313
        $w = $this->getStringWidth($txt)+$this->ws*substr_count($txt, ' ');
1314
        return sprintf(
1315
            '%.2F %.2F %.2F %.2F re f',
1316
            $x*$this->k,
1317
            ($this->h-($y-$up/1000*$this->fontSize))*$this->k,
1318
            $w*$this->k,
1319
            -$ut/1000*$this->fontSizePt
1320
        );
1321
    }
1322
1323
    protected function parseJPG($file)
1324
    {
1325
        //Extract info from a JPEG file
1326
        $a = getImageSize($file);
1327
        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...
1328
            $this->error('Missing or incorrect image file: '.$file);
1329
        }
1330
        if ($a[2]!=2) {
1331
            $this->error('Not a JPEG file: '.$file);
1332
        }
1333
        if (!isset($a['channels']) || $a['channels'] == 3) {
1334
            $colspace = 'DeviceRGB';
1335
        } elseif ($a['channels'] == 4) {
1336
            $colspace = 'DeviceCMYK';
1337
        } else {
1338
            $colspace='DeviceGray';
1339
        }
1340
        $bpc = isset($a['bits']) ? $a['bits'] : 8;
1341
        //Read whole file
1342
        $f = fopen($file, 'rb');
1343
        $data = '';
1344
        while (!feof($f)) {
1345
            $data .= fread($f, 8192);
1346
        }
1347
        fclose($f);
1348
        return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data);
1349
    }
1350
1351
    protected function parsePNG($file)
1352
    {
1353
        //Extract info from a PNG file
1354
        $f = fopen($file, 'rb');
1355
        if (!$f) {
1356
            $this->error('Can\'t open image file: '.$file);
1357
        }
1358
        //Check signature
1359
        if ($this->readstream($f, 8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
1360
            $this->error('Not a PNG file: '.$file);
1361
        }
1362
        //Read header chunk
1363
        $this->readstream($f, 4);
1364
        if ($this->readstream($f, 4)!='IHDR') {
1365
            $this->error('Incorrect PNG file: '.$file);
1366
        }
1367
        $w = $this->readint($f);
1368
        $h = $this->readint($f);
1369
        $bpc = ord($this->readstream($f, 1));
1370
        if ($bpc>8) {
1371
            $this->error('16-bit depth not supported: '.$file);
1372
        }
1373
        $ct = ord($this->readstream($f, 1));
1374
        if ($ct == 0) {
1375
            $colspace = 'DeviceGray';
1376
        } elseif ($ct == 2) {
1377
            $colspace = 'DeviceRGB';
1378
        } elseif ($ct == 3) {
1379
            $colspace = 'Indexed';
1380
        } else {
1381
            $this->error('Alpha channel not supported: '.$file);
1382
        }
1383
        if (ord($this->readstream($f, 1)) != 0) {
1384
            $this->error('Unknown compression method: '.$file);
1385
        }
1386
        if (ord($this->readstream($f, 1)) != 0) {
1387
            $this->error('Unknown filter method: '.$file);
1388
        }
1389
        if (ord($this->readstream($f, 1)) != 0) {
1390
            $this->error('Interlacing not supported: '.$file);
1391
        }
1392
        $this->readstream($f, 4);
1393
        $parms = '/DecodeParms <</Predictor 15 /Colors '
1394
            . ($ct==2 ? 3 : 1)
1395
            . ' /BitsPerComponent '
1396
            . $bpc
1397
            . ' /Columns '
1398
            . $w
1399
            . '>>';
1400
        //Scan chunks looking for palette, transparency and image data
1401
        $pal = '';
1402
        $trns = '';
1403
        $data = '';
1404
        do {
1405
            $n = $this->readint($f);
1406
            $type = $this->readstream($f, 4);
1407
            if ($type == 'PLTE') {
1408
                //Read palette
1409
                $pal = $this->readstream($f, $n);
1410
                $this->readstream($f, 4);
1411
            } elseif ($type == 'tRNS') {
1412
                //Read transparency info
1413
                $t = $this->readstream($f, $n);
1414
                if ($ct == 0) {
1415
                    $trns = array(ord(substr($t, 1, 1)));
1416
                } elseif ($ct == 2) {
1417
                    $trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1)));
1418
                } else {
1419
                    $pos = strpos($t, chr(0));
1420
                    if ($pos !== false) {
1421
                        $trns = array($pos);
1422
                    }
1423
                }
1424
                $this->readstream($f, 4);
1425
            } elseif ($type == 'IDAT') {
1426
                //Read image data block
1427
                $data .= $this->readstream($f, $n);
1428
                $this->readstream($f, 4);
1429
            } elseif ($type == 'IEND') {
1430
                break;
1431
            } else {
1432
                $this->readstream($f, $n+4);
1433
            }
1434
        } while ($n);
1435
        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...
1436
            $this->error('Missing palette in '.$file);
1437
        }
1438
        fclose($f);
1439
        return [
1440
            'w'=>$w,
1441
            'h'=>$h,
1442
            'cs'=>$colspace,
1443
            'bpc'=>$bpc,
1444
            'f'=>'FlateDecode',
1445
            'parms'=>$parms,
1446
            'pal'=>$pal,
1447
            'trns'=>$trns,
1448
            'data'=>$data
1449
        ];
1450
    }
1451
1452
    protected function readstream($f, $n)
1453
    {
1454
        //Read n bytes from stream
1455
        $res='';
1456
        while ($n > 0 && !feof($f)) {
1457
            $s=fread($f, $n);
1458
            if ($s === false) {
1459
                $this->error('Error while reading stream');
1460
            }
1461
            $n -= strlen($s);
1462
            $res .= $s;
1463
        }
1464
        if ($n > 0) {
1465
            $this->error('Unexpected end of stream');
1466
        }
1467
        return $res;
1468
    }
1469
1470
    protected function readint($f)
1471
    {
1472
        //Read a 4-byte integer from stream
1473
        $a = unpack('Ni', $this->readstream($f, 4));
1474
        return $a['i'];
1475
    }
1476
1477
    protected function parseGIF($file)
1478
    {
1479
        //Extract info from a GIF file (via PNG conversion)
1480
        if (!function_exists('imagepng')) {
1481
            $this->error('GD extension is required for GIF support');
1482
        }
1483
        if (!function_exists('imagecreatefromgif')) {
1484
            $this->error('GD has no GIF read support');
1485
        }
1486
        $im = imagecreatefromgif($file);
1487
        if (!$im) {
1488
            $this->error('Missing or incorrect image file: '.$file);
1489
        }
1490
        imageinterlace($im, 0);
1491
        $tmp = tempnam('.', 'gif');
1492
        if (!$tmp) {
1493
            $this->error('Unable to create a temporary file');
1494
        }
1495
        if (!imagepng($im, $tmp)) {
1496
            $this->error('Error while saving to temporary file');
1497
        }
1498
        imagedestroy($im);
1499
        $info=$this->parsePNG($tmp);
1500
        unlink($tmp);
1501
        return $info;
1502
    }
1503
1504
    protected function newObj()
1505
    {
1506
        //Begin a new object
1507
        $this->n++;
1508
        $this->offsets[$this->n] = strlen($this->buffer);
1509
        $this->out($this->n.' 0 obj');
1510
    }
1511
1512
    protected function putStream($s)
1513
    {
1514
        $this->out('stream');
1515
        $this->out($s);
1516
        $this->out('endstream');
1517
    }
1518
1519
    protected function out($s)
1520
    {
1521
        //Add a line to the document
1522
        if ($this->state == 2) {
1523
            $this->pages[$this->page].=$s."\n";
1524
        } else {
1525
            $this->buffer .= $s."\n";
1526
        }
1527
    }
1528
1529
    protected function putPages()
1530
    {
1531
        $nb = $this->page;
1532
        if (!empty($this->aliasNbPages)) {
1533
            //Replace number of pages
1534
            for ($n=1; $n<=$nb; $n++) {
1535
                $this->pages[$n] = str_replace($this->aliasNbPages, $nb, $this->pages[$n]);
1536
            }
1537
        }
1538
        if ($this->defOrientation == 'P') {
1539
            $wPt = $this->defPageFormat[0]*$this->k;
1540
            $hPt = $this->defPageFormat[1]*$this->k;
1541
        } else {
1542
            $wPt = $this->defPageFormat[1]*$this->k;
1543
            $hPt = $this->defPageFormat[0]*$this->k;
1544
        }
1545
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1546
        for ($n=1; $n<=$nb; $n++) {
1547
            //Page
1548
            $this->newObj();
1549
            $this->out('<</Type /Page');
1550
            $this->out('/Parent 1 0 R');
1551
            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...
1552
                $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...
1553
            }
1554
            $this->out('/Resources 2 0 R');
1555
            if (isset($this->PageLinks[$n])) {
1556
                //Links
1557
                $annots = '/Annots [';
1558
                foreach ($this->PageLinks[$n] as $pl) {
1559
                    $rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0]+$pl[2], $pl[1]-$pl[3]);
1560
                    $annots .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
1561
                    if (is_string($pl[4])) {
1562
                        $annots .= '/A <</S /URI /URI '.$this->textString($pl[4]).'>>>>';
1563
                    } else {
1564
                        $l = $this->links[$pl[4]];
1565
                        $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...
1566
                        $annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>', 1+2*$l[0], $h-$l[1]*$this->k);
1567
                    }
1568
                }
1569
                $this->out($annots.']');
1570
            }
1571
            $this->out('/Contents '.($this->n+1).' 0 R>>');
1572
            $this->out('endobj');
1573
            //Page content
1574
            $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
1575
            $this->newObj();
1576
            $this->out('<<'.$filter.'/Length '.strlen($p).'>>');
1577
            $this->putStream($p);
1578
            $this->out('endobj');
1579
        }
1580
        //Pages root
1581
        $this->offsets[1]=strlen($this->buffer);
1582
        $this->out('1 0 obj');
1583
        $this->out('<</Type /Pages');
1584
        $kids = '/Kids [';
1585
        for ($i=0; $i<$nb; $i++) {
1586
            $kids .= (3+2*$i).' 0 R ';
1587
        }
1588
        $this->out($kids.']');
1589
        $this->out('/Count '.$nb);
1590
        $this->out(sprintf('/MediaBox [0 0 %.2F %.2F]', $wPt, $hPt));
1591
        $this->out('>>');
1592
        $this->out('endobj');
1593
    }
1594
1595
    protected function putFonts()
1596
    {
1597
        $nf = $this->n;
1598
        foreach ($this->diffs as $diff) {
1599
            //Encodings
1600
            $this->newObj();
1601
            $this->out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
1602
            $this->out('endobj');
1603
        }
1604
        foreach ($this->fontFiles as $file => $info) {
1605
            //Font file embedding
1606
            $this->newObj();
1607
            $this->fontFiles[$file]['n']=$this->n;
1608
            $font='';
1609
            $f = fopen($this->getFontPath().$file, 'rb', 1);
1610
            if (!$f) {
1611
                $this->error('Font file not found');
1612
            }
1613
            while (!feof($f)) {
1614
                $font.=fread($f, 8192);
1615
            }
1616
            fclose($f);
1617
            $compressed = (substr($file, -2)=='.z');
1618
            if (!$compressed && isset($info['length2'])) {
1619
                $header = (ord($font[0])==128);
1620
                if ($header) {
1621
                    //Strip first binary header
1622
                    $font = substr($font, 6);
1623
                }
1624
                if ($header && ord($font[$info['length1']]) == 128) {
1625
                    //Strip second binary header
1626
                    $font = substr($font, 0, $info['length1']).substr($font, $info['length1']+6);
1627
                }
1628
            }
1629
            $this->out('<</Length '.strlen($font));
1630
            if ($compressed) {
1631
                $this->out('/Filter /FlateDecode');
1632
            }
1633
            $this->out('/Length1 '.$info['length1']);
1634
            if (isset($info['length2'])) {
1635
                $this->out('/Length2 '.$info['length2'].' /Length3 0');
1636
            }
1637
            $this->out('>>');
1638
            $this->putStream($font);
1639
            $this->out('endobj');
1640
        }
1641
        foreach ($this->fonts as $k => $font) {
1642
            //Font objects
1643
            $this->fonts[$k]['n']=$this->n+1;
1644
            $type = $font['type'];
1645
            $name = $font['name'];
1646
            if ($type == 'core') {
1647
                //Standard font
1648
                $this->newObj();
1649
                $this->out('<</Type /Font');
1650
                $this->out('/BaseFont /'.$name);
1651
                $this->out('/Subtype /Type1');
1652
                if ($name != 'Symbol' && $name != 'ZapfDingbats') {
1653
                    $this->out('/Encoding /WinAnsiEncoding');
1654
                }
1655
                $this->out('>>');
1656
                $this->out('endobj');
1657
            } elseif ($type=='Type1' || $type=='TrueType') {
1658
                //Additional Type1 or TrueType font
1659
                $this->newObj();
1660
                $this->out('<</Type /Font');
1661
                $this->out('/BaseFont /'.$name);
1662
                $this->out('/Subtype /'.$type);
1663
                $this->out('/FirstChar 32 /LastChar 255');
1664
                $this->out('/Widths '.($this->n+1).' 0 R');
1665
                $this->out('/FontDescriptor '.($this->n+2).' 0 R');
1666
                if ($font['enc']) {
1667
                    if (isset($font['diff'])) {
1668
                        $this->out('/Encoding '.($nf+$font['diff']).' 0 R');
1669
                    } else {
1670
                        $this->out('/Encoding /WinAnsiEncoding');
1671
                    }
1672
                }
1673
                $this->out('>>');
1674
                $this->out('endobj');
1675
                //Widths
1676
                $this->newObj();
1677
                $cw =& $font['cw'];
1678
                $s = '[';
1679
                for ($i=32; $i<=255; $i++) {
1680
                    $s .= $cw[chr($i)].' ';
1681
                }
1682
                $this->out($s.']');
1683
                $this->out('endobj');
1684
                //Descriptor
1685
                $this->newObj();
1686
                $s='<</Type /FontDescriptor /FontName /'.$name;
1687
                foreach ($font['desc'] as $k => $v) {
1688
                    $s .= ' /'.$k.' '.$v;
1689
                }
1690
                $file=$font['file'];
1691
                if ($file) {
1692
                    $s .= ' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->fontFiles[$file]['n'].' 0 R';
1693
                }
1694
                $this->out($s.'>>');
1695
                $this->out('endobj');
1696
            } else {
1697
                //Allow for additional types
1698
                $mtd='_put'.strtolower($type);
1699
                if (!method_exists($this, $mtd)) {
1700
                    $this->error('Unsupported font type: '.$type);
1701
                }
1702
                $this->$mtd($font);
1703
            }
1704
        }
1705
    }
1706
    
1707
    protected function putImages()
1708
    {
1709
        foreach (array_keys($this->images) as $file) {
1710
            $this->putimage($this->images[$file]);
1711
            unset($this->images[$file]['data']);
1712
            unset($this->images[$file]['smask']);
1713
        }
1714
    }
1715
    
1716
    protected function putimage(&$info)
1717
    {
1718
        $this->newobj();
1719
        $info['n'] = $this->n;
1720
        $this->out('<</Type /XObject');
1721
        $this->out('/Subtype /Image');
1722
        $this->out('/Width '.$info['w']);
1723
        $this->out('/Height '.$info['h']);
1724
        if ($info['cs']=='Indexed') {
1725
            $this->out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
1726
        } else {
1727
            $this->out('/ColorSpace /'.$info['cs']);
1728
            if ($info['cs']=='DeviceCMYK') {
1729
                $this->out('/Decode [1 0 1 0 1 0 1 0]');
1730
            }
1731
        }
1732
        $this->out('/BitsPerComponent '.$info['bpc']);
1733
        if (isset($info['f'])) {
1734
            $this->out('/Filter /'.$info['f']);
1735
        }
1736
        if (isset($info['dp'])) {
1737
            $this->out('/DecodeParms <<'.$info['dp'].'>>');
1738
        }
1739
        if (isset($info['trns']) && is_array($info['trns'])) {
1740
            $trns = '';
1741
            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...
1742
                $trns .= $info['trns'][$i].' '.$info['trns'][$i].' ';
1743
            }
1744
            $this->out('/Mask ['.$trns.']');
1745
        }
1746
        if (isset($info['smask'])) {
1747
            $this->out('/SMask '.($this->n+1).' 0 R');
1748
        }
1749
        $this->out('/Length '.strlen($info['data']).'>>');
1750
        $this->putstream($info['data']);
1751
        $this->out('endobj');
1752
    // Soft mask
1753
        if (isset($info['smask'])) {
1754
            $dp = '/Predictor 15 /Colors 1 /BitsPerComponent 8 /Columns '.$info['w'];
1755
            $smask = [
1756
                'w'=>$info['w'],
1757
                'h'=>$info['h'],
1758
                'cs'=>'DeviceGray',
1759
                'bpc'=>8,
1760
                'f'=>$info['f'],
1761
                'dp'=>$dp,
1762
                'data'=>$info['smask']
1763
            ];
1764
            $this->putimage($smask);
1765
        }
1766
    // Palette
1767
        if ($info['cs']=='Indexed') {
1768
            $this->putstreamobject($info['pal']);
0 ignored issues
show
Bug introduced by
The method putstreamobject() does not exist on NFePHP\DA\Legacy\FPDF\Fpdf1. 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...
1769
        }
1770
    }
1771
    
1772
1773
    /*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...
1774
    {
1775
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1776
        reset($this->images);
1777
        foreach (list($file,$info) as each($this->images)) {
1778
            $this->newObj();
1779
            $this->images[$file]['n'] = $this->n;
1780
            $this->out('<</Type /XObject');
1781
            $this->out('/Subtype /Image');
1782
            $this->out('/Width '.$info['w']);
1783
            $this->out('/Height '.$info['h']);
1784
            if ($info['cs']=='Indexed') {
1785
                $this->out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
1786
            } else {
1787
                $this->out('/ColorSpace /'.$info['cs']);
1788
                if ($info['cs']=='DeviceCMYK') {
1789
                    $this->out('/Decode [1 0 1 0 1 0 1 0]');
1790
                }
1791
            }
1792
            $this->out('/BitsPerComponent '.$info['bpc']);
1793
            if (isset($info['f'])) {
1794
                $this->out('/Filter /'.$info['f']);
1795
            }
1796
            if (isset($info['parms'])) {
1797
                $this->out($info['parms']);
1798
            }
1799
            if (isset($info['trns']) && is_array($info['trns'])) {
1800
                $trns = '';
1801
                for ($i=0; $i<count($info['trns']); $i++) {
1802
                    $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
1803
                }
1804
                $this->out('/Mask ['.$trns.']');
1805
            }
1806
            $this->out('/Length '.strlen($info['data']).'>>');
1807
            $this->putStream($info['data']);
1808
            unset($this->images[$file]['data']);
1809
            $this->out('endobj');
1810
            //Palette
1811
            if ($info['cs'] == 'Indexed') {
1812
                $this->newObj();
1813
                $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
1814
                $this->out('<<'.$filter.'/Length '.strlen($pal).'>>');
1815
                $this->putStream($pal);
1816
                $this->out('endobj');
1817
            }
1818
        }
1819
    }*/
1820
1821
    protected function putXobjectDict()
1822
    {
1823
        foreach ($this->images as $image) {
1824
            $this->out('/I'.$image['i'].' '.$image['n'].' 0 R');
1825
        }
1826
    }
1827
1828
    protected function putResourceDict()
1829
    {
1830
        $this->out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
1831
        $this->out('/Font <<');
1832
        foreach ($this->fonts as $font) {
1833
            $this->out('/F'.$font['i'].' '.$font['n'].' 0 R');
1834
        }
1835
        $this->out('>>');
1836
        $this->out('/XObject <<');
1837
        $this->putXobjectDict();
1838
        $this->out('>>');
1839
    }
1840
1841
    protected function putResources()
1842
    {
1843
        $this->putFonts();
1844
        $this->putImages();
1845
        //Resource dictionary
1846
        $this->offsets[2] = strlen($this->buffer);
1847
        $this->out('2 0 obj');
1848
        $this->out('<<');
1849
        $this->putResourceDict();
1850
        $this->out('>>');
1851
        $this->out('endobj');
1852
    }
1853
1854
    protected function putInfo()
1855
    {
1856
        $this->out('/Producer '.$this->textString('FPDF '. self::FPDF_VERSION));
1857
        if (!empty($this->title)) {
1858
            $this->out('/Title '.$this->textString($this->title));
1859
        }
1860
        if (!empty($this->subject)) {
1861
            $this->out('/Subject '.$this->textString($this->subject));
1862
        }
1863
        if (!empty($this->author)) {
1864
            $this->out('/Author '.$this->textString($this->author));
1865
        }
1866
        if (!empty($this->keywords)) {
1867
            $this->out('/Keywords '.$this->textString($this->keywords));
1868
        }
1869
        if (!empty($this->creator)) {
1870
            $this->out('/Creator '.$this->textString($this->creator));
1871
        }
1872
        $this->out('/CreationDate '.$this->textString('D:'.@date('YmdHis')));
1873
    }
1874
1875
    protected function putCatalog()
1876
    {
1877
        $this->out('/Type /Catalog');
1878
        $this->out('/Pages 1 0 R');
1879
        if ($this->zoomMode=='fullpage') {
1880
            $this->out('/OpenAction [3 0 R /Fit]');
1881
        } elseif ($this->zoomMode=='fullwidth') {
1882
            $this->out('/OpenAction [3 0 R /FitH null]');
1883
        } elseif ($this->zoomMode=='real') {
1884
            $this->out('/OpenAction [3 0 R /XYZ null null 1]');
1885
        } elseif (!is_string($this->zoomMode)) {
1886
            $this->out('/OpenAction [3 0 R /XYZ null null '.($this->zoomMode/100).']');
1887
        }
1888
        if ($this->layoutMode=='single') {
1889
            $this->out('/PageLayout /SinglePage');
1890
        } elseif ($this->layoutMode=='continuous') {
1891
            $this->out('/PageLayout /OneColumn');
1892
        } elseif ($this->layoutMode=='two') {
1893
            $this->out('/PageLayout /TwoColumnLeft');
1894
        }
1895
    }
1896
1897
    protected function putHeader()
1898
    {
1899
        $this->out('%PDF-'.$this->pdfVersion);
1900
    }
1901
1902
    protected function putTrailer()
1903
    {
1904
        $this->out('/Size '.($this->n+1));
1905
        $this->out('/Root '.$this->n.' 0 R');
1906
        $this->out('/Info '.($this->n-1).' 0 R');
1907
    }
1908
1909
    protected function endDoc()
1910
    {
1911
        $this->putHeader();
1912
        $this->putPages();
1913
        $this->putResources();
1914
        //Info
1915
        $this->newObj();
1916
        $this->out('<<');
1917
        $this->putInfo();
1918
        $this->out('>>');
1919
        $this->out('endobj');
1920
        //Catalog
1921
        $this->newObj();
1922
        $this->out('<<');
1923
        $this->putCatalog();
1924
        $this->out('>>');
1925
        $this->out('endobj');
1926
        //Cross-ref
1927
        $o=strlen($this->buffer);
1928
        $this->out('xref');
1929
        $this->out('0 '.($this->n+1));
1930
        $this->out('0000000000 65535 f ');
1931
        for ($i=1; $i<=$this->n; $i++) {
1932
            $this->out(sprintf('%010d 00000 n ', $this->offsets[$i]));
1933
        }
1934
        //Trailer
1935
        $this->out('trailer');
1936
        $this->out('<<');
1937
        $this->putTrailer();
1938
        $this->out('>>');
1939
        $this->out('startxref');
1940
        $this->out($o);
1941
        $this->out('%%EOF');
1942
        $this->state=3;
1943
    }
1944
}
1945