Completed
Push — master ( a0ced1...0c034e )
by Roberto
123:33 queued 74:20
created

Fpdf::ln()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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

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

1. Pass all data via parameters

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

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

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

    public function myFunction() {
        // Do something
    }
}
Loading history...
563 1
        $family = strtolower($family);
564 1
        if ($family == '') {
565
            $family = $this->fontFamily;
566
        }
567 1
        if ($family == 'arial') {
568
            $family = 'helvetica';
569 1
        } elseif ($family == 'symbol' || $family == 'zapfdingbats') {
570
            $style = '';
571
        }
572 1
        $style = strtoupper($style);
573 1
        if (strpos($style, 'U') !== false) {
574
            $this->underline = true;
575
            $style = str_replace('U', '', $style);
576
        } else {
577 1
            $this->underline = false;
578
        }
579 1
        if ($style == 'IB') {
580
            $style = 'BI';
581
        }
582 1
        if ($size == 0) {
583
            $size = $this->fontSizePt;
584
        }
585
        //Test if font is already selected
586 1
        if ($this->fontFamily==$family && $this->fontStyle==$style && $this->fontSizePt==$size) {
587 1
            return;
588
        }
589
        //Test if used for the first time
590 1
        $fontkey = $family.$style;
591 1
        if (!isset($this->fonts[$fontkey])) {
592
            //Check if one of the standard fonts
593 1
            if (isset($this->coreFonts[$fontkey])) {
594 1
                if (!isset($fpdf_charwidths[$fontkey])) {
595
                    //Load metric file
596 1
                    $file=$family;
597 1
                    if ($family=='times' || $family=='helvetica') {
598 1
                        $file .= strtolower($style);
599
                    }
600 1
                    include $this->getFontPath().$file.'.php';
601 1
                    if (!isset($fpdf_charwidths[$fontkey])) {
602
                        $this->error('Could not include font metric file');
603
                    }
604
                }
605 1
                $i = count($this->fonts)+1;
606 1
                $name = $this->coreFonts[$fontkey];
607 1
                $cw = $fpdf_charwidths[$fontkey];
608 1
                $this->fonts[$fontkey] = ['i'=>$i, 'type'=>'core', 'name'=>$name, 'up'=>-100, 'ut'=>50, 'cw'=>$cw];
609
            } else {
610
                $this->error('Undefined font: '.$family.' '.$style);
611
            }
612
        }
613
        //Select it
614 1
        $this->fontFamily = $family;
615 1
        $this->fontStyle = $style;
616 1
        $this->fontSizePt = $size;
617 1
        $this->fontSize = $size/$this->k;
618 1
        $this->currentFont =& $this->fonts[$fontkey];
619 1
        if ($this->page > 0) {
620 1
            $this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt));
621
        }
622 1
    }
623
    
624
    public function setFontSize($size)
625
    {
626
        //Set font size in points
627
        if ($this->fontSizePt == $size) {
628
            return;
629
        }
630
        $this->fontSizePt = $size;
631
        $this->fontSize = $size/$this->k;
632
        if ($this->page > 0) {
633
            $this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt));
634
        }
635
    }
636
    
637
    public function addlink()
638
    {
639
        //Create a new internal link
640
        $n = count($this->links)+1;
641
        $this->links[$n] = array(0, 0);
642
        return $n;
643
    }
644
    
645
    public function setlink($link, $y = 0, $page = -1)
646
    {
647
        //Set destination of internal link
648
        if ($y == -1) {
649
            $y = $this->y;
650
        }
651
        if ($page == -1) {
652
            $page = $this->page;
653
        }
654
        $this->links[$link] = array($page, $y);
655
    }
656
    
657
    public function link($x, $y, $w, $h, $link)
658
    {
659
        //Put a link on the page
660
        $this->PageLinks[$this->page][] = [
661
            $x*$this->k,
662
            $this->hPt-$y*$this->k,
663
            $w*$this->k,
664
            $h*$this->k,
665
            $link
666
        ];
667
    }
668
    
669 1
    public function text($x, $y, $txt)
670
    {
671
        //Output a string
672 1
        $s = sprintf('BT %.2F %.2F Td (%s) Tj ET', $x*$this->k, ($this->h-$y)*$this->k, $this->escape($txt));
673 1
        if ($this->underline && $txt!='') {
674
            $s .= ' '.$this->doUnderLine($x, $y, $txt);
675
        }
676 1
        if ($this->colorFlag) {
677 1
            $s = 'q '.$this->textColor.' '.$s.' Q';
678
        }
679 1
        $this->out($s);
680 1
    }
681
    
682
    public function acceptPageBreak()
683
    {
684
        //Accept automatic page break or not
685
        return $this->autoPageBreak;
686
    }
687
    
688
    public function cell($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = false, $link = '')
689
    {
690
        //Output a cell
691
        $k = $this->k;
692
        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...
693
            && !$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...
694
            && !$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...
695
            && $this->acceptPageBreak()
696
        ) {
697
            //Automatic page break
698
            $x = $this->x;
699
            $ws = $this->ws;
700
            if ($ws > 0) {
701
                $this->ws = 0;
702
                $this->out('0 Tw');
703
            }
704
            $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...
705
            $this->x = $x;
706
            if ($ws > 0) {
707
                $this->ws = $ws;
708
                $this->out(sprintf('%.3F Tw', $ws*$k));
709
            }
710
        }
711
        if ($w == 0) {
712
            $w = $this->w-$this->rMargin-$this->x;
713
        }
714
        $s='';
715
        if ($fill || $border==1) {
716
            if ($fill) {
717
                $op=($border==1) ? 'B' : 'f';
718
            } else {
719
                $op='S';
720
            }
721
            $s=sprintf('%.2F %.2F %.2F %.2F re %s ', $this->x*$k, ($this->h-$this->y)*$k, $w*$k, -$h*$k, $op);
722
        }
723
        if (is_string($border)) {
724
            $x = $this->x;
725
            $y = $this->y;
726
            if (strpos($border, 'L') !== false) {
727
                $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x*$k, ($this->h-$y)*$k, $x*$k, ($this->h-($y+$h))*$k);
728
            }
