Completed
Push — master ( 189d26...420ed5 )
by Roberto
06:31 queued 03:46
created

Fpdf::addFont()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 58

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
nc 16
nop 3
dl 0
loc 58
ccs 0
cts 56
cp 0
crap 42
rs 8.2941
c 0
b 0
f 0

How to fix   Long Method   

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
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
    public function __construct($orientation = 'P', $unit = 'mm', $format = 'A4')
71
    {
72
        //Some checks
73
        $this->dochecks();
74
        //Initialization of properties
75
        $this->page = 0;
76
        $this->n = 2;
77
        $this->buffer = '';
78
        $this->pages = [];
79
        $this->pageSizes = [];
80
        $this->state = 0;
81
        $this->fonts = [];
82
        $this->fontFiles = [];
83
        $this->diffs = [];
84
        $this->images = [];
85
        $this->links = [];
86
        $this->inHeader = false;
87
        $this->inFooter = false;
88
        $this->lasth = 0;
89
        $this->fontFamily = '';
90
        $this->fontStyle = '';
91
        $this->fontSizePt = 12;
92
        $this->underline = false;
93
        $this->drawColor = '0 G';
94
        $this->fillColor = '0 g';
95
        $this->textColor = '0 g';
96
        $this->colorFlag = false;
97
        $this->ws = 0;
98
        //Standard fonts
99
        $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
        if ($unit == 'pt') {
117
            $this->k = 1;
118
        } elseif ($unit == 'mm') {
119
            $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
        $this->pageFormats = [
129
            'a3' => [841.89,1190.55],
130
            'a4' => [595.28,841.89],
131
            'a5' => [420.94,595.28],
132
            'letter' => [612,792],
133
            'legal' => [612,1008]
134
        ];
135
        if (is_string($format)) {
136
            $format = $this->getpageformat($format);
137
        }
138
        $this->defPageFormat = $format;
139
        $this->curPageFormat = $format;
140
        //Page orientation
141
        $orientation = strtolower($orientation);
142
        if ($orientation == 'p' || $orientation == 'portrait') {
143
            $this->defOrientation='P';
144
            $this->w = $this->defPageFormat[0];
145
            $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
        $this->curOrientation = $this->defOrientation;
154
        $this->wPt = $this->w*$this->k;
155
        $this->hPt = $this->h*$this->k;
156
        //Page margins (1 cm)
157
        $margin = 28.35/$this->k;
158
        $this->setMargins($margin, $margin);
159
        //Interior cell margin (1 mm)
160
        $this->cMargin = $margin/10;
161
        //Line width (0.2 mm)
162
        $this->lineWidth = .567/$this->k;
163
        //Automatic page break
164
        $this->setAutoPageBreak(true, 2*$margin);
165
        //Full width display mode
166
        $this->setDisplayMode('fullwidth');
167
        //Enable compression
168
        $this->setCompression(true);
169
        //Set default PDF version number
170
        $this->pdfVersion='1.3';
171
    }
172
    
173
    public function setMargins($left, $top, $right = null)
174
    {
175
        //Set left, top and right margins
176
        $this->lMargin = $left;
177
        $this->tMargin = $top;
178
        if ($right === null) {
179
            $right = $left;
180
        }
181
        $this->rMargin=$right;
182
    }
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
    public function setAutoPageBreak($auto, $margin = 0)
206
    {
207
        //Set auto page break mode and triggering margin
208
        $this->autoPageBreak = $auto;
209
        $this->bMargin = $margin;
210
        $this->pageBreakTrigger = $this->h-$margin;
211
    }
212
    
213
    public function setDisplayMode($zoom, $layout = 'continuous')
214
    {
215
        //Set display mode in viewer
216
        if ($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom)) {
217
            $this->zoomMode = $zoom;
218
        } else {
219
            $this->error('Incorrect zoom display mode: '.$zoom);
220
        }
221
        if ($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default') {
222
            $this->layoutMode = $layout;
223
        } else {
224
            $this->error('Incorrect layout display mode: '.$layout);
225
        }
226
    }
227
    
228
    public function setCompression($compress)
229
    {
230
        //Set page compression
231
        if (function_exists('gzcompress')) {
232
            $this->compress = $compress;
233
        } else {
234
            $this->compress = false;
235
        }
236
    }
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
    public function aliasNbPages($alias = '{nb}')
284
    {
285
        //Define an alias for total number of pages
286
        $this->aliasNbPages=$alias;
287
    }
288
    
289
    public function error($msg)
290
    {
291
        throw new Exception($msg);
292
    }
293
    
294
    public function open()
295
    {
296
        $this->state = 1;
297
    }
298
    
299
    public function close()
300
    {
301
        //Terminate document
302
        if ($this->state == 3) {
303
            return;
304
        }
305
        if ($this->page == 0) {
306
            $this->addPage();
307
        }
308
        //Page footer
309
        $this->inFooter = true;
310
        $this->footer();
311
        $this->inFooter = false;
312
        //Close page
313
        $this->endPage();
314
        //Close document
315
        $this->endDoc();
316
    }
317
    
318
    public function addPage($orientation = '', $format = '')
319
    {
320
        //Start a new page
321
        if ($this->state == 0) {
322
            $this->open();
323
        }
324
        $family = $this->fontFamily;
325
        $style = $this->fontStyle.($this->underline ? 'U' : '');
326
        $size = $this->fontSizePt;
327
        $lw = $this->lineWidth;
328
        $dc = $this->drawColor;
329
        $fc = $this->fillColor;
330
        $tc = $this->textColor;
331
        $cf = $this->colorFlag;
332
        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
        $this->beginPage($orientation, $format);
342
        //Set line cap style to square
343
        $this->out('2 J');
344
        //Set line width
345
        $this->lineWidth = $lw;
346
        $this->out(sprintf('%.2F w', $lw*$this->k));
347
        //Set font
348
        if ($family) {
349
            $this->setFont($family, $style, $size);
350
        }
351
        //Set colors
352
        $this->drawColor = $dc;
353
        if ($dc!='0 G') {
354
            $this->out($dc);
355
        }
356
        $this->fillColor = $fc;
357
        if ($fc != '0 g') {
358
            $this->out($fc);
359
        }
360
        $this->textColor = $tc;
361
        $this->colorFlag = $cf;
362
        //Page header
363
        $this->inHeader = true;
364
        $this->Header();
365
        $this->inHeader = false;
366
        //Restore line width
367
        if ($this->lineWidth != $lw) {
368
            $this->lineWidth = $lw;
369
            $this->out(sprintf('%.2F w', $lw*$this->k));
370
        }
371
        //Restore font
372
        if ($family) {
373
            $this->setFont($family, $style, $size);
374
        }
375
        //Restore colors
376
        if ($this->drawColor != $dc) {
377
            $this->drawColor = $dc;
378
            $this->out($dc);
379
        }
380
        if ($this->fillColor != $fc) {
381
            $this->fillColor = $fc;
382
            $this->out($fc);
383
        }
384
        $this->textColor = $tc;
385
        $this->colorFlag = $cf;
386
    }
387
    
388
    public function header()
389
    {
390
        //To be implemented in your own inherited class
391
    }
392
    
393
    public function footer()
394
    {
395
        //To be implemented in your own inherited class
396
    }
397
    
398
    public function pageNo()
399
    {
400
        //Get current page number
401
        return $this->page;
402
    }
403
    
404
    public function setDrawColor($r, $g = null, $b = null)
405
    {
406
        //Set color for all stroking operations
407
        if (($r==0 && $g==0 && $b==0) || $g===null) {
408
            $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
        if ($this->page > 0) {
413
            $this->out($this->drawColor);
414
        }
415
    }
416
    
417
    public function setFillColor($r, $g = null, $b = null)
418
    {
419
        //Set color for all filling operations
420
        if (($r==0 && $g==0 && $b==0) || $g===null) {
421
            $this->fillColor = sprintf('%.3F g', $r/255);
422
        } else {
423
            $this->fillColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255);
424
        }
425
        $this->colorFlag = ($this->fillColor != $this->textColor);
426
        if ($this->page > 0) {
427
            $this->out($this->fillColor);
428
        }
429
    }
430
    
431
    public function settextColor($r, $g = null, $b = null)
432
    {
433
        //Set color for text
434
        if (($r==0 && $g==0 && $b==0) || $g===null) {
435
            $this->textColor = sprintf('%.3F g', $r/255);
436
        } else {
437
            $this->textColor = sprintf('%.3F %.3F %.3F rg', $r/255, $g/255, $b/255);
438
        }
439
        $this->colorFlag = ($this->fillColor != $this->textColor);
440
    }
441
    
442
    public function getStringWidth($s)
443
    {
444
        //Get width of a string in the current font
445
        $s = (string)$s;
446
        $cw =& $this->currentFont['cw'];
447
        $w = 0;
448
        $l = strlen($s);
449
        for ($i=0; $i<$l; $i++) {
450
            $w += $cw[$s[$i]];
451
        }
452
        return $w*$this->fontSize/1000;
453
    }
454
    
455
    public function setLineWidth($width)
456
    {
457
        //Set line width
458
        $this->lineWidth = $width;
459
        if ($this->page > 0) {
460
            $this->out(sprintf('%.2F w', $width*$this->k));
461
        }
462
    }
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
    public function rect($x, $y, $w, $h, $style = '')
479
    {
480
        //Draw a rectangle
481
        if ($style == 'F') {
482
            $op = 'f';
483
        } elseif ($style == 'FD' || $style == 'DF') {
484
            $op = 'B';
485
        } else {
486
            $op = 'S';
487
        }
488
        $this->out(
489
            sprintf(
490
                '%.2F %.2F %.2F %.2F re %s',
491
                $x*$this->k,
492
                ($this->h-$y)*$this->k,
493
                $w*$this->k,
494
                -$h*$this->k,
495
                $op
496
            )
497
        );
498
    }
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] = ['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] = ['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
    public function setFont($family, $style = '', $size = 0)
560
    {
561
        //Select a font; size given in points
562
        global $fpdf_charwidths;
563
        $family = strtolower($family);
564
        if ($family == '') {
565
            $family = $this->fontFamily;
566
        }
567
        if ($family == 'arial') {
568
            $family = 'helvetica';
569
        } elseif ($family == 'symbol' || $family == 'zapfdingbats') {
570
            $style = '';
571
        }
572
        $style = strtoupper($style);
573
        if (strpos($style, 'U') !== false) {
574
            $this->underline = true;
575
            $style = str_replace('U', '', $style);
576
        } else {
577
            $this->underline = false;
578
        }
579
        if ($style == 'IB') {
580
            $style = 'BI';
581
        }
582
        if ($size == 0) {
583
            $size = $this->fontSizePt;
584
        }
585
        //Test if font is already selected
586
        if ($this->fontFamily==$family && $this->fontStyle==$style && $this->fontSizePt==$size) {
587
            return;
588
        }
589
        //Test if used for the first time
590
        $fontkey = $family.$style;
591
        if (!isset($this->fonts[$fontkey])) {
592
            //Check if one of the standard fonts
593
            if (isset($this->coreFonts[$fontkey])) {
594
                if (!isset($fpdf_charwidths[$fontkey])) {
595
                    //Load metric file
596
                    $file=$family;
597
                    if ($family=='times' || $family=='helvetica') {
598
                        $file .= strtolower($style);
599
                    }
600
                    include $this->getFontPath().$file.'.php';
601
                    if (!isset($fpdf_charwidths[$fontkey])) {
602
                        $this->error('Could not include font metric file');
603
                    }
604
                }
605
                $i = count($this->fonts)+1;
606
                $name = $this->coreFonts[$fontkey];
607
                $cw = $fpdf_charwidths[$fontkey];
608
                $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
        $this->fontFamily = $family;
615
        $this->fontStyle = $style;
616
        $this->fontSizePt = $size;
617
        $this->fontSize = $size/$this->k;
618
        $this->currentFont =& $this->fonts[$fontkey];
619
        if ($this->page > 0) {
620
            $this->out(sprintf('BT /F%d %.2F Tf ET', $this->currentFont['i'], $this->fontSizePt));
621
        }
622
    }
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] = [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] = [$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
    public function text($x, $y, $txt)
670
    {
671
        //Output a string
672
        $s = sprintf('BT %.2F %.2F Td (%s) Tj ET', $x*$this->k, ($this->h-$y)*$this->k, $this->escape($txt));
673
        if ($this->underline && $txt!='') {
674
            $s .= ' '.$this->doUnderLine($x, $y, $txt);
675
        }
676
        if ($this->colorFlag) {
677
            $s = 'q '.$this->textColor.' '.$s.' Q';
678
        }
679
        $this->out($s);
680
    }
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
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
    public function output($name = '', $dest = '')
1116
    {
1117
        //Output PDF to some destination
1118
        if ($this->state < 3) {
1119
            $this->close();
1120
        }
1121
        $dest = strtoupper($dest);
1122
        if ($dest == '') {
1123
            if ($name == '') {
1124
                $name = 'doc.pdf';
1125
                $dest = 'I';
1126
            } else {
1127
                $dest = 'F';
1128
            }
1129
        }
1130
        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
                $f=fopen($name, 'wb');
1169
                if (!$f) {
1170
                    $this->error('Unable to create output file: '.$name);
1171
                }
1172
                fwrite($f, $this->buffer, strlen($this->buffer));
1173
                fclose($f);
1174
                break;
1175
            case 'S':
1176
                //Return as a string
1177
                return $this->buffer;
1178
            default:
1179
                $this->error('Incorrect output destination: '.$dest);
1180
        }
1181
        return '';
1182
    }
1183
    
1184
    
1185
    protected function dochecks()
1186
    {
1187
        //Check availability of %F
1188
        if (sprintf('%.1F', 1.0)!='1.0') {
1189
            $this->error('This version of PHP is not supported');
1190
        }
1191
        //Check mbstring overloading
1192
        if (ini_get('mbstring.func_overload') & 2) {
1193
            $this->error('mbstring overloading must be disabled');
1194
        }
1195
    }
1196
    
1197
    
1198
    protected function getpageformat($format)
1199
    {
1200
        $format=strtolower($format);
1201
        if (!isset($this->pageFormats[$format])) {
1202
            $this->error('Unknown page format: '.$format);
1203
        }
1204
        $a=$this->pageFormats[$format];
1205
        return [$a[0]/$this->k, $a[1]/$this->k];
1206
    }
1207
    
1208
    
1209
    protected function getFontPath()
1210
    {
1211
        if (!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font')) {
1212
            define('FPDF_FONTPATH', dirname(__FILE__).'/font/');
1213
        }
1214
        return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : '';
1215
    }
1216
    
1217
    
1218
    protected function beginPage($orientation, $format)
1219
    {
1220
        $this->page++;
1221
        $this->pages[$this->page] = '';
1222
        $this->state = 2;
1223
        $this->x = $this->lMargin;
1224
        $this->y = $this->tMargin;
1225
        $this->fontFamily = '';
1226
        //Check page size
1227
        if ($orientation == '') {
1228
            $orientation = $this->defOrientation;
1229
        } else {
1230
            $orientation = strtoupper($orientation[0]);
1231
        }
1232
        if ($format == '') {
1233
            $format = $this->defPageFormat;
1234
        } else {
1235
            if (is_string($format)) {
1236
                $format=$this->getpageformat($format);
1237
            }
1238
        }
1239
        if ($orientation != $this->curOrientation
1240
            || $format[0]!=$this->curPageFormat[0]
1241
            || $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
        if ($orientation != $this->defOrientation
1258
            || $format[0] != $this->defPageFormat[0]
1259
            || $format[1] != $this->defPageFormat[1]
1260
        ) {
1261
            $this->PageSizes[$this->page] = [$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
    }
1264
    
1265
    
1266
    protected function endPage()
1267
    {
1268
        $this->state = 1;
1269
    }
1270
    
1271
    
1272
    protected function escape($s)
1273
    {
1274
        //Escape special characters in strings
1275
        $s = str_replace('\\', '\\\\', $s);
1276
        $s = str_replace('(', '\\(', $s);
1277
        $s = str_replace(')', '\\)', $s);
1278
        $s = str_replace("\r", '\\r', $s);
1279
        return $s;
1280
    }
1281
    
1282
    
1283
    protected function textString($s)
1284
    {
1285
        //Format a text string
1286
        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 ['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 = [ord(substr($t, 1, 1))];
1428
                } elseif ($ct == 2) {
1429
                    $trns = [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 = [$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
    protected function newObj()
1521
    {
1522
        //Begin a new object
1523
        $this->n++;
1524
        $this->offsets[$this->n] = strlen($this->buffer);
1525
        $this->out($this->n.' 0 obj');
1526
    }
1527
    
1528
    
1529
    protected function putStream($s)
1530
    {
1531
        $this->out('stream');
1532
        $this->out($s);
1533
        $this->out('endstream');
1534
    }
1535
    
1536
    
1537
    protected function out($s)
1538
    {
1539
        //Add a line to the document
1540
        if ($this->state == 2) {
1541
            $this->pages[$this->page].=$s."\n";
1542
        } else {
1543
            $this->buffer .= $s."\n";
1544
        }
1545
    }
1546
    
1547
    
1548
    protected function putPages()
1549
    {
1550
        $nb = $this->page;
1551
        if (!empty($this->aliasNbPages)) {
1552
            //Replace number of pages
1553
            for ($n=1; $n<=$nb; $n++) {
1554
                $this->pages[$n] = str_replace($this->aliasNbPages, $nb, $this->pages[$n]);
1555
            }
1556
        }
1557
        if ($this->defOrientation == 'P') {
1558
            $wPt = $this->defPageFormat[0]*$this->k;
1559
            $hPt = $this->defPageFormat[1]*$this->k;
1560
        } else {
1561
            $wPt = $this->defPageFormat[1]*$this->k;
1562
            $hPt = $this->defPageFormat[0]*$this->k;
1563
        }
1564
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1565
        for ($n=1; $n<=$nb; $n++) {
1566
            //Page
1567
            $this->newObj();
1568
            $this->out('<</Type /Page');
1569
            $this->out('/Parent 1 0 R');
1570
            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
            $this->out('/Resources 2 0 R');
1574
            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
            $this->out('/Contents '.($this->n+1).' 0 R>>');
1591
            $this->out('endobj');
1592
            //Page content
1593
            $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
1594
            $this->newObj();
1595
            $this->out('<<'.$filter.'/Length '.strlen($p).'>>');
1596
            $this->putStream($p);
1597
            $this->out('endobj');
1598
        }
1599
        //Pages root
1600
        $this->offsets[1]=strlen($this->buffer);
1601
        $this->out('1 0 obj');
1602
        $this->out('<</Type /Pages');
1603
        $kids = '/Kids [';
1604
        for ($i=0; $i<$nb; $i++) {
1605
            $kids .= (3+2*$i).' 0 R ';
1606
        }
1607
        $this->out($kids.']');
1608
        $this->out('/Count '.$nb);
1609
        $this->out(sprintf('/MediaBox [0 0 %.2F %.2F]', $wPt, $hPt));
1610
        $this->out('>>');
1611
        $this->out('endobj');
1612
    }
1613
    
1614
    
1615
    protected function putFonts()
1616
    {
1617
        $nf = $this->n;
1618
        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
        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
        foreach ($this->fonts as $k => $font) {
1662
            //Font objects
1663
            $this->fonts[$k]['n']=$this->n+1;
1664
            $type = $font['type'];
1665
            $name = $font['name'];
1666
            if ($type == 'core') {
1667
                //Standard font
1668
                $this->newObj();
1669
                $this->out('<</Type /Font');
1670
                $this->out('/BaseFont /'.$name);
1671
                $this->out('/Subtype /Type1');
1672
                if ($name != 'Symbol' && $name != 'ZapfDingbats') {
1673
                    $this->out('/Encoding /WinAnsiEncoding');
1674
                }
1675
                $this->out('>>');
1676
                $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
                $this->$mtd($font);
1723
            }
1724
        }
1725
    }
1726
    
1727
    
1728
    protected function putImages()
1729
    {
1730
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1731
        reset($this->images);
1732
       
1733
        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
    }
1776
    
1777
    protected function putXobjectDict()
1778
    {
1779
        foreach ($this->images as $image) {
1780
            $this->out('/I'.$image['i'].' '.$image['n'].' 0 R');
1781
        }
1782
    }
1783
    
1784
    protected function putResourceDict()
1785
    {
1786
        $this->out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
1787
        $this->out('/Font <<');
1788
        foreach ($this->fonts as $font) {
1789
            $this->out('/F'.$font['i'].' '.$font['n'].' 0 R');
1790
        }
1791
        $this->out('>>');
1792
        $this->out('/XObject <<');
1793
        $this->putXobjectDict();
1794
        $this->out('>>');
1795
    }
1796
    
1797
    protected function putResources()
1798
    {
1799
        $this->putFonts();
1800
        $this->putImages();
1801
        //Resource dictionary
1802
        $this->offsets[2] = strlen($this->buffer);
1803
        $this->out('2 0 obj');
1804
        $this->out('<<');
1805
        $this->putResourceDict();
1806
        $this->out('>>');
1807
        $this->out('endobj');
1808
    }
1809
    
1810
    protected function putInfo()
1811
    {
1812
        $this->out('/Producer '.$this->textString('FPDF '. self::FPDF_VERSION));
1813
        if (!empty($this->title)) {
1814
            $this->out('/Title '.$this->textString($this->title));
1815
        }
1816
        if (!empty($this->subject)) {
1817
            $this->out('/Subject '.$this->textString($this->subject));
1818
        }
1819
        if (!empty($this->author)) {
1820
            $this->out('/Author '.$this->textString($this->author));
1821
        }
1822
        if (!empty($this->keywords)) {
1823
            $this->out('/Keywords '.$this->textString($this->keywords));
1824
        }
1825
        if (!empty($this->creator)) {
1826
            $this->out('/Creator '.$this->textString($this->creator));
1827
        }
1828
        $this->out('/CreationDate '.$this->textString('D:'.@date('YmdHis')));
1829
    }
1830
    
1831
    protected function putCatalog()
1832
    {
1833
        $this->out('/Type /Catalog');
1834
        $this->out('/Pages 1 0 R');
1835
        if ($this->zoomMode=='fullpage') {
1836
            $this->out('/OpenAction [3 0 R /Fit]');
1837
        } elseif ($this->zoomMode=='fullwidth') {
1838
            $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
        if ($this->layoutMode=='single') {
1845
            $this->out('/PageLayout /SinglePage');
1846
        } elseif ($this->layoutMode=='continuous') {
1847
            $this->out('/PageLayout /OneColumn');
1848
        } elseif ($this->layoutMode=='two') {
1849
            $this->out('/PageLayout /TwoColumnLeft');
1850
        }
1851
    }
1852
    
1853
    protected function putHeader()
1854
    {
1855
        $this->out('%PDF-'.$this->pdfVersion);
1856
    }
1857
    
1858
    protected function putTrailer()
1859
    {
1860
        $this->out('/Size '.($this->n+1));
1861
        $this->out('/Root '.$this->n.' 0 R');
1862
        $this->out('/Info '.($this->n-1).' 0 R');
1863
    }
1864
    
1865
    protected function endDoc()
1866
    {
1867
        $this->putHeader();
1868
        $this->putPages();
1869
        $this->putResources();
1870
        //Info
1871
        $this->newObj();
1872
        $this->out('<<');
1873
        $this->putInfo();
1874
        $this->out('>>');
1875
        $this->out('endobj');
1876
        //Catalog
1877
        $this->newObj();
1878
        $this->out('<<');
1879
        $this->putCatalog();
1880
        $this->out('>>');
1881
        $this->out('endobj');
1882
        //Cross-ref
1883
        $o=strlen($this->buffer);
1884
        $this->out('xref');
1885
        $this->out('0 '.($this->n+1));
1886
        $this->out('0000000000 65535 f ');
1887
        for ($i=1; $i<=$this->n; $i++) {
1888
            $this->out(sprintf('%010d 00000 n ', $this->offsets[$i]));
1889
        }
1890
        //Trailer
1891
        $this->out('trailer');
1892
        $this->out('<<');
1893
        $this->putTrailer();
1894
        $this->out('>>');
1895
        $this->out('startxref');
1896
        $this->out($o);
1897
        $this->out('%%EOF');
1898
        $this->state=3;
1899
    }
1900
}
1901