729
            if (strpos($border, 'T') !== false) {
730
                $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x*$k, ($this->h-$y)*$k, ($x+$w)*$k, ($this->h-$y)*$k);
731
            }
732
            if (strpos($border, 'R') !== false) {
733
                $s .= sprintf(
734
                    '%.2F %.2F m %.2F %.2F l S ',
735
                    ($x+$w)*$k,
736
                    ($this->h-$y)*$k,
737
                    ($x+$w)*$k,
738
                    ($this->h-($y+$h))*$k
739
                );
740
            }
741
            if (strpos($border, 'B') !== false) {
742
                $s .= sprintf(
743
                    '%.2F %.2F m %.2F %.2F l S ',
744
                    $x*$k,
745
                    ($this->h-($y+$h))*$k,
746
                    ($x+$w)*$k,
747
                    ($this->h-($y+$h))*$k
748
                );
749
            }
750
        }
751
        if ($txt !== '') {
752
            if ($align == 'R') {
753
                $dx = $w-$this->cMargin-$this->getStringWidth($txt);
754
            } elseif ($align == 'C') {
755
                $dx = ($w-$this->getStringWidth($txt))/2;
756
            } else {
757
                $dx = $this->cMargin;
758
            }
759
            if ($this->colorFlag) {
760
                $s .= 'q '.$this->textColor.' ';
761
            }
762
            $txt2 = str_replace(')', '\\)', str_replace('(', '\\(', str_replace('\\', '\\\\', $txt)));
763
            $s .= sprintf(
764
                'BT %.2F %.2F Td (%s) Tj ET',
765
                ($this->x+$dx)*$k,
766
                ($this->h-($this->y+.5*$h+.3*$this->fontSize))*$k,
767
                $txt2
768
            );
769
            if ($this->underline) {
770
                $s .= ' '.$this->doUnderLine($this->x+$dx, $this->y+.5*$h+.3*$this->fontSize, $txt);
771
            }
772
            if ($this->colorFlag) {
773
                $s.=' Q';
774
            }
775
            if ($link) {
776
                $this->link(
777
                    $this->x+$dx,
778
                    $this->y+.5*$h-.5*$this->fontSize,
779
                    $this->getStringWidth($txt),
780
                    $this->fontSize,
781
                    $link
782
                );
783
            }
784
        }
785
        if ($s) {
786
            $this->out($s);
787
        }
788
        $this->lasth = $h;
789
        if ($ln > 0) {
790
            //Go to next line
791
            $this->y += $h;
792
            if ($ln == 1) {
793
                $this->x = $this->lMargin;
794
            }
795
        } else {
796
            $this->x += $w;
797
        }
798
    }
799
    
800
    public function multicell($w, $h, $txt, $border = 0, $align = 'J', $fill = false)
801
    {
802
        //Output text with automatic or explicit line breaks
803
        $cw =& $this->currentFont['cw'];
804
        if ($w == 0) {
805
            $w = $this->w-$this->rMargin-$this->x;
806
        }
807
        $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
808
        $s = str_replace("\r", '', $txt);
809
        $nb = strlen($s);
810
        if ($nb>0 && $s[$nb-1] == "\n") {
811
            $nb--;
812
        }
813
        $b = 0;
814
        if ($border) {
815
            if ($border == 1) {
816
                $border = 'LTRB';
817
                $b = 'LRT';
818
                $b2 = 'LR';
819
            } else {
820
                $b2 = '';
821
                if (strpos($border, 'L') !== false) {
822
                    $b2 .= 'L';
823
                }
824
                if (strpos($border, 'R') !== false) {
825
                    $b2 .= 'R';
826
                }
827
                $b=(strpos($border, 'T') !== false) ? $b2.'T' : $b2;
828
            }
829
        }
830
        $sep = -1;
831
        $i = 0;
832
        $j = 0;
833
        $l = 0;
834
        $ns = 0;
835
        $nl = 1;
836
        while ($i<$nb) {
837
            //Get next character
838
            $c = $s[$i];
839
            if ($c == "\n") {
840
                //Explicit line break
841
                if ($this->ws > 0) {
842
                    $this->ws = 0;
843
                    $this->out('0 Tw');
844
                }
845
                $this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
846
                $i++;
847
                $sep = -1;
848
                $j = $i;
849
                $l = 0;
850
                $ns = 0;
851
                $nl++;
852
                if ($border && $nl == 2) {
853
                    $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...
854
                }
855
                continue;
856
            }
857
            if ($c == ' ') {
858
                $sep = $i;
859
                $ls = $l;
860
                $ns++;
861
            }
862
            $l += $cw[$c];
863
            if ($l > $wmax) {
864
                //Automatic line break
865
                if ($sep == -1) {
866
                    if ($i == $j) {
867
                        $i++;
868
                    }
869
                    if ($this->ws > 0) {
870
                        $this->ws = 0;
871
                        $this->out('0 Tw');
872
                    }
873
                    $this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
874
                } else {
875
                    if ($align=='J') {
876
                        $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...
877
                        $this->out(sprintf('%.3F Tw', $this->ws*$this->k));
878
                    }
879
                    $this->cell($w, $h, substr($s, $j, $sep-$j), $b, 2, $align, $fill);
880
                    $i = $sep+1;
881
                }
882
                $sep = -1;
883
                $j = $i;
884
                $l = 0;
885
                $ns = 0;
886
                $nl++;
887
                if ($border && $nl == 2) {
888
                    $b = $b2;
889
                }
890
            } else {
891
                $i++;
892
            }
893
        }
894
        //Last chunk
895
        if ($this->ws > 0) {
896
            $this->ws = 0;
897
            $this->out('0 Tw');
898
        }
899
        if ($border && strpos($border, 'B')!==false) {
900
            $b .= 'B';
901
        }
902
        $this->cell($w, $h, substr($s, $j, $i-$j), $b, 2, $align, $fill);
903
        $this->x = $this->lMargin;
904
    }
905
    
906
    
907
    public function write($h, $txt, $link = '')
908
    {
909
        //Output text in flowing mode
910
        $cw =& $this->currentFont['cw'];
911
        $w = $this->w-$this->rMargin-$this->x;
912
        $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
913
        $s = str_replace("\r", '', $txt);
914
        $nb = strlen($s);
915
        $sep = -1;
916
        $i = 0;
917
        $j = 0;
918
        $l = 0;
919
        $nl = 1;
920
        while ($i < $nb) {
921
            //Get next character
922
            $c=$s[$i];
923
            if ($c=="\n") {
924
                //Explicit line break
925
                $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...
926
                $i++;
927
                $sep = -1;
928
                $j = $i;
929
                $l = 0;
930
                if ($nl == 1) {
931
                    $this->x = $this->lMargin;
932
                    $w = $this->w-$this->rMargin-$this->x;
933
                    $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
934
                }
935
                $nl++;
936
                continue;
937
            }
938
            if ($c == ' ') {
939
                $sep = $i;
940
            }
941
            $l += $cw[$c];
942
            if ($l > $wmax) {
943
                //Automatic line break
944
                if ($sep == -1) {
945
                    if ($this->x > $this->lMargin) {
946
                        //Move to next line
947
                        $this->x = $this->lMargin;
948
                        $this->y += $h;
949
                        $w = $this->w-$this->rMargin-$this->x;
950
                        $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
951
                        $i++;
952
                        $nl++;
953
                        continue;
954
                    }
955
                    if ($i == $j) {
956
                        $i++;
957
                    }
958
                    $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...
959
                } else {
960
                    $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...
961
                    $i = $sep+1;
962
                }
963
                $sep = -1;
964
                $j = $i;
965
                $l = 0;
966
                if ($nl == 1) {
967
                    $this->x = $this->lMargin;
968
                    $w = $this->w-$this->rMargin-$this->x;
969
                    $wmax = ($w-2*$this->cMargin)*1000/$this->fontSize;
970
                }
971
                $nl++;
972
            } else {
973
                $i++;
974
            }
975
        }
976
        //Last chunk
977
        if ($i != $j) {
978
            $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...
979
        }
980
    }
981
    
982
    public function ln($h = null)
983
    {
984
        //Line feed; default value is last cell height
985
        $this->x = $this->lMargin;
986
        if ($h === null) {
987
            $this->y += $this->lasth;
988
        } else {
989
            $this->y += $h;
990
        }
991
    }
992
    
993
    public function image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '')
994
    {
995
        //Put an image on the page
996
        if (!isset($this->images[$file])) {
997
            //First use of this image, get info
998
            if ($type == '') {
999
                $pos = strrpos($file, '.');
1000
                if (!$pos) {
1001
                    $this->error('Image file has no extension and no type was specified: '.$file);
1002
                }
1003
                $type = substr($file, $pos+1);
1004
            }
1005
            $type = strtolower($type);
1006
            if ($type == 'jpeg') {
1007
                $type = 'jpg';
1008
            }
1009
            $mtd = 'parse'.strtoupper($type);
1010
            if (!method_exists($this, $mtd)) {
1011
                $this->error('Unsupported image type: '.$type);
1012
            }
1013
            $info = $this->$mtd($file);
1014
            $info['i'] = count($this->images)+1;
1015
            $this->images[$file] = $info;
1016
        } else {
1017
            $info = $this->images[$file];
1018
        }
1019
        //Automatic width and height calculation if needed
1020
        if ($w == 0 && $h == 0) {
1021
            //Put image at 72 dpi
1022
            $w = $info['w']/$this->k;
1023
            $h = $info['h']/$this->k;
1024
        } elseif ($w == 0) {
1025
            $w = $h*$info['w']/$info['h'];
1026
        } elseif ($h == 0) {
1027
            $h = $w*$info['h']/$info['w'];
1028
        }
1029
        //Flowing mode
1030
        if ($y === null) {
1031
            if ($this->y+$h > $this->pageBreakTrigger
1032
                && !$this->inHeader
1033
                && !$this->inFooter
1034
                && $this->acceptPageBreak()
1035
            ) {
1036
                //Automatic page break
1037
                $x2 = $this->x;
1038
                $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...
1039
                $this->x = $x2;
1040
            }
1041
            $y = $this->y;
1042
            $this->y += $h;
1043
        }
1044
        if ($x === null) {
1045
            $x = $this->x;
1046
        }
1047
        $this->out(
1048
            sprintf(
1049
                'q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q',
1050
                $w*$this->k,
1051
                $h*$this->k,
1052
                $x*$this->k,
1053
                ($this->h-($y+$h))*$this->k,
1054
                $info['i']
1055
            )
1056
        );
1057
        if ($link) {
1058
            $this->link($x, $y, $w, $h, $link);
1059
        }
1060
    }
1061
    
1062
    
1063
    public function getX()
1064
    {
1065
        //Get x position
1066
        return $this->x;
1067
    }
1068
    
1069
    
1070
    public function setX($x)
1071
    {
1072
        //Set x position
1073
        if ($x >= 0) {
1074
            $this->x = $x;
1075
        } else {
1076
            $this->x = $this->w+$x;
1077
        }
1078
    }
1079
    
1080
    
1081
    public function getY()
1082
    {
1083
        //Get y position
1084
        return $this->y;
1085
    }
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
    
1100
    public function setXY($x, $y)
1101
    {
1102
        //Set x and y positions
1103
        $this->setY($y);
1104
        $this->setX($x);
1105
    }
1106
    
1107
    public function getPdf()
1108
    {
1109
        if ($this->state < 3) {
1110
            $this->close();
1111
        }
1112
        return $this->buffer;
1113
    }
1114
    
1115 1
    public function output($name = '', $dest = '')
1116
    {
1117
        //Output PDF to some destination
1118 1
        if ($this->state < 3) {
1119 1
            $this->close();
1120
        }
1121 1
        $dest = strtoupper($dest);
1122 1
        if ($dest == '') {
1123
            if ($name == '') {
1124
                $name = 'doc.pdf';
1125
                $dest = 'I';
1126
            } else {
1127
                $dest = 'F';
1128
            }
1129
        }
1130 1
        switch ($dest) {
1131
            case 'I':
1132
                //Send to standard output
1133
                if (ob_get_length()) {
1134
                    $this->error('Some data has already been output, can\'t send PDF file');
1135
                }
1136
                if (php_sapi_name() != 'cli') {
1137
                    //We send to a browser
1138
                    header('Content-Type: application/pdf');
1139
                    if (headers_sent()) {
1140
                        $this->error('Some data has already been output, can\'t send PDF file');
1141
                    }
1142
                    header('Content-Length: '.strlen($this->buffer));
1143
                    header('Content-Disposition: inline; filename="'.$name.'"');
1144
                    header('Cache-Control: private, max-age=0, must-revalidate');
1145
                    header('Pragma: public');
1146
                    ini_set('zlib.output_compression', '0');
1147
                }
1148
                echo $this->buffer;
1149
                break;
1150
            case 'D':
1151
                //Download file
1152
                if (ob_get_length()) {
1153
                    $this->error('Some data has already been output, can\'t send PDF file');
1154
                }
1155
                header('Content-Type: application/x-download');
1156
                if (headers_sent()) {
1157
                    $this->error('Some data has already been output, can\'t send PDF file');
1158
                }
1159
                header('Content-Length: '.strlen($this->buffer));
1160
                header('Content-Disposition: attachment; filename="'.$name.'"');
1161
                header('Cache-Control: private, max-age=0, must-revalidate');
1162
                header('Pragma: public');
1163
                ini_set('zlib.output_compression', '0');
1164
                echo $this->buffer;
1165
                break;
1166
            case 'F':
1167
                //Save to local file
1168 1
                $f=fopen($name, 'wb');
1169 1
                if (!$f) {
1170
                    $this->error('Unable to create output file: '.$name);
1171
                }
1172 1
                fwrite($f, $this->buffer, strlen($this->buffer));
1173 1
                fclose($f);
1174 1
                break;
1175
            case 'S':
1176
                //Return as a string
1177
                return $this->buffer;
1178
            default:
1179
                $this->error('Incorrect output destination: '.$dest);
1180
        }
1181 1
        return '';
1182
    }
1183
    
1184
    
1185 1
    protected function dochecks()
1186
    {
1187
        //Check availability of %F
1188 1
        if (sprintf('%.1F', 1.0)!='1.0') {
1189
            $this->error('This version of PHP is not supported');
1190
        }
1191
        //Check mbstring overloading
1192 1
        if (ini_get('mbstring.func_overload') & 2) {
1193
            $this->error('mbstring overloading must be disabled');
1194
        }
1195 1
    }
1196
    
1197
    
1198 1
    protected function getpageformat($format)
1199
    {
1200 1
        $format=strtolower($format);
1201 1
        if (!isset($this->pageFormats[$format])) {
1202
            $this->error('Unknown page format: '.$format);
1203
        }
1204 1
        $a=$this->pageFormats[$format];
1205 1
        return array($a[0]/$this->k, $a[1]/$this->k);
1206
    }
1207
    
1208
    
1209 1
    protected function getFontPath()
1210
    {
1211 1
        if (!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font')) {
1212
            define('FPDF_FONTPATH', dirname(__FILE__).'/font/');
1213
        }
1214 1
        return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
1215
    }
1216
    
1217
    
1218 1
    protected function beginPage($orientation, $format)
1219
    {
1220 1
        $this->page++;
1221 1
        $this->pages[$this->page] = '';
1222 1
        $this->state = 2;
1223 1
        $this->x = $this->lMargin;
1224 1
        $this->y = $this->tMargin;
1225 1
        $this->fontFamily = '';
1226
        //Check page size
1227 1
        if ($orientation == '') {
1228
            $orientation = $this->defOrientation;
1229
        } else {
1230 1
            $orientation = strtoupper($orientation[0]);
1231
        }
1232 1
        if ($format == '') {
1233
            $format = $this->defPageFormat;
1234
        } else {
1235 1
            if (is_string($format)) {
1236 1
                $format=$this->getpageformat($format);
1237
            }
1238
        }
1239 1
        if ($orientation != $this->curOrientation
1240 1
            || $format[0]!=$this->curPageFormat[0]
1241 1
            || $format[1]!=$this->curPageFormat[1]
1242
        ) {
1243
            //New size
1244
            if ($orientation == 'P') {
1245
                $this->w = $format[0];
1246
                $this->h = $format[1];
1247
            } else {
1248
                $this->w = $format[1];
1249
                $this->h = $format[0];
1250
            }
1251
            $this->wPt = $this->w*$this->k;
1252
            $this->hPt = $this->h*$this->k;
1253
            $this->pageBreakTrigger = $this->h-$this->bMargin;
1254
            $this->curOrientation = $orientation;
1255
            $this->curPageFormat = $format;
1256
        }
1257 1
        if ($orientation != $this->defOrientation
1258 1
            || $format[0] != $this->defPageFormat[0]
1259 1
            || $format[1] != $this->defPageFormat[1]
1260
        ) {
1261
            $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...
1262
        }
1263 1
    }
1264
    
1265
    
1266 1
    protected function endPage()
1267
    {
1268 1
        $this->state = 1;
1269 1
    }
1270
    
1271
    
1272 1
    protected function escape($s)
1273
    {
1274
        //Escape special characters in strings
1275 1
        $s = str_replace('\\', '\\\\', $s);
1276 1
        $s = str_replace('(', '\\(', $s);
1277 1
        $s = str_replace(')', '\\)', $s);
1278 1
        $s = str_replace("\r", '\\r', $s);
1279 1
        return $s;
1280
    }
1281
    
1282
    
1283 1
    protected function textString($s)
1284
    {
1285
        //Format a text string
1286 1
        return '('.$this->escape($s).')';
1287
    }
1288
    
1289
    
1290
    protected function utf8Toutf16($s)
1291
    {
1292
        //Convert UTF-8 to UTF-16BE with BOM
1293
        $res = "\xFE\xFF";
1294
        $nb = strlen($s);
1295
        $i = 0;
1296
        while ($i < $nb) {
1297
            $c1 = ord($s[$i++]);
1298
            if ($c1 >= 224) {
1299
                //3-byte character
1300
                $c2 = ord($s[$i++]);
1301
                $c3 = ord($s[$i++]);
1302
                $res .= chr((($c1 & 0x0F)<<4) + (($c2 & 0x3C)>>2));
1303
                $res .= chr((($c2 & 0x03)<<6) + ($c3 & 0x3F));
1304
            } elseif ($c1 >= 192) {
1305
                //2-byte character
1306
                $c2 = ord($s[$i++]);
1307
                $res .= chr(($c1 & 0x1C)>>2);
1308
                $res .= chr((($c1 & 0x03)<<6) + ($c2 & 0x3F));
1309
            } else {
1310
                //Single-byte character
1311
                $res .= "\0".chr($c1);
1312
            }
1313
        }
1314
        return $res;
1315
    }
1316
    
1317
    
1318
    protected function doUnderLine($x, $y, $txt)
1319
    {
1320
        //Underline text
1321
        $up = $this->currentFont['up'];
1322
        $ut = $this->currentFont['ut'];
1323
        $w = $this->getStringWidth($txt)+$this->ws*substr_count($txt, ' ');
1324
        return sprintf(
1325
            '%.2F %.2F %.2F %.2F re f',
1326
            $x*$this->k,
1327
            ($this->h-($y-$up/1000*$this->fontSize))*$this->k,
1328
            $w*$this->k,
1329
            -$ut/1000*$this->fontSizePt
1330
        );
1331
    }
1332
    
1333
    
1334
    protected function parseJPG($file)
1335
    {
1336
        //Extract info from a JPEG file
1337
        $a = getImageSize($file);
1338
        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...
1339
            $this->error('Missing or incorrect image file: '.$file);
1340
        }
1341
        if ($a[2]!=2) {
1342
            $this->error('Not a JPEG file: '.$file);
1343
        }
1344
        if (!isset($a['channels']) || $a['channels'] == 3) {
1345
            $colspace = 'DeviceRGB';
1346
        } elseif ($a['channels'] == 4) {
1347
            $colspace = 'DeviceCMYK';
1348
        } else {
1349
            $colspace='DeviceGray';
1350
        }
1351
        $bpc = isset($a['bits']) ? $a['bits'] : 8;
1352
        //Read whole file
1353
        $f = fopen($file, 'rb');
1354
        $data = '';
1355
        while (!feof($f)) {
1356
            $data .= fread($f, 8192);
1357
        }
1358
        fclose($f);
1359
        return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data);
1360
    }
1361
    
1362
    
1363
    protected function parsePNG($file)
1364
    {
1365
        //Extract info from a PNG file
1366
        $f = fopen($file, 'rb');
1367
        if (!$f) {
1368
            $this->error('Can\'t open image file: '.$file);
1369
        }
1370
        //Check signature
1371
        if ($this->readstream($f, 8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
1372
            $this->error('Not a PNG file: '.$file);
1373
        }
1374
        //Read header chunk
1375
        $this->readstream($f, 4);
1376
        if ($this->readstream($f, 4)!='IHDR') {
1377
            $this->error('Incorrect PNG file: '.$file);
1378
        }
1379
        $w = $this->readint($f);
1380
        $h = $this->readint($f);
1381
        $bpc = ord($this->readstream($f, 1));
1382
        if ($bpc>8) {
1383
            $this->error('16-bit depth not supported: '.$file);
1384
        }
1385
        $ct = ord($this->readstream($f, 1));
1386
        if ($ct == 0) {
1387
            $colspace = 'DeviceGray';
1388
        } elseif ($ct == 2) {
1389
            $colspace = 'DeviceRGB';
1390
        } elseif ($ct == 3) {
1391
            $colspace = 'Indexed';
1392
        } else {
1393
            $this->error('Alpha channel not supported: '.$file);
1394
        }
1395
        if (ord($this->readstream($f, 1)) != 0) {
1396
            $this->error('Unknown compression method: '.$file);
1397
        }
1398
        if (ord($this->readstream($f, 1)) != 0) {
1399
            $this->error('Unknown filter method: '.$file);
1400
        }
1401
        if (ord($this->readstream($f, 1)) != 0) {
1402
            $this->error('Interlacing not supported: '.$file);
1403
        }
1404
        $this->readstream($f, 4);
1405
        $parms = '/DecodeParms <</Predictor 15 /Colors '
1406
            . ($ct==2 ? 3 : 1)
1407
            . ' /BitsPerComponent '
1408
            . $bpc
1409
            . ' /Columns '
1410
            . $w
1411
            . '>>';
1412
        //Scan chunks looking for palette, transparency and image data
1413
        $pal = '';
1414
        $trns = '';
1415
        $data = '';
1416
        do {
1417
            $n = $this->readint($f);
1418
            $type = $this->readstream($f, 4);
1419
            if ($type == 'PLTE') {
1420
                //Read palette
1421
                $pal = $this->readstream($f, $n);
1422
                $this->readstream($f, 4);
1423
            } elseif ($type == 'tRNS') {
1424
                //Read transparency info
1425
                $t = $this->readstream($f, $n);
1426
                if ($ct == 0) {
1427
                    $trns = array(ord(substr($t, 1, 1)));
1428
                } elseif ($ct == 2) {
1429
                    $trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1)));
1430
                } else {
1431
                    $pos = strpos($t, chr(0));
1432
                    if ($pos !== false) {
1433
                        $trns = array($pos);
1434
                    }
1435
                }
1436
                $this->readstream($f, 4);
1437
            } elseif ($type == 'IDAT') {
1438
                //Read image data block
1439
                $data .= $this->readstream($f, $n);
1440
                $this->readstream($f, 4);
1441
            } elseif ($type == 'IEND') {
1442
                break;
1443
            } else {
1444
                $this->readstream($f, $n+4);
1445
            }
1446
        } while ($n);
1447
        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...
1448
            $this->error('Missing palette in '.$file);
1449
        }
1450
        fclose($f);
1451
        return [
1452
            'w'=>$w,
1453
            'h'=>$h,
1454
            'cs'=>$colspace,
1455
            'bpc'=>$bpc,
1456
            'f'=>'FlateDecode',
1457
            'parms'=>$parms,
1458
            'pal'=>$pal,
1459
            'trns'=>$trns,
1460
            'data'=>$data
1461
        ];
1462
    }
1463
    
1464
    
1465
    protected function readstream($f, $n)
1466
    {
1467
        //Read n bytes from stream
1468
        $res='';
1469
        while ($n > 0 && !feof($f)) {
1470
            $s=fread($f, $n);
1471
            if ($s === false) {
1472
                $this->error('Error while reading stream');
1473
            }
1474
            $n -= strlen($s);
1475
            $res .= $s;
1476
        }
1477
        if ($n > 0) {
1478
            $this->error('Unexpected end of stream');
1479
        }
1480
        return $res;
1481
    }
1482
    
1483
    
1484
    protected function readint($f)
1485
    {
1486
        //Read a 4-byte integer from stream
1487
        $a = unpack('Ni', $this->readstream($f, 4));
1488
        return $a['i'];
1489
    }
1490
    
1491
    
1492
    protected function parseGIF($file)
1493
    {
1494
        //Extract info from a GIF file (via PNG conversion)
1495
        if (!function_exists('imagepng')) {
1496
            $this->error('GD extension is required for GIF support');
1497
        }
1498
        if (!function_exists('imagecreatefromgif')) {
1499
            $this->error('GD has no GIF read support');
1500
        }
1501
        $im = imagecreatefromgif($file);
1502
        if (!$im) {
1503
            $this->error('Missing or incorrect image file: '.$file);
1504
        }
1505
        imageinterlace($im, 0);
1506
        $tmp = tempnam('.', 'gif');
1507
        if (!$tmp) {
1508
            $this->error('Unable to create a temporary file');
1509
        }
1510
        if (!imagepng($im, $tmp)) {
1511
            $this->error('Error while saving to temporary file');
1512
        }
1513
        imagedestroy($im);
1514
        $info=$this->parsePNG($tmp);
1515
        unlink($tmp);
1516
        return $info;
1517
    }
1518
    
1519
    
1520 1
    protected function newObj()
1521
    {
1522
        //Begin a new object
1523 1
        $this->n++;
1524 1
        $this->offsets[$this->n] = strlen($this->buffer);
1525 1
        $this->out($this->n.' 0 obj');
1526 1
    }
1527
    
1528
    
1529 1
    protected function putStream($s)
1530
    {
1531 1
        $this->out('stream');
1532 1
        $this->out($s);
1533 1
        $this->out('endstream');
1534 1
    }
1535
    
1536
    
1537 1
    protected function out($s)
1538
    {
1539
        //Add a line to the document
1540 1
        if ($this->state == 2) {
1541 1
            $this->pages[$this->page].=$s."\n";
1542
        } else {
1543 1
            $this->buffer .= $s."\n";
1544
        }
1545 1
    }
1546
    
1547
    
1548 1
    protected function putPages()
1549
    {
1550 1
        $nb = $this->page;
1551 1
        if (!empty($this->aliasNbPages)) {
1552
            //Replace number of pages
1553 1
            for ($n=1; $n<=$nb; $n++) {
1554 1
                $this->pages[$n] = str_replace($this->aliasNbPages, $nb, $this->pages[$n]);
1555
            }
1556
        }
1557 1
        if ($this->defOrientation == 'P') {
1558 1
            $wPt = $this->defPageFormat[0]*$this->k;
1559 1
            $hPt = $this->defPageFormat[1]*$this->k;
1560
        } else {
1561
            $wPt = $this->defPageFormat[1]*$this->k;
1562
            $hPt = $this->defPageFormat[0]*$this->k;
1563
        }
1564 1
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1565 1
        for ($n=1; $n<=$nb; $n++) {
1566
            //Page
1567 1
            $this->newObj();
1568 1
            $this->out('<</Type /Page');
1569 1
            $this->out('/Parent 1 0 R');
1570 1
            if (isset($this->PageSizes[$n])) {
0 ignored issues
show
Bug introduced by
The property PageSizes does not seem to exist. Did you mean pageSizes?

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

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

Loading history...
1571
                $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...
1572
            }
1573 1
            $this->out('/Resources 2 0 R');
1574 1
            if (isset($this->PageLinks[$n])) {
1575
                //Links
1576
                $annots = '/Annots [';
1577
                foreach ($this->PageLinks[$n] as $pl) {
1578
                    $rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0]+$pl[2], $pl[1]-$pl[3]);
1579
                    $annots .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
1580
                    if (is_string($pl[4])) {
1581
                        $annots .= '/A <</S /URI /URI '.$this->textString($pl[4]).'>>>>';
1582
                    } else {
1583
                        $l = $this->links[$pl[4]];
1584
                        $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...
1585
                        $annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>', 1+2*$l[0], $h-$l[1]*$this->k);
1586
                    }
1587
                }
1588
                $this->out($annots.']');
1589
            }
1590 1
            $this->out('/Contents '.($this->n+1).' 0 R>>');
1591 1
            $this->out('endobj');
1592
            //Page content
1593 1
            $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
1594 1
            $this->newObj();
1595 1
            $this->out('<<'.$filter.'/Length '.strlen($p).'>>');
1596 1
            $this->putStream($p);
1597 1
            $this->out('endobj');
1598
        }
1599
        //Pages root
1600 1
        $this->offsets[1]=strlen($this->buffer);
1601 1
        $this->out('1 0 obj');
1602 1
        $this->out('<</Type /Pages');
1603 1
        $kids = '/Kids [';
1604 1
        for ($i=0; $i<$nb; $i++) {
1605 1
            $kids .= (3+2*$i).' 0 R ';
1606
        }
1607 1
        $this->out($kids.']');
1608 1
        $this->out('/Count '.$nb);
1609 1
        $this->out(sprintf('/MediaBox [0 0 %.2F %.2F]', $wPt, $hPt));
1610 1
        $this->out('>>');
1611 1
        $this->out('endobj');
1612 1
    }
1613
    
1614
    
1615 1
    protected function putFonts()
1616
    {
1617 1
        $nf = $this->n;
1618 1
        foreach ($this->diffs as $diff) {
1619
            //Encodings
1620
            $this->newObj();
1621
            $this->out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
1622
            $this->out('endobj');
1623
        }
1624 1
        foreach ($this->fontFiles as $file => $info) {
1625
            //Font file embedding
1626
            $this->newObj();
1627
            $this->fontFiles[$file]['n']=$this->n;
1628
            $font='';
1629
            $f = fopen($this->getFontPath().$file, 'rb', 1);
1630
            if (!$f) {
1631
                $this->error('Font file not found');
1632
            }
1633
            while (!feof($f)) {
1634
                $font.=fread($f, 8192);
1635
            }
1636
            fclose($f);
1637
            $compressed = (substr($file, -2)=='.z');
1638
            if (!$compressed && isset($info['length2'])) {
1639
                $header = (ord($font[0])==128);
1640
                if ($header) {
1641
                    //Strip first binary header
1642
                    $font = substr($font, 6);
1643
                }
1644
                if ($header && ord($font[$info['length1']]) == 128) {
1645
                    //Strip second binary header
1646
                    $font = substr($font, 0, $info['length1']).substr($font, $info['length1']+6);
1647
                }
1648
            }
1649
            $this->out('<</Length '.strlen($font));
1650
            if ($compressed) {
1651
                $this->out('/Filter /FlateDecode');
1652
            }
1653
            $this->out('/Length1 '.$info['length1']);
1654
            if (isset($info['length2'])) {
1655
                $this->out('/Length2 '.$info['length2'].' /Length3 0');
1656
            }
1657
            $this->out('>>');
1658
            $this->putStream($font);
1659
            $this->out('endobj');
1660
        }
1661 1
        foreach ($this->fonts as $k => $font) {
1662
            //Font objects
1663 1
            $this->fonts[$k]['n']=$this->n+1;
1664 1
            $type = $font['type'];
1665 1
            $name = $font['name'];
1666 1
            if ($type == 'core') {
1667
                //Standard font
1668 1
                $this->newObj();
1669 1
                $this->out('<</Type /Font');
1670 1
                $this->out('/BaseFont /'.$name);
1671 1
                $this->out('/Subtype /Type1');
1672 1
                if ($name != 'Symbol' && $name != 'ZapfDingbats') {
1673 1
                    $this->out('/Encoding /WinAnsiEncoding');
1674
                }
1675 1
                $this->out('>>');
1676 1
                $this->out('endobj');
1677
            } elseif ($type=='Type1' || $type=='TrueType') {
1678
                //Additional Type1 or TrueType font
1679
                $this->newObj();
1680
                $this->out('<</Type /Font');
1681
                $this->out('/BaseFont /'.$name);
1682
                $this->out('/Subtype /'.$type);
1683
                $this->out('/FirstChar 32 /LastChar 255');
1684
                $this->out('/Widths '.($this->n+1).' 0 R');
1685
                $this->out('/FontDescriptor '.($this->n+2).' 0 R');
1686
                if ($font['enc']) {
1687
                    if (isset($font['diff'])) {
1688
                        $this->out('/Encoding '.($nf+$font['diff']).' 0 R');
1689
                    } else {
1690
                        $this->out('/Encoding /WinAnsiEncoding');
1691
                    }
1692
                }
1693
                $this->out('>>');
1694
                $this->out('endobj');
1695
                //Widths
1696
                $this->newObj();
1697
                $cw =& $font['cw'];
1698
                $s = '[';
1699
                for ($i=32; $i<=255; $i++) {
1700
                    $s .= $cw[chr($i)].' ';
1701
                }
1702
                $this->out($s.']');
1703
                $this->out('endobj');
1704
                //Descriptor
1705
                $this->newObj();
1706
                $s='<</Type /FontDescriptor /FontName /'.$name;
1707
                foreach ($font['desc'] as $k => $v) {
1708
                    $s .= ' /'.$k.' '.$v;
1709
                }
1710
                $file=$font['file'];
1711
                if ($file) {
1712
                    $s .= ' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->fontFiles[$file]['n'].' 0 R';
1713
                }
1714
                $this->out($s.'>>');
1715
                $this->out('endobj');
1716
            } else {
1717
                //Allow for additional types
1718
                $mtd='_put'.strtolower($type);
1719
                if (!method_exists($this, $mtd)) {
1720
                    $this->error('Unsupported font type: '.$type);
1721
                }
1722 1
                $this->$mtd($font);
1723
            }
1724
        }
1725 1
    }
1726
    
1727
    
1728 1
    protected function putImages()
1729
    {
1730 1
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1731 1
        reset($this->images);
1732
       
1733 1
        foreach ($this->images as $file => $info) {
1734
            $this->newObj();
1735
            $this->images[$file]['n'] = $this->n;
1736
            $this->out('<</Type /XObject');
1737
            $this->out('/Subtype /Image');
1738
            $this->out('/Width '.$info['w']);
1739
            $this->out('/Height '.$info['h']);
1740
            if ($info['cs']=='Indexed') {
1741
                $this->out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
1742
            } else {
1743
                $this->out('/ColorSpace /'.$info['cs']);
1744
                if ($info['cs']=='DeviceCMYK') {
1745
                    $this->out('/Decode [1 0 1 0 1 0 1 0]');
1746
                }
1747
            }
1748
            $this->out('/BitsPerComponent '.$info['bpc']);
1749
            if (isset($info['f'])) {
1750
                $this->out('/Filter /'.$info['f']);
1751
            }
1752
            if (isset($info['parms'])) {
1753
                $this->out($info['parms']);
1754
            }
1755
            if (isset($info['trns']) && is_array($info['trns'])) {
1756
                $trns = '';
1757
                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...
1758
                    $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
1759
                }
1760
                $this->out('/Mask ['.$trns.']');
1761
            }
1762
            $this->out('/Length '.strlen($info['data']).'>>');
1763
            $this->putStream($info['data']);
1764
            unset($this->images[$file]['data']);
1765
            $this->out('endobj');
1766
            //Palette
1767
            if ($info['cs'] == 'Indexed') {
1768
                $this->newObj();
1769
                $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
1770
                $this->out('<<'.$filter.'/Length '.strlen($pal).'>>');
1771
                $this->putStream($pal);
1772
                $this->out('endobj');
1773
            }
1774
        }
1775 1
    }
1776
    
1777 1
    protected function putXobjectDict()
1778
    {
1779 1
        foreach ($this->images as $image) {
1780
            $this->out('/I'.$image['i'].' '.$image['n'].' 0 R');
1781
        }
1782 1
    }
1783
    
1784 1
    protected function putResourceDict()
1785
    {
1786 1
        $this->out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
1787 1
        $this->out('/Font <<');
1788 1
        foreach ($this->fonts as $font) {
1789 1
            $this->out('/F'.$font['i'].' '.$font['n'].' 0 R');
1790
        }
1791 1
        $this->out('>>');
1792 1
        $this->out('/XObject <<');
1793 1
        $this->putXobjectDict();
1794 1
        $this->out('>>');
1795 1
    }
1796
    
1797 1
    protected function putResources()
1798
    {
1799 1
        $this->putFonts();
1800 1
        $this->putImages();
1801
        //Resource dictionary
1802 1
        $this->offsets[2] = strlen($this->buffer);
1803 1
        $this->out('2 0 obj');
1804 1
        $this->out('<<');
1805 1
        $this->putResourceDict();
1806 1
        $this->out('>>');
1807 1
        $this->out('endobj');
1808 1
    }
1809
    
1810 1
    protected function putInfo()
1811
    {
1812 1
        $this->out('/Producer '.$this->textString('FPDF '. self::FPDF_VERSION));
1813 1
        if (!empty($this->title)) {
1814
            $this->out('/Title '.$this->textString($this->title));
1815
        }
1816 1
        if (!empty($this->subject)) {
1817
            $this->out('/Subject '.$this->textString($this->subject));
1818
        }
1819 1
        if (!empty($this->author)) {
1820
            $this->out('/Author '.$this->textString($this->author));
1821
        }
1822 1
        if (!empty($this->keywords)) {
1823
            $this->out('/Keywords '.$this->textString($this->keywords));
1824
        }
1825 1
        if (!empty($this->creator)) {
1826
            $this->out('/Creator '.$this->textString($this->creator));
1827
        }
1828 1
        $this->out('/CreationDate '.$this->textString('D:'.@date('YmdHis')));
1829 1
    }
1830
    
1831 1
    protected function putCatalog()
1832
    {
1833 1
        $this->out('/Type /Catalog');
1834 1
        $this->out('/Pages 1 0 R');
1835 1
        if ($this->zoomMode=='fullpage') {
1836
            $this->out('/OpenAction [3 0 R /Fit]');
1837 1
        } elseif ($this->zoomMode=='fullwidth') {
1838 1
            $this->out('/OpenAction [3 0 R /FitH null]');
1839
        } elseif ($this->zoomMode=='real') {
1840
            $this->out('/OpenAction [3 0 R /XYZ null null 1]');
1841
        } elseif (!is_string($this->zoomMode)) {
1842
            $this->out('/OpenAction [3 0 R /XYZ null null '.($this->zoomMode/100).']');
1843
        }
1844 1
        if ($this->layoutMode=='single') {
1845
            $this->out('/PageLayout /SinglePage');
1846 1
        } elseif ($this->layoutMode=='continuous') {
1847 1
            $this->out('/PageLayout /OneColumn');
1848
        } elseif ($this->layoutMode=='two') {
1849
            $this->out('/PageLayout /TwoColumnLeft');
1850
        }
1851 1
    }
1852
    
1853 1
    protected function putHeader()
1854
    {
1855 1
        $this->out('%PDF-'.$this->pdfVersion);
1856 1
    }
1857
    
1858 1
    protected function putTrailer()
1859
    {
1860 1
        $this->out('/Size '.($this->n+1));
1861 1
        $this->out('/Root '.$this->n.' 0 R');
1862 1
        $this->out('/Info '.($this->n-1).' 0 R');
1863 1
    }
1864
    
1865 1
    protected function endDoc()
1866
    {
1867 1
        $this->putHeader();
1868 1
        $this->putPages();
1869 1
        $this->putResources();
1870
        //Info
1871 1
        $this->newObj();
1872 1
        $this->out('<<');
1873 1
        $this->putInfo();
1874 1
        $this->out('>>');
1875 1
        $this->out('endobj');
1876
        //Catalog
1877 1
        $this->newObj();
1878 1
        $this->out('<<');
1879 1
        $this->putCatalog();
1880 1
        $this->out('>>');
1881 1
        $this->out('endobj');
1882
        //Cross-ref
1883 1
        $o=strlen($this->buffer);
1884 1
        $this->out('xref');
1885 1
        $this->out('0 '.($this->n+1));
1886 1
        $this->out('0000000000 65535 f ');
1887 1
        for ($i=1; $i<=$this->n; $i++) {
1888 1
            $this->out(sprintf('%010d 00000 n ', $this->offsets[$i]));
1889
        }
1890
        //Trailer
1891 1
        $this->out('trailer');
1892 1
        $this->out('<<');
1893 1
        $this->putTrailer();
1894 1
        $this->out('>>');
1895 1
        $this->out('startxref');
1896 1
        $this->out($o);
1897 1
        $this->out('%%EOF');
1898 1
        $this->state=3;
1899 1
    }
1900
}
1901