Passed
Pull Request — master (#131)
by Tomas
12:38
created

Image::GetWidth()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
/**
4
 * JPGraph v4.0.3
5
 */
6
7
namespace Amenadiel\JpGraph\Image;
8
9
use Amenadiel\JpGraph\Text\LanguageConv;
10
use Amenadiel\JpGraph\Text\TTF;
11
use Amenadiel\JpGraph\Util;
12
use Amenadiel\JpGraph\Util\ErrMsgText;
13
14
// load fonts only once, and define a constant for them
15 1
define("GD_FF_FONT0", imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT0.gdf'));
16 1
define("GD_FF_FONT1", imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT1.gdf'));
17 1
define("GD_FF_FONT2", imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT2.gdf'));
18 1
define("GD_FF_FONT1_BOLD", imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT1-Bold.gdf'));
19 1
define("GD_FF_FONT2_BOLD", imageloadfont(dirname(dirname(__FILE__)) . '/fonts/FF_FONT2-Bold.gdf'));
20
21
/**
22
 * File:        GD_IMAGE.INC.PHP
23
 * // Description: PHP Graph Plotting library. Low level image drawing routines
24
 * // Created:     2001-01-08, refactored 2008-03-29
25
 * // Ver:         $Id: gd_image.inc.php 1922 2010-01-11 11:42:50Z ljp $
26
 * //
27
 * // Copyright (c) Asial Corporation. All rights reserved.
28
 */
29
30
/**
31
 * @class Image
32
 * // Description: The very coor image drawing class that encapsulates all
33
 * //              calls to the GD library
34
 * //              Note: The class used by the library is the decendant
35
 * //              class RotImage which extends the Image class with transparent
36
 * //              rotation.
37
 */
38
class Image
39
{
40
    public $img;
41
    public $rgb;
42
    public $img_format;
43
    public $ttf;
44
    public $line_style = LINESTYLE_SOLID;
45
    public $current_color;
46
    public $current_color_name;
47
    public $original_width  = 0;
48
    public $original_height = 0;
49
    public $plotwidth       = 0;
50
    public $plotheight      = 0;
51
52
    // for __get, __set
53
    private $_left_margin   = 30;
54
    private $_right_margin  = 30;
55
    private $_top_margin    = 20;
56
    private $_bottom_margin = 30;
57
    //private $_plotwidth=0,$_plotheight=0;
58
    private $_width       = 0;
59
    private $_height      = 0;
60
    private $_line_weight = 1;
61
62
    protected $expired           = true;
63
    protected $lastx             = 0;
64
    protected $lasty             = 0;
65
    protected $obs_list          = [];
66
    protected $font_size         = 12;
67
    protected $font_family       = FF_DEFAULT;
68
    protected $font_style        = FS_NORMAL;
69
    protected $font_file         = '';
70
    protected $text_halign       = 'left';
71
    protected $text_valign       = 'bottom';
72
    protected $use_anti_aliasing = false;
73
    protected $quality;
74
    protected $colorstack    = [];
75
    protected $colorstackidx = 0;
76
    protected $canvascolor   = 'white';
77
    protected $langconv;
78
    protected $iInterlace = false;
79
    protected $bbox_cache = []; // STore the last found tetx bounding box
80
    protected $ff_font0;
81
    protected $ff_font0_bold;
82
    protected $ff_font1;
83
    protected $ff_font1_bold;
84
    protected $ff_font2;
85
    protected $ff_font2_bold;
86
87
    /**
88
     * CONSTRUCTOR.
89
     *
90
     * @param mixed $aWidth
91
     * @param mixed $aHeight
92
     * @param mixed $aFormat
93
     * @param mixed $aSetAutoMargin
94
     */
95 21
    public function __construct($aWidth = 0, $aHeight = 0, $aFormat = DEFAULT_GFORMAT, $aSetAutoMargin = true)
96
    {
97 21
        $this->original_width  = $aWidth;
98 21
        $this->original_height = $aHeight;
99 21
        $this->CreateImgCanvas($aWidth, $aHeight);
100
101 21
        if ($aSetAutoMargin) {
102 21
            $this->SetAutoMargin();
103
        }
104
105 21
        if (!$this->SetImgFormat($aFormat)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->SetImgFormat($aFormat) of type null|true is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
106
            Util\JpGraphError::RaiseL(25081, $aFormat); //("JpGraph: Selected graphic format is either not supported or unknown [$aFormat]");
107
        }
108 21
        $this->ttf      = new TTF();
109 21
        $this->langconv = new LanguageConv();
110
111 21
        $this->ff_font0 =  GD_FF_FONT0;
112 21
        $this->ff_font1 =  GD_FF_FONT1;
113 21
        $this->ff_font2 =  GD_FF_FONT2;
114 21
        $this->ff_font1_bold =  GD_FF_FONT1_BOLD;
115 21
        $this->ff_font2_bold =  GD_FF_FONT2_BOLD;
116 21
    }
117
118
    // Enable interlacing in images
119
    public function SetInterlace($aFlg = true)
120
    {
121
        $this->iInterlace = $aFlg;
122
    }
123
124
    // Should we use anti-aliasing. Note: This really slows down graphics!
125 19
    public function SetAntiAliasing($aFlg = true)
126
    {
127 19
        $this->use_anti_aliasing = $aFlg;
128 19
        if (function_exists('imageantialias')) {
129 19
            imageantialias($this->img, $aFlg);
130
        } /*else {
131
    Util\JpGraphError::RaiseL(25128); //('The function imageantialias() is not available in your PHP installation. Use the GD version that comes with PHP and not the standalone version.')
132
    }*/
133 19
    }
134
135 6
    public function GetAntiAliasing()
136
    {
137 6
        return $this->use_anti_aliasing;
138
    }
139
140 21
    public function CreateRawCanvas($aWidth = 0, $aHeight = 0)
141
    {
142 21
        $aWidth *= SUPERSAMPLING_SCALE;
143 21
        $aHeight *= SUPERSAMPLING_SCALE;
144
145 21
        if ($aWidth <= 1 || $aHeight <= 1) {
146
            Util\JpGraphError::RaiseL(25082, $aWidth, $aHeight); //("Illegal sizes specified for width or height when creating an image, (width=$aWidth, height=$aHeight)");
147
        }
148
149 21
        $this->img = @imagecreatetruecolor($aWidth, $aHeight);
150 21
        if ($this->img === false) {
151
            Util\JpGraphError::RaiseL(25126);
152
            //die("Can't create truecolor image. Check that you really have GD2 library installed.");
153
        }
154 21
        $this->SetAlphaBlending();
155
156 21
        if ($this->iInterlace) {
157
            imageinterlace($this->img, 1);
158
        }
159 21
        if ($this->rgb != null) {
160 4
            $this->rgb->img = $this->img;
161
        } else {
162 21
            $this->rgb = new RGB($this->img);
163
        }
164 21
    }
165
166 1
    public function CloneCanvasH()
167
    {
168 1
        $oldimage = $this->img;
169 1
        $this->CreateRawCanvas($this->width, $this->height);
170 1
        imagecopy($this->img, $oldimage, 0, 0, 0, 0, $this->width, $this->height);
0 ignored issues
show
Bug introduced by
$this->height of type double is incompatible with the type integer expected by parameter $src_h of imagecopy(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

170
        imagecopy($this->img, $oldimage, 0, 0, 0, 0, $this->width, /** @scrutinizer ignore-type */ $this->height);
Loading history...
Bug introduced by
$this->width of type double is incompatible with the type integer expected by parameter $src_w of imagecopy(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

170
        imagecopy($this->img, $oldimage, 0, 0, 0, 0, /** @scrutinizer ignore-type */ $this->width, $this->height);
Loading history...
171
172 1
        return $oldimage;
173
    }
174
175 21
    public function CreateImgCanvas($aWidth = 0, $aHeight = 0)
176
    {
177 21
        $old = [$this->img, $this->width, $this->height];
178
179 21
        $aWidth  = round($aWidth);
180 21
        $aHeight = round($aHeight);
181
182 21
        $this->width  = $aWidth;
183 21
        $this->height = $aHeight;
184
185 21
        if ($aWidth == 0 || $aHeight == 0) {
186
            // We will set the final size later.
187
            // Note: The size must be specified before any other
188
            // img routines that stroke anything are called.
189
            $this->img = null;
190
            $this->rgb = null;
191
192
            return $old;
193
        }
194
195 21
        $this->CreateRawCanvas($aWidth, $aHeight);
196
        // Set canvas color (will also be the background color for a
197
        // a pallett image
198 21
        $this->SetColor($this->canvascolor);
199 21
        $this->FilledRectangle(0, 0, $this->width - 1, $this->height - 1);
200
201 21
        return $old;
202
    }
203
204 9
    public function CopyCanvasH($aToHdl, $aFromHdl, $aToX, $aToY, $aFromX, $aFromY, $aWidth, $aHeight, $aw = -1, $ah = -1)
205
    {
206 9
        if ($aw === -1) {
207 1
            $aw = $aWidth;
208 1
            $ah = $aHeight;
209 1
            $f  = 'imagecopyresized';
210
        } else {
211 9
            $f = 'imagecopyresampled';
212
        }
213 9
        $f($aToHdl, $aFromHdl, $aToX, $aToY, $aFromX, $aFromY, $aWidth, $aHeight, $aw, $ah);
214 9
    }
215
216 4
    public function Copy($fromImg, $toX, $toY, $fromX, $fromY, $toWidth, $toHeight, $fromWidth = -1, $fromHeight = -1)
217
    {
218 4
        $this->CopyCanvasH($this->img, $fromImg, $toX, $toY, $fromX, $fromY, $toWidth, $toHeight, $fromWidth, $fromHeight);
219 4
    }
220
221 5
    public function CopyMerge($fromImg, $toX, $toY, $fromX, $fromY, $toWidth, $toHeight, $fromWidth = -1, $fromHeight = -1, $aMix = 100)
222
    {
223 5
        if ($aMix == 100) {
224 3
            $this->CopyCanvasH(
225 3
                $this->img,
226 3
                $fromImg,
227 3
                $toX,
228 3
                $toY,
229 3
                $fromX,
230 3
                $fromY,
231 3
                $toWidth,
232 3
                $toHeight,
233 3
                $fromWidth,
234 3
                $fromHeight
235
            );
236
        } else {
237 2
            if (($fromWidth != -1 && ($fromWidth != $toWidth)) || ($fromHeight != -1 && ($fromHeight != $fromHeight))) {
238
                // Create a new canvas that will hold the re-scaled original from image
239 1
                if ($toWidth <= 1 || $toHeight <= 1) {
240
                    Util\JpGraphError::RaiseL(25083); //('Illegal image size when copying image. Size for copied to image is 1 pixel or less.');
241
                }
242
243 1
                $tmpimg = @imagecreatetruecolor($toWidth, $toHeight);
244
245 1
                if ($tmpimg < 1) {
246
                    Util\JpGraphError::RaiseL(25084); //('Failed to create temporary GD canvas. Out of memory ?');
247
                }
248 1
                $this->CopyCanvasH(
249 1
                    $tmpimg,
250 1
                    $fromImg,
251 1
                    0,
252 1
                    0,
253 1
                    0,
254 1
                    0,
255 1
                    $toWidth,
256 1
                    $toHeight,
257 1
                    $fromWidth,
258 1
                    $fromHeight
259
                );
260 1
                $fromImg = $tmpimg;
261
            }
262 2
            imagecopymerge($this->img, $fromImg, $toX, $toY, $fromX, $fromY, $toWidth, $toHeight, $aMix);
263
        }
264 5
    }
265
266 4
    public static function GetWidth($aImg)
267
    {
268 4
        return imagesx($aImg);
269
    }
270
271 4
    public static function GetHeight($aImg)
272
    {
273 4
        return imagesy($aImg);
274
    }
275
276 4
    public static function CreateFromString($aStr)
277
    {
278 4
        $img = imagecreatefromstring($aStr);
279 4
        if ($img === false) {
280
            Util\JpGraphError::RaiseL(25085);
281
            //('An image can not be created from the supplied string. It is either in a format not supported or the string is representing an corrupt image.');
282
        }
283
284 4
        return $img;
285
    }
286
287 1
    public function SetCanvasH($aHdl)
288
    {
289 1
        $this->img      = $aHdl;
290 1
        $this->rgb->img = $aHdl;
291 1
    }
292
293
    public function SetCanvasColor($aColor)
294
    {
295
        $this->canvascolor = $aColor;
296
    }
297
298 21
    public function SetAlphaBlending($aFlg = true)
299
    {
300 21
        imagealphablending($this->img, $aFlg);
301 21
    }
302
303 21
    public function SetAutoMargin()
304
    {
305 21
        $min_bm = 5;
306 21
        $lm     = min(40, $this->width / 7);
307 21
        $rm     = min(20, $this->width / 10);
308 21
        $tm     = max(5, $this->height / 7);
309 21
        $bm     = max($min_bm, $this->height / 6);
310 21
        $this->SetMargin($lm, $rm, $tm, $bm);
311 21
    }
312
313
    /**
314
     * PUBLIC METHODS.
315
     *
316
     * @param mixed $family
317
     * @param mixed $style
318
     * @param mixed $size
319
     */
320 21
    public function SetFont($family, $style = FS_NORMAL, $size = 10)
321
    {
322 21
        $this->font_family = $family;
323 21
        $this->font_style  = $style;
324 21
        $this->font_size   = $size * SUPERSAMPLING_SCALE;
325 21
        $this->font_file   = '';
326 21
        if (($this->font_family == FF_FONT1 || $this->font_family == FF_FONT2) && $this->font_style == FS_BOLD) {
327 12
            ++$this->font_family;
328
        }
329 21
        if ($this->font_family > FF_FONT2 + 1) {
330
            // A TTF font so get the font file
331
332
            // Check that this PHP has support for TTF fonts
333 21
            if (!function_exists('imagettfbbox')) {
334
                // use internal font when php is configured without '--with-ttf'
335
                $this->font_family = FF_FONT1;
336
            //  Util\JpGraphError::RaiseL(25087);//('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.');
337
            } else {
338 21
                $this->font_file = $this->ttf->File($this->font_family, $this->font_style);
339
            }
340
        }
341 21
    }
342
343
    // Get the specific height for a text string
344 21
    public function GetTextHeight($txt = '', $angle = 0)
345
    {
346 21
        $tmp = preg_split('/\n/', $txt);
347 21
        $n   = safe_count($tmp);
348 21
        $m   = 0;
349 21
        for ($i = 0; $i < $n; ++$i) {
350 21
            $m = max($m, strlen($tmp[$i]));
351
        }
352
353 21
        if ($this->font_family <= FF_FONT2 + 1) {
354 12
            if ($angle == 0) {
355 12
                $h = imagefontheight($this->font_family);
356 12
                if ($h === false) {
357
                    Util\JpGraphError::RaiseL(25088); //('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
358
                }
359
360 12
                return $n * $h;
361
            }
362
            $w = @imagefontwidth($this->font_family);
363
            if ($w === false) {
364
                Util\JpGraphError::RaiseL(25088); //('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
365
            }
366
367
            return $m * $w;
368
        }
369 21
        $bbox = $this->GetTTFBBox($txt, $angle);
370
371 21
        return $bbox[1] - $bbox[5] + 1;
372
    }
373
374
    // Estimate font height
375 21
    public function GetFontHeight($angle = 0)
376
    {
377 21
        $txt = 'XOMg';
378
379 21
        return $this->GetTextHeight($txt, $angle);
380
    }
381
382
    // Approximate font width with width of letter "O"
383
    public function GetFontWidth($angle = 0)
384
    {
385
        $txt = 'O';
386
387
        return $this->GetTextWidth($txt, $angle);
388
    }
389
390
    // Get actual width of text in absolute pixels. Note that the width is the
391
    // texts projected with onto the x-axis. Call with angle=0 to get the true
392
    // etxt width.
393 18
    public function GetTextWidth($txt, $angle = 0)
394
    {
395 18
        $tmp = preg_split('/\n/', $txt);
396 18
        $n   = safe_count($tmp);
397 18
        if ($this->font_family <= FF_FONT2 + 1) {
398 12
            $m = 0;
399 12
            for ($i = 0; $i < $n; ++$i) {
400 12
                $l = strlen($tmp[$i]);
401 12
                if ($l > $m) {
402 11
                    $m = $l;
403
                }
404
            }
405
406 12
            if ($angle == 0) {
407 12
                $w = @imagefontwidth($this->font_family);
408 12
                if ($w === false) {
409
                    Util\JpGraphError::RaiseL(25088); //('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
410
                }
411
412 12
                return $m * $w;
413
            }
414
            // 90 degrees internal so height becomes width
415
            $h = @imagefontheight($this->font_family);
416
            if ($h === false) {
417
                Util\JpGraphError::RaiseL(25089); //('You have a misconfigured GD font support. The call to imagefontheight() fails.');
418
            }
419
420
            return $n * $h;
421
        }
422
        // For TTF fonts we must walk through a lines and find the
423
        // widest one which we use as the width of the multi-line
424
        // paragraph
425 14
        $m = 0;
426 14
        for ($i = 0; $i < $n; ++$i) {
427 14
            $bbox = $this->GetTTFBBox($tmp[$i], $angle);
428 14
            $mm   = $bbox[2] - $bbox[0];
429 14
            if ($mm > $m) {
430 14
                $m = $mm;
431
            }
432
        }
433
434 14
        return $m;
435
    }
436
437
    // Draw text with a box around it
438
    public function StrokeBoxedText(
439
        $x,
440
        $y,
441
        $txt,
442
        $dir = 0,
443
        $fcolor = 'white',
444
        $bcolor = 'black',
445
        $shadowcolor = false,
446
        $paragraph_align = 'left',
447
        $xmarg = 6,
448
        $ymarg = 4,
449
        $cornerradius = 0,
450
        $dropwidth = 3
451
    ) {
452
        $oldx = $this->lastx;
453
        $oldy = $this->lasty;
454
455
        if (!is_numeric($dir)) {
456
            if ($dir == 'h') {
457
                $dir = 0;
458
            } elseif ($dir == 'v') {
459
                $dir = 90;
460
            } else {
461
                Util\JpGraphError::RaiseL(25090, $dir);
462
            }
463
            //(" Unknown direction specified in call to StrokeBoxedText() [$dir]");
464
        }
465
466
        if ($this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2 + 1) {
467
            $width  = $this->GetTextWidth($txt, $dir);
468
            $height = $this->GetTextHeight($txt, $dir);
469
        } else {
470
            $width  = $this->GetBBoxWidth($txt, $dir);
471
            $height = $this->GetBBoxHeight($txt, $dir);
472
        }
473
474
        $height += 2 * $ymarg;
475
        $width += 2 * $xmarg;
476
477
        if ($this->text_halign == 'right') {
478
            $x -= $width;
479
        } elseif ($this->text_halign == 'center') {
480
            $x -= $width / 2;
481
        }
482
483
        if ($this->text_valign == 'bottom') {
484
            $y -= $height;
485
        } elseif ($this->text_valign == 'center') {
486
            $y -= $height / 2;
487
        }
488
489
        $olda = $this->SetAngle(0);
0 ignored issues
show
introduced by
The method SetAngle() does not exist on Amenadiel\JpGraph\Image\Image. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

489
        /** @scrutinizer ignore-call */ 
490
        $olda = $this->SetAngle(0);
Loading history...
490
491
        if ($shadowcolor) {
492
            $this->PushColor($shadowcolor);
493
            $this->FilledRoundedRectangle(
494
                $x - $xmarg + $dropwidth,
495
                $y - $ymarg + $dropwidth,
496
                $x + $width + $dropwidth,
497
                $y + $height - $ymarg + $dropwidth,
498
                $cornerradius
499
            );
500
            $this->PopColor();
501
            $this->PushColor($fcolor);
502
            $this->FilledRoundedRectangle(
503
                $x - $xmarg,
504
                $y - $ymarg,
505
                $x + $width,
506
                $y + $height - $ymarg,
507
                $cornerradius
508
            );
509
            $this->PopColor();
510
            $this->PushColor($bcolor);
511
            $this->RoundedRectangle(
512
                $x - $xmarg,
513
                $y - $ymarg,
514
                $x + $width,
515
                $y + $height - $ymarg,
516
                $cornerradius
517
            );
518
            $this->PopColor();
519
        } else {
520
            if ($fcolor) {
521
                $oc = $this->current_color;
522
                $this->SetColor($fcolor);
523
                $this->FilledRoundedRectangle($x - $xmarg, $y - $ymarg, $x + $width, $y + $height - $ymarg, $cornerradius);
524
                $this->current_color = $oc;
525
            }
526
            if ($bcolor) {
527
                $oc = $this->current_color;
528
                $this->SetColor($bcolor);
529
                $this->RoundedRectangle($x - $xmarg, $y - $ymarg, $x + $width, $y + $height - $ymarg, $cornerradius);
530
                $this->current_color = $oc;
531
            }
532
        }
533
534
        $h = $this->text_halign;
535
        $v = $this->text_valign;
536
        $this->SetTextAlign('left', 'top');
537
538
        $debug = false;
539
        $this->StrokeText($x, $y, $txt, $dir, $paragraph_align, $debug);
540
541
        $bb = [$x - $xmarg, $y + $height - $ymarg, $x + $width, $y + $height - $ymarg,
542
            $x + $width, $y - $ymarg, $x - $xmarg, $y - $ymarg, ];
543
        $this->SetTextAlign($h, $v);
544
545
        $this->SetAngle($olda);
546
        $this->lastx = $oldx;
547
        $this->lasty = $oldy;
548
549
        return $bb;
550
    }
551
552
    // Draw text with a box around it. This time the box will be rotated
553
    // with the text. The previous method will just make a larger enough non-rotated
554
    // box to hold the text inside.
555
    public function StrokeBoxedText2(
556
        $x,
557
        $y,
558
        $txt,
559
        $dir = 0,
560
        $fcolor = 'white',
561
        $bcolor = 'black',
562
        $shadowcolor = false,
563
        $paragraph_align = 'left',
564
        $xmarg = 6,
565
        $ymarg = 4,
566
        $cornerradius = 0,
567
        $dropwidth = 3
568
    ) {
569
        // This version of boxed text will stroke a rotated box round the text
570
        // thta will follow the angle of the text.
571
        // This has two implications:
572
        // 1) This methos will only support TTF fonts
573
        // 2) The only two alignment that makes sense are centered or baselined
574
575
        if ($this->font_family <= FF_FONT2 + 1) {
576
            Util\JpGraphError::RaiseL(25131); //StrokeBoxedText2() Only support TTF fonts and not built in bitmap fonts
577
        }
578
579
        $oldx = $this->lastx;
580
        $oldy = $this->lasty;
581
        $dir  = $this->NormAngle($dir);
582
583
        if (!is_numeric($dir)) {
584
            if ($dir == 'h') {
585
                $dir = 0;
586
            } elseif ($dir == 'v') {
587
                $dir = 90;
588
            } else {
589
                Util\JpGraphError::RaiseL(25090, $dir);
590
            }
591
            //(" Unknown direction specified in call to StrokeBoxedText() [$dir]");
592
        }
593
594
        $width       = $this->GetTextWidth($txt, 0) + 2 * $xmarg;
595
        $height      = $this->GetTextHeight($txt, 0) + 2 * $ymarg;
596
        $rect_width  = $this->GetBBoxWidth($txt, $dir);
597
        $rect_height = $this->GetBBoxHeight($txt, $dir);
598
599
        $baseline_offset = $this->bbox_cache[1] - 1;
0 ignored issues
show
Unused Code introduced by
The assignment to $baseline_offset is dead and can be removed.
Loading history...
600
601
        if ($this->text_halign == 'center') {
602
            if ($dir >= 0 && $dir <= 90) {
603
                $x -= $rect_width / 2;
604
                $x += sin($dir * M_PI / 180) * $height;
605
                $y += $rect_height / 2;
606
            } elseif ($dir >= 270 && $dir <= 360) {
607
                $x -= $rect_width / 2;
608
                $y -= $rect_height / 2;
609
                $y += cos($dir * M_PI / 180) * $height;
610
            } elseif ($dir >= 90 && $dir <= 180) {
611
                $x += $rect_width / 2;
612
                $y += $rect_height / 2;
613
                $y += cos($dir * M_PI / 180) * $height;
614
            } else {
615
                // $dir > 180 &&  $dir < 270
616
                $x += $rect_width / 2;
617
                $x += sin($dir * M_PI / 180) * $height;
618
                $y -= $rect_height / 2;
619
            }
620
        }
621
622
        // Rotate the box around this point
623
        $this->SetCenter($x, $y);
0 ignored issues
show
introduced by
The method SetCenter() does not exist on Amenadiel\JpGraph\Image\Image. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

623
        $this->/** @scrutinizer ignore-call */ 
624
               SetCenter($x, $y);
Loading history...
624
        $olda = $this->SetAngle(-$dir);
625
626
        // We need to use adjusted coordinats for the box to be able
627
        // to draw the box below the baseline. This cannot be done before since
628
        // the rotating point must be the original x,y since that is arounbf the
629
        // point where the text will rotate and we cannot change this since
630
        // that is where the GD/GreeType will rotate the text
631
632
        // For smaller <14pt font we need to do some additional
633
        // adjustments to make it look good
634
        if ($this->font_size < 14) {
635
            $x -= 2;
636
            $y += 2;
637
        }
638
        //  $y += $baseline_offset;
639
640
        if ($shadowcolor) {
641
            $this->PushColor($shadowcolor);
642
            $this->FilledRectangle(
643
                $x - $xmarg + $dropwidth,
644
                $y + $ymarg + $dropwidth - $height,
645
                $x + $width + $dropwidth,
646
                $y + $ymarg + $dropwidth
647
            );
648
            //$cornerradius);
649
            $this->PopColor();
650
            $this->PushColor($fcolor);
651
            $this->FilledRectangle(
652
                $x - $xmarg,
653
                $y + $ymarg - $height,
654
                $x + $width,
655
                $y + $ymarg
656
            );
657
            //$cornerradius);
658
            $this->PopColor();
659
            $this->PushColor($bcolor);
660
            $this->Rectangle(
661
                $x - $xmarg,
662
                $y + $ymarg - $height,
663
                $x + $width,
664
                $y + $ymarg
665
            );
666
            //$cornerradius);
667
            $this->PopColor();
668
        } else {
669
            if ($fcolor) {
670
                $oc = $this->current_color;
671
                $this->SetColor($fcolor);
672
                $this->FilledRectangle($x - $xmarg, $y + $ymarg - $height, $x + $width, $y + $ymarg); //,$cornerradius);
673
                $this->current_color = $oc;
674
            }
675
            if ($bcolor) {
676
                $oc = $this->current_color;
677
                $this->SetColor($bcolor);
678
                $this->Rectangle($x - $xmarg, $y + $ymarg - $height, $x + $width, $y + $ymarg); //,$cornerradius);
679
                $this->current_color = $oc;
680
            }
681
        }
682
683
        if ($this->font_size < 14) {
684
            $x += 2;
685
            $y -= 2;
686
        }
687
688
        // Restore the original y before we stroke the text
689
        // $y -= $baseline_offset;
690
691
        $this->SetCenter(0, 0);
692
        $this->SetAngle($olda);
693
694
        $h = $this->text_halign;
695
        $v = $this->text_valign;
696
        if ($this->text_halign == 'center') {
697
            $this->SetTextAlign('center', 'basepoint');
698
        } else {
699
            $this->SetTextAlign('basepoint', 'basepoint');
700
        }
701
702
        $debug = false;
703
        $this->StrokeText($x, $y, $txt, $dir, $paragraph_align, $debug);
704
705
        $bb = [$x - $xmarg, $y + $height - $ymarg,
706
            $x + $width, $y + $height - $ymarg,
707
            $x + $width, $y - $ymarg,
708
            $x - $xmarg, $y - $ymarg, ];
709
710
        $this->SetTextAlign($h, $v);
711
        $this->SetAngle($olda);
712
713
        $this->lastx = $oldx;
714
        $this->lasty = $oldy;
715
716
        return $bb;
717
    }
718
719
    // Set text alignment
720 21
    public function SetTextAlign($halign, $valign = 'bottom')
721
    {
722 21
        $this->text_halign = $halign;
723 21
        $this->text_valign = $valign;
724 21
    }
725
726 12
    public function _StrokeBuiltinFont($x, $y, $txt, $dir, $paragraph_align, &$aBoundingBox, $aDebug = false)
727
    {
728 12
        if (is_numeric($dir) && $dir != 90 && $dir != 0) {
729
            Util\JpGraphError::RaiseL(25091);
730
        }
731
        //(" Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead.");
732
733 12
        $h  = $this->GetTextHeight($txt);
734 12
        $fh = $this->GetFontHeight();
735 12
        $w  = $this->GetTextWidth($txt);
736
737 12
        if ($this->text_halign == 'right') {
738 6
            $x -= $dir == 0 ? $w : $h;
739 12
        } elseif ($this->text_halign == 'center') {
740
            // For center we subtract 1 pixel since this makes the middle
741
            // be prefectly in the middle
742 11
            $x -= $dir == 0 ? $w / 2 - 1 : $h / 2;
743
        }
744 12
        if ($this->text_valign == 'top') {
745 10
            $y += $dir == 0 ? $h : $w;
746 9
        } elseif ($this->text_valign == 'center') {
747 7
            $y += $dir == 0 ? $h / 2 : $w / 2;
748
        }
749
750 12
        $use_font = $this->font_family;
751
752 12
        if ($dir == 90) {
753 4
            imagestringup($this->img, $use_font, $x, $y, $txt, $this->current_color);
754 4
            $aBoundingBox = [round($x), round($y), round($x), round($y - $w), round($x + $h), round($y - $w), round($x + $h), round($y)];
755 4
            if ($aDebug) {
756
                // Draw bounding box
757
                $this->PushColor('green');
758
                $this->Polygon($aBoundingBox, true);
759 4
                $this->PopColor();
760
            }
761
        } else {
762 12
            if (preg_match('/\n/', $txt)) {
763 2
                $tmp = preg_split('/\n/', $txt);
764 2
                for ($i = 0; $i < safe_count($tmp); ++$i) {
765 2
                    $w1 = $this->GetTextWidth($tmp[$i]);
766 2
                    if ($paragraph_align == 'left') {
767 1
                        imagestring($this->img, $use_font, $x, $y - $h + 1 + $i * $fh, $tmp[$i], $this->current_color);
768 1
                    } elseif ($paragraph_align == 'right') {
769
                        imagestring($this->img, $use_font, $x + ($w - $w1), $y - $h + 1 + $i * $fh, $tmp[$i], $this->current_color);
770
                    } else {
771 1
                        imagestring($this->img, $use_font, $x + $w / 2 - $w1 / 2, $y - $h + 1 + $i * $fh, $tmp[$i], $this->current_color);
772
                    }
773
                }
774
            } else {
775
                //Put the text
776 11
                imagestring($this->img, $use_font, $x, $y - $h + 1, $txt, $this->current_color);
777
            }
778 12
            if ($aDebug) {
779
                // Draw the bounding rectangle and the bounding box
780
                $p1 = [round($x), round($y), round($x), round($y - $h), round($x + $w), round($y - $h), round($x + $w), round($y)];
781
782
                // Draw bounding box
783
                $this->PushColor('green');
784
                $this->Polygon($p1, true);
785
                $this->PopColor();
786
            }
787 12
            $aBoundingBox = [round($x), round($y), round($x), round($y - $h), round($x + $w), round($y - $h), round($x + $w), round($y)];
788
        }
789 12
    }
790
791 21
    public function AddTxtCR($aTxt)
792
    {
793
        // If the user has just specified a '\n'
794
        // instead of '\n\t' we have to add '\r' since
795
        // the width will be too muchy otherwise since when
796
        // we print we stroke the individually lines by hand.
797 21
        $e = explode("\n", $aTxt);
798 21
        $n = safe_count($e);
799 21
        for ($i = 0; $i < $n; ++$i) {
800 21
            $e[$i] = str_replace("\r", '', $e[$i]);
801
        }
802
803 21
        return implode("\n\r", $e);
804
    }
805
806 21
    public function NormAngle($a)
807
    {
808
        // Normalize angle in degrees
809
        // Normalize angle to be between 0-360
810 21
        while ($a > 360) {
811
            $a -= 360;
812
        }
813
814 21
        while ($a < -360) {
815
            $a += 360;
816
        }
817
818 21
        if ($a < 0) {
819
            $a = 360 + $a;
820
        }
821
822 21
        return $a;
823
    }
824
825 21
    public function imagettfbbox_fixed($size, $angle, $fontfile, $text)
826
    {
827 21
        if (!USE_LIBRARY_IMAGETTFBBOX) {
828
            $bbox = @imagettfbbox($size, $angle, $fontfile, $text);
829
            if ($bbox === false) {
830
                Util\JpGraphError::RaiseL(25092, $this->font_file);
831
                //("There is either a configuration problem with TrueType or a problem reading font file (".$this->font_file."). Make sure file exists and is in a readable place for the HTTP process. (If 'basedir' restriction is enabled in PHP then the font file must be located in the document root.). It might also be a wrongly installed FreeType library. Try uppgrading to at least FreeType 2.1.13 and recompile GD with the correct setup so it can find the new FT library.");
832
            }
833
            $this->bbox_cache = $bbox;
834
835
            return $bbox;
836
        }
837
838
        // The built in imagettfbbox is buggy for angles != 0 so
839
        // we calculate this manually by getting the bounding box at
840
        // angle = 0 and then rotate the bounding box manually
841 21
        $bbox = @imagettfbbox($size, 0, $fontfile, $text);
842 21
        if ($bbox === false && !is_readable($this->font_file)) {
843
            Util\JpGraphError::RaiseL(25092, $this->font_file);
844
            //("There is either a configuration problem with TrueType or a problem reading font file (".$this->font_file."). Make sure file exists and is in a readable place for the HTTP process. (If 'basedir' restriction is enabled in PHP then the font file must be located in the document root.). It might also be a wrongly installed FreeType library. Try uppgrading to at least FreeType 2.1.13 and recompile GD with the correct setup so it can find the new FT library.");
845
        }
846
847 21
        $angle = $this->NormAngle($angle);
848
849 21
        $a   = $angle * M_PI / 180;
850 21
        $ca  = cos($a);
851 21
        $sa  = sin($a);
852 21
        $ret = [];
853
854
        // We always add 1 pixel to the left since the left edge of the bounding
855
        // box is sometimes coinciding with the first pixel of the text
856
        //$bbox[0] -= 1;
857
        //$bbox[6] -= 1;
858
859
        // For roatated text we need to add extra width for rotated
860
        // text since the kerning and stroking of the TTF is not the same as for
861
        // text at a 0 degree angle
862
863 21
        if ($angle > 0.001 && abs($angle - 360) > 0.001) {
864 18
            $h = abs($bbox[7] - $bbox[1]);
865 18
            $w = abs($bbox[2] - $bbox[0]);
866
867 18
            $bbox[0] -= 2;
868 18
            $bbox[6] -= 2;
869
            // The width is underestimated so compensate for that
870 18
            $bbox[2] += round($w * 0.06);
871 18
            $bbox[4] += round($w * 0.06);
872
873
            // and we also need to compensate with increased height
874 18
            $bbox[5] -= round($h * 0.1);
875 18
            $bbox[7] -= round($h * 0.1);
876
877 18
            if ($angle > 90) {
878
                // For angles > 90 we also need to extend the height further down
879
                // by the baseline since that is also one more problem
880
                $bbox[1] += round($h * 0.15);
881
                $bbox[3] += round($h * 0.15);
882
883
                // and also make it slighty less height
884
                $bbox[7] += round($h * 0.05);
885
                $bbox[5] += round($h * 0.05);
886
887
                // And we need to move the box slightly top the rright (from a tetx perspective)
888
                $bbox[0] += round($w * 0.02);
889
                $bbox[6] += round($w * 0.02);
890
891
                if ($angle > 180) {
892
                    // And we need to move the box slightly to the left (from a text perspective)
893
                    $bbox[0] -= round($w * 0.02);
894
                    $bbox[6] -= round($w * 0.02);
895
                    $bbox[2] -= round($w * 0.02);
896
                    $bbox[4] -= round($w * 0.02);
897
                }
898
            }
899 18
            for ($i = 0; $i < 7; $i += 2) {
900 18
                $ret[$i]     = round($bbox[$i] * $ca + $bbox[$i + 1] * $sa);
901 18
                $ret[$i + 1] = round($bbox[$i + 1] * $ca - $bbox[$i] * $sa);
902
            }
903 18
            $this->bbox_cache = $ret;
904
905 18
            return $ret;
906
        }
907 21
        $this->bbox_cache = $bbox;
908
909 21
        return $bbox;
910
    }
911
912
    // Deprecated
913 21
    public function GetTTFBBox($aTxt, $aAngle = 0)
914
    {
915 21
        $bbox = $this->imagettfbbox_fixed($this->font_size, $aAngle, $this->font_file, $aTxt);
916
917 21
        return $bbox;
918
    }
919
920 21
    public function GetBBoxTTF($aTxt, $aAngle = 0)
921
    {
922
        // Normalize the bounding box to become a minimum
923
        // enscribing rectangle
924
925 21
        $aTxt = $this->AddTxtCR($aTxt);
926
927 21
        if (!is_readable($this->font_file)) {
928
            Util\JpGraphError::RaiseL(25093, $this->font_file);
929
            //('Can not read font file ('.$this->font_file.') in call to Image::GetBBoxTTF. Please make sure that you have set a font before calling this method and that the font is installed in the TTF directory.');
930
        }
931 21
        $bbox = $this->imagettfbbox_fixed($this->font_size, $aAngle, $this->font_file, $aTxt);
932
933 21
        if ($aAngle == 0) {
934 21
            return $bbox;
935
        }
936
937 18
        if ($aAngle >= 0) {
938 18
            if ($aAngle <= 90) {
939
                //<=0
940 18
                $bbox = [$bbox[6], $bbox[1], $bbox[2], $bbox[1],
941 18
                    $bbox[2], $bbox[5], $bbox[6], $bbox[5], ];
942
            } elseif ($aAngle <= 180) {
943
                //<= 2
944
                $bbox = [$bbox[4], $bbox[7], $bbox[0], $bbox[7],
945
                    $bbox[0], $bbox[3], $bbox[4], $bbox[3], ];
946
            } elseif ($aAngle <= 270) {
947
                //<= 3
948
                $bbox = [$bbox[2], $bbox[5], $bbox[6], $bbox[5],
949
                    $bbox[6], $bbox[1], $bbox[2], $bbox[1], ];
950
            } else {
951
                $bbox = [$bbox[0], $bbox[3], $bbox[4], $bbox[3],
952 18
                    $bbox[4], $bbox[7], $bbox[0], $bbox[7], ];
953
            }
954
        } elseif ($aAngle < 0) {
955
            if ($aAngle <= -270) {
956
                // <= -3
957
                $bbox = [$bbox[6], $bbox[1], $bbox[2], $bbox[1],
958
                    $bbox[2], $bbox[5], $bbox[6], $bbox[5], ];
959
            } elseif ($aAngle <= -180) {
960
                // <= -2
961
                $bbox = [$bbox[0], $bbox[3], $bbox[4], $bbox[3],
962
                    $bbox[4], $bbox[7], $bbox[0], $bbox[7], ];
963
            } elseif ($aAngle <= -90) {
964
                // <= -1
965
                $bbox = [$bbox[2], $bbox[5], $bbox[6], $bbox[5],
966
                    $bbox[6], $bbox[1], $bbox[2], $bbox[1], ];
967
            } else {
968
                $bbox = [$bbox[0], $bbox[3], $bbox[4], $bbox[3],
969
                    $bbox[4], $bbox[7], $bbox[0], $bbox[7], ];
970
            }
971
        }
972
973 18
        return $bbox;
974
    }
975
976 21
    public function GetBBoxHeight($aTxt, $aAngle = 0)
977
    {
978 21
        $box = $this->GetBBoxTTF($aTxt, $aAngle);
979
980 21
        return abs($box[7] - $box[1]);
981
    }
982
983 21
    public function GetBBoxWidth($aTxt, $aAngle = 0)
984
    {
985 21
        $box = $this->GetBBoxTTF($aTxt, $aAngle);
986
987 21
        return $box[2] - $box[0] + 1;
988
    }
989
990 21
    public function _StrokeTTF($x, $y, $txt, $dir, $paragraph_align, &$aBoundingBox, $debug = false)
991
    {
992
        // Setup default inter line margin for paragraphs to be
993
        // 3% of the font height.
994 21
        $ConstLineSpacing = 0.03;
995
996
        // Remember the anchor point before adjustment
997 21
        if ($debug) {
998
            $ox = $x;
999
            $oy = $y;
1000
        }
1001
1002 21
        if (!preg_match('/\n/', $txt) || ($dir > 0 && preg_match('/\n/', $txt))) {
1003
            // Format a single line
1004
1005 21
            $txt    = $this->AddTxtCR($txt);
1006 21
            $bbox   = $this->GetBBoxTTF($txt, $dir);
1007 21
            $width  = $this->GetBBoxWidth($txt, $dir);
1008 21
            $height = $this->GetBBoxHeight($txt, $dir);
1009
1010
            // The special alignment "basepoint" is mostly used internally
1011
            // in the library. This will put the anchor position at the left
1012
            // basepoint of the tetx. This is the default anchor point for
1013
            // TTF text.
1014
1015 21
            if ($this->text_valign != 'basepoint') {
1016
                // Align x,y ot lower left corner of bbox
1017
1018 21
                if ($this->text_halign == 'right') {
1019 21
                    $x -= $width;
1020 21
                    $x -= $bbox[0];
1021 21
                } elseif ($this->text_halign == 'center') {
1022 21
                    $x -= $width / 2;
1023 21
                    $x -= $bbox[0];
1024 21
                } elseif ($this->text_halign == 'baseline') {
1025
                    // This is only support for text at 90 degree !!
1026
                    // Do nothing the text is drawn at baseline by default
1027
                }
1028
1029 21
                if ($this->text_valign == 'top') {
1030 21
                    $y -= $bbox[1]; // Adjust to bottom of text
1031 21
                    $y += $height;
1032 21
                } elseif ($this->text_valign == 'center') {
1033 20
                    $y -= $bbox[1]; // Adjust to bottom of text
1034 20
                    $y += $height / 2;
1035 21
                } elseif ($this->text_valign == 'baseline') {
1036
                    // This is only support for text at 0 degree !!
1037
                    // Do nothing the text is drawn at baseline by default
1038
                }
1039
            }
1040 21
            imagettftext(
1041 21
                $this->img,
1042 21
                $this->font_size,
1043 21
                $dir,
1044 21
                $x,
1045 21
                $y,
1046 21
                $this->current_color,
1047 21
                $this->font_file,
1048 21
                $txt
1049
            );
1050
1051
            // Calculate and return the co-ordinates for the bounding box
1052 21
            $box = $this->imagettfbbox_fixed($this->font_size, $dir, $this->font_file, $txt);
1053 21
            $p1  = [];
1054
1055 21
            for ($i = 0; $i < 4; ++$i) {
1056 21
                $p1[] = round($box[$i * 2] + $x);
1057 21
                $p1[] = round($box[$i * 2 + 1] + $y);
1058
            }
1059 21
            $aBoundingBox = $p1;
1060
1061
            // Debugging code to highlight the bonding box and bounding rectangle
1062
            // For text at 0 degrees the bounding box and bounding rectangle are the
1063
            // same
1064 21
            if ($debug) {
1065
                // Draw the bounding rectangle and the bounding box
1066
1067
                $p  = [];
1068
                $p1 = [];
1069
1070
                for ($i = 0; $i < 4; ++$i) {
1071
                    $p[]  = $bbox[$i * 2] + $x;
1072
                    $p[]  = $bbox[$i * 2 + 1] + $y;
1073
                    $p1[] = $box[$i * 2] + $x;
1074
                    $p1[] = $box[$i * 2 + 1] + $y;
1075
                }
1076
1077
                // Draw bounding box
1078
                $this->PushColor('green');
1079
                $this->Polygon($p1, true);
1080
                $this->PopColor();
1081
1082
                // Draw bounding rectangle
1083
                $this->PushColor('darkgreen');
1084
                $this->Polygon($p, true);
1085
                $this->PopColor();
1086
1087
                // Draw a cross at the anchor point
1088
                $this->PushColor('red');
1089
                $this->Line($ox - 15, $oy, $ox + 15, $oy);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $ox does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $oy does not seem to be defined for all execution paths leading up to this point.
Loading history...
1090
                $this->Line($ox, $oy - 15, $ox, $oy + 15);
1091 21
                $this->PopColor();
1092
            }
1093
        } else {
1094
            // Format a text paragraph
1095 2
            $fh = $this->GetFontHeight();
1096
1097
            // Line margin is 25% of font height
1098 2
            $linemargin = round($fh * $ConstLineSpacing);
1099 2
            $fh += $linemargin;
1100 2
            $w = $this->GetTextWidth($txt);
1101
1102 2
            $y -= $linemargin / 2;
1103 2
            $tmp = preg_split('/\n/', $txt);
1104 2
            $nl  = safe_count($tmp);
1105 2
            $h   = $nl * $fh;
1106
1107 2
            if ($this->text_halign == 'right') {
1108
                $x -= $dir == 0 ? $w : $h;
1109 2
            } elseif ($this->text_halign == 'center') {
1110
                $x -= $dir == 0 ? $w / 2 : $h / 2;
1111
            }
1112
1113 2
            if ($this->text_valign == 'top') {
1114 1
                $y += $dir == 0 ? $h : $w;
1115 1
            } elseif ($this->text_valign == 'center') {
1116
                $y += $dir == 0 ? $h / 2 : $w / 2;
1117
            }
1118
1119
            // Here comes a tricky bit.
1120
            // Since we have to give the position for the string at the
1121
            // baseline this means thaht text will move slightly up
1122
            // and down depending on any of it's character descend below
1123
            // the baseline, for example a 'g'. To adjust the Y-position
1124
            // we therefore adjust the text with the baseline Y-offset
1125
            // as used for the current font and size. This will keep the
1126
            // baseline at a fixed positoned disregarding the actual
1127
            // characters in the string.
1128 2
            $standardbox  = $this->GetTTFBBox('Gg', $dir);
1129 2
            $yadj         = $standardbox[1];
1130 2
            $xadj         = $standardbox[0];
0 ignored issues
show
Unused Code introduced by
The assignment to $xadj is dead and can be removed.
Loading history...
1131 2
            $aBoundingBox = [];
1132 2
            for ($i = 0; $i < $nl; ++$i) {
1133 2
                $wl   = $this->GetTextWidth($tmp[$i]);
1134 2
                $bbox = $this->GetTTFBBox($tmp[$i], $dir);
1135 2
                if ($paragraph_align == 'left') {
1136 2
                    $xl = $x;
1137
                } elseif ($paragraph_align == 'right') {
1138
                    $xl = $x + ($w - $wl);
1139
                } else {
1140
                    // Center
1141
                    $xl = $x + $w / 2 - $wl / 2;
1142
                }
1143
1144
                // In theory we should adjust with full pre-lead to get the lines
1145
                // lined up but this doesn't look good so therfore we only adjust with
1146
                // half th pre-lead
1147 2
                $xl -= $bbox[0] / 2;
1148 2
                $yl = $y - $yadj;
1149
                //$xl = $xl- $xadj;
1150 2
                imagettftext(
1151 2
                    $this->img,
1152 2
                    $this->font_size,
1153 2
                    $dir,
1154 2
                    $xl,
1155 2
                    $yl - ($h - $fh) + $fh * $i,
0 ignored issues
show
Bug introduced by
$yl - $h - $fh + $fh * $i of type double is incompatible with the type integer expected by parameter $y of imagettftext(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1155
                    /** @scrutinizer ignore-type */ $yl - ($h - $fh) + $fh * $i,
Loading history...
1156 2
                    $this->current_color,
1157 2
                    $this->font_file,
1158 2
                    $tmp[$i]
1159
                );
1160
1161
                // echo "xl=$xl,".$tmp[$i]." <br>";
1162 2
                if ($debug) {
1163
                    // Draw the bounding rectangle around each line
1164
                    $box = @imagettfbbox($this->font_size, $dir, $this->font_file, $tmp[$i]);
0 ignored issues
show
Unused Code introduced by
The assignment to $box is dead and can be removed.
Loading history...
1165
                    $p   = [];
1166
                    for ($j = 0; $j < 4; ++$j) {
1167
                        $p[] = $bbox[$j * 2] + $xl;
1168
                        $p[] = $bbox[$j * 2 + 1] + $yl - ($h - $fh) + $fh * $i;
1169
                    }
1170
1171
                    // Draw bounding rectangle
1172
                    $this->PushColor('darkgreen');
1173
                    $this->Polygon($p, true);
1174
                    $this->PopColor();
1175
                }
1176
            }
1177
1178
            // Get the bounding box
1179 2
            $bbox = $this->GetBBoxTTF($txt, $dir);
1180 2
            for ($j = 0; $j < 4; ++$j) {
1181 2
                $bbox[$j * 2] += round($x);
1182 2
                $bbox[$j * 2 + 1] += round($y - ($h - $fh) - $yadj);
1183
            }
1184 2
            $aBoundingBox = $bbox;
1185
1186 2
            if ($debug) {
1187
                // Draw a cross at the anchor point
1188
                $this->PushColor('red');
1189
                $this->Line($ox - 25, $oy, $ox + 25, $oy);
1190
                $this->Line($ox, $oy - 25, $ox, $oy + 25);
1191
                $this->PopColor();
1192
            }
1193
        }
1194 21
    }
1195
1196 21
    public function StrokeText($x, $y, $txt, $dir = 0, $paragraph_align = 'left', $debug = false)
1197
    {
1198 21
        $x = round($x);
1199 21
        $y = round($y);
1200
1201
        // Do special language encoding
1202 21
        $txt = $this->langconv->Convert($txt, $this->font_family);
1203
1204 21
        if (!is_numeric($dir)) {
1205
            Util\JpGraphError::RaiseL(25094); //(" Direction for text most be given as an angle between 0 and 90.");
1206
        }
1207
1208 21
        if ($this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2 + 1) {
1209 12
            $this->_StrokeBuiltinFont($x, $y, $txt, $dir, $paragraph_align, $boundingbox, $debug);
1210 21
        } elseif ($this->font_family >= _FIRST_FONT && $this->font_family <= _LAST_FONT) {
1211 21
            $this->_StrokeTTF($x, $y, $txt, $dir, $paragraph_align, $boundingbox, $debug);
1212
        } else {
1213
            Util\JpGraphError::RaiseL(25095); //(" Unknown font font family specification. ");
1214
        }
1215
1216 21
        return $boundingbox;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $boundingbox does not seem to be defined for all execution paths leading up to this point.
Loading history...
1217
    }
1218
1219 21
    public function SetMargin($lm, $rm, $tm, $bm)
1220
    {
1221 21
        $this->left_margin   = $lm;
1222 21
        $this->right_margin  = $rm;
1223 21
        $this->top_margin    = $tm;
1224 21
        $this->bottom_margin = $bm;
1225
1226 21
        $this->plotwidth  = $this->width - $this->left_margin - $this->right_margin;
1227 21
        $this->plotheight = $this->height - $this->top_margin - $this->bottom_margin;
1228
1229 21
        if ($this->width > 0 && $this->height > 0) {
1230 21
            if ($this->plotwidth < 0 || $this->plotheight < 0) {
1231
                Util\JpGraphError::RaiseL(25130, $this->plotwidth, $this->plotheight);
1232
                //Util\JpGraphError::raise("To small plot area. ($lm,$rm,$tm,$bm : $this->plotwidth x $this->plotheight). With the given image size and margins there is to little space left for the plot. Increase the plot size or reduce the margins.");
1233
            }
1234
        }
1235 21
    }
1236
1237
    public function SetTransparent($color)
1238
    {
1239
        imagecolortransparent($this->img, $this->rgb->allocate($color));
0 ignored issues
show
Bug introduced by
The method allocate() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1239
        imagecolortransparent($this->img, $this->rgb->/** @scrutinizer ignore-call */ allocate($color));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1240
    }
1241
1242 21
    public function SetColor($color, $aAlpha = 0)
1243
    {
1244 21
        $this->current_color_name = $color;
1245 21
        $this->current_color      = $this->rgb->allocate($color, $aAlpha);
1246 21
        if ($this->current_color == -1) {
1247
            $tc = imagecolorstotal($this->img);
0 ignored issues
show
Unused Code introduced by
The assignment to $tc is dead and can be removed.
Loading history...
1248
            Util\JpGraphError::RaiseL(25096);
1249
            //("Can't allocate any more colors. Image has already allocated maximum of <b>$tc colors</b>. This might happen if you have anti-aliasing turned on together with a background image or perhaps gradient fill since this requires many, many colors. Try to turn off anti-aliasing. If there is still a problem try downgrading the quality of the background image to use a smaller pallete to leave some entries for your graphs. You should try to limit the number of colors in your background image to 64. If there is still problem set the constant DEFINE(\"USE_APPROX_COLORS\",true); in jpgraph.php This will use approximative colors when the palette is full. Unfortunately there is not much JpGraph can do about this since the palette size is a limitation of current graphic format and what the underlying GD library suppports.");
1250
        }
1251
1252 21
        return $this->current_color;
1253
    }
1254
1255 21
    public function PushColor($color)
1256
    {
1257 21
        if ($color != '') {
1258 21
            $this->colorstack[$this->colorstackidx]     = $this->current_color_name;
1259 21
            $this->colorstack[$this->colorstackidx + 1] = $this->current_color;
1260 21
            $this->colorstackidx += 2;
1261 21
            $this->SetColor($color);
1262
        } else {
1263
            Util\JpGraphError::RaiseL(25097); //("Color specified as empty string in PushColor().");
1264
        }
1265 21
    }
1266
1267 21
    public function PopColor()
1268
    {
1269 21
        if ($this->colorstackidx < 1) {
1270
            Util\JpGraphError::RaiseL(25098); //(" Negative Color stack index. Unmatched call to PopColor()");
1271
        }
1272 21
        $this->current_color      = $this->colorstack[--$this->colorstackidx];
1273 21
        $this->current_color_name = $this->colorstack[--$this->colorstackidx];
1274 21
    }
1275
1276 21
    public function SetLineWeight($weight)
1277
    {
1278 21
        $old = $this->line_weight;
1279 21
        imagesetthickness($this->img, $weight);
1280 21
        $this->line_weight = $weight;
1281
1282 21
        return $old;
1283
    }
1284
1285 16
    public function SetStartPoint($x, $y)
1286
    {
1287 16
        $this->lastx = round($x);
1288 16
        $this->lasty = round($y);
1289 16
    }
1290
1291
    public function Arc($cx, $cy, $w, $h, $s, $e)
1292
    {
1293
        // GD Arc doesn't like negative angles
1294
        while ($s < 0) {
1295
            $s += 360;
1296
        }
1297
1298
        while ($e < 0) {
1299
            $e += 360;
1300
        }
1301
1302
        imagearc($this->img, round($cx), round($cy), round($w), round($h), $s, $e, $this->current_color);
0 ignored issues
show
Bug introduced by
round($cy) of type double is incompatible with the type integer expected by parameter $cy of imagearc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1302
        imagearc($this->img, round($cx), /** @scrutinizer ignore-type */ round($cy), round($w), round($h), $s, $e, $this->current_color);
Loading history...
Bug introduced by
round($cx) of type double is incompatible with the type integer expected by parameter $cx of imagearc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1302
        imagearc($this->img, /** @scrutinizer ignore-type */ round($cx), round($cy), round($w), round($h), $s, $e, $this->current_color);
Loading history...
Bug introduced by
round($h) of type double is incompatible with the type integer expected by parameter $height of imagearc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1302
        imagearc($this->img, round($cx), round($cy), round($w), /** @scrutinizer ignore-type */ round($h), $s, $e, $this->current_color);
Loading history...
Bug introduced by
round($w) of type double is incompatible with the type integer expected by parameter $width of imagearc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1302
        imagearc($this->img, round($cx), round($cy), /** @scrutinizer ignore-type */ round($w), round($h), $s, $e, $this->current_color);
Loading history...
1303
    }
1304
1305 3
    public function FilledArc($xc, $yc, $w, $h, $s, $e, $style = '')
1306
    {
1307 3
        $s = round($s);
1308 3
        $e = round($e);
1309 3
        while ($s < 0) {
1310
            $s += 360;
1311
        }
1312
1313 3
        while ($e < 0) {
1314
            $e += 360;
1315
        }
1316
1317 3
        if ($style == '') {
1318 3
            $style = IMG_ARC_PIE;
1319
        }
1320
1321 3
        if (abs($s - $e) > 0) {
1322 3
            imagefilledarc($this->img, round($xc), round($yc), round($w), round($h), $s, $e, $this->current_color, $style);
0 ignored issues
show
Bug introduced by
It seems like $s can also be of type double; however, parameter $start of imagefilledarc() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1322
            imagefilledarc($this->img, round($xc), round($yc), round($w), round($h), /** @scrutinizer ignore-type */ $s, $e, $this->current_color, $style);
Loading history...
Bug introduced by
round($xc) of type double is incompatible with the type integer expected by parameter $cx of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1322
            imagefilledarc($this->img, /** @scrutinizer ignore-type */ round($xc), round($yc), round($w), round($h), $s, $e, $this->current_color, $style);
Loading history...
Bug introduced by
round($h) of type double is incompatible with the type integer expected by parameter $height of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1322
            imagefilledarc($this->img, round($xc), round($yc), round($w), /** @scrutinizer ignore-type */ round($h), $s, $e, $this->current_color, $style);
Loading history...
Bug introduced by
round($w) of type double is incompatible with the type integer expected by parameter $width of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1322
            imagefilledarc($this->img, round($xc), round($yc), /** @scrutinizer ignore-type */ round($w), round($h), $s, $e, $this->current_color, $style);
Loading history...
Bug introduced by
It seems like $e can also be of type double; however, parameter $end of imagefilledarc() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1322
            imagefilledarc($this->img, round($xc), round($yc), round($w), round($h), $s, /** @scrutinizer ignore-type */ $e, $this->current_color, $style);
Loading history...
Bug introduced by
round($yc) of type double is incompatible with the type integer expected by parameter $cy of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1322
            imagefilledarc($this->img, round($xc), /** @scrutinizer ignore-type */ round($yc), round($w), round($h), $s, $e, $this->current_color, $style);
Loading history...
1323
            //            $this->DrawImageSmoothArc($this->img,round($xc),round($yc),round($w),round($h),$s,$e,$this->current_color,$style);
1324
        }
1325 3
    }
1326
1327
    public function FilledCakeSlice($cx, $cy, $w, $h, $s, $e)
1328
    {
1329
        $this->CakeSlice($cx, $cy, $w, $h, $s, $e, $this->current_color_name);
1330
    }
1331
1332 3
    public function CakeSlice($xc, $yc, $w, $h, $s, $e, $fillcolor = '', $arccolor = '')
1333
    {
1334 3
        $s  = round($s);
1335 3
        $e  = round($e);
1336 3
        $w  = round($w);
1337 3
        $h  = round($h);
1338 3
        $xc = round($xc);
1339 3
        $yc = round($yc);
1340 3
        if ($s == $e) {
1341
            // A full circle. We draw this a plain circle
1342
            $this->PushColor($fillcolor);
1343
            imagefilledellipse($this->img, $xc, $yc, 2 * $w, 2 * $h, $this->current_color);
0 ignored issues
show
Bug introduced by
2 * $w of type double is incompatible with the type integer expected by parameter $width of imagefilledellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1343
            imagefilledellipse($this->img, $xc, $yc, /** @scrutinizer ignore-type */ 2 * $w, 2 * $h, $this->current_color);
Loading history...
Bug introduced by
$yc of type double is incompatible with the type integer expected by parameter $cy of imagefilledellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1343
            imagefilledellipse($this->img, $xc, /** @scrutinizer ignore-type */ $yc, 2 * $w, 2 * $h, $this->current_color);
Loading history...
Bug introduced by
2 * $h of type double is incompatible with the type integer expected by parameter $height of imagefilledellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1343
            imagefilledellipse($this->img, $xc, $yc, 2 * $w, /** @scrutinizer ignore-type */ 2 * $h, $this->current_color);
Loading history...
Bug introduced by
$xc of type double is incompatible with the type integer expected by parameter $cx of imagefilledellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1343
            imagefilledellipse($this->img, /** @scrutinizer ignore-type */ $xc, $yc, 2 * $w, 2 * $h, $this->current_color);
Loading history...
1344
1345
            // If antialiasing is used then we often don't have any color no the surrounding
1346
            // arc. So, we need to check for this special case so we don't send an empty
1347
            // color to the push function. In this case we use the fill color for the arc as well
1348
            if ($arccolor != '') {
1349
                $this->PopColor();
1350
                $this->PushColor($arccolor);
1351
            }
1352
            imageellipse($this->img, $xc, $yc, 2 * $w, 2 * $h, $this->current_color);
0 ignored issues
show
Bug introduced by
$xc of type double is incompatible with the type integer expected by parameter $cx of imageellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1352
            imageellipse($this->img, /** @scrutinizer ignore-type */ $xc, $yc, 2 * $w, 2 * $h, $this->current_color);
Loading history...
Bug introduced by
2 * $w of type double is incompatible with the type integer expected by parameter $width of imageellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1352
            imageellipse($this->img, $xc, $yc, /** @scrutinizer ignore-type */ 2 * $w, 2 * $h, $this->current_color);
Loading history...
Bug introduced by
2 * $h of type double is incompatible with the type integer expected by parameter $height of imageellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1352
            imageellipse($this->img, $xc, $yc, 2 * $w, /** @scrutinizer ignore-type */ 2 * $h, $this->current_color);
Loading history...
Bug introduced by
$yc of type double is incompatible with the type integer expected by parameter $cy of imageellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1352
            imageellipse($this->img, $xc, /** @scrutinizer ignore-type */ $yc, 2 * $w, 2 * $h, $this->current_color);
Loading history...
1353
            $this->Line($xc, $yc, cos($s * M_PI / 180) * $w + $xc, $yc + sin($s * M_PI / 180) * $h);
1354
            $this->PopColor();
1355
        } else {
1356 3
            $this->PushColor($fillcolor);
1357 3
            $this->FilledArc($xc, $yc, 2 * $w, 2 * $h, $s, $e);
1358 3
            $this->PopColor();
1359 3
            if ($arccolor != '') {
1360
                $this->PushColor($arccolor);
1361
                // We add 2 pixels to make the Arc() better aligned with
1362
                // the filled arc.
1363
                imagefilledarc($this->img, $xc, $yc, 2 * $w, 2 * $h, $s, $e, $this->current_color, IMG_ARC_NOFILL | IMG_ARC_EDGED);
0 ignored issues
show
Bug introduced by
2 * $h of type double is incompatible with the type integer expected by parameter $height of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1363
                imagefilledarc($this->img, $xc, $yc, 2 * $w, /** @scrutinizer ignore-type */ 2 * $h, $s, $e, $this->current_color, IMG_ARC_NOFILL | IMG_ARC_EDGED);
Loading history...
Bug introduced by
$e of type double is incompatible with the type integer expected by parameter $end of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1363
                imagefilledarc($this->img, $xc, $yc, 2 * $w, 2 * $h, $s, /** @scrutinizer ignore-type */ $e, $this->current_color, IMG_ARC_NOFILL | IMG_ARC_EDGED);
Loading history...
Bug introduced by
$xc of type double is incompatible with the type integer expected by parameter $cx of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1363
                imagefilledarc($this->img, /** @scrutinizer ignore-type */ $xc, $yc, 2 * $w, 2 * $h, $s, $e, $this->current_color, IMG_ARC_NOFILL | IMG_ARC_EDGED);
Loading history...
Bug introduced by
2 * $w of type double is incompatible with the type integer expected by parameter $width of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1363
                imagefilledarc($this->img, $xc, $yc, /** @scrutinizer ignore-type */ 2 * $w, 2 * $h, $s, $e, $this->current_color, IMG_ARC_NOFILL | IMG_ARC_EDGED);
Loading history...
Bug introduced by
$s of type double is incompatible with the type integer expected by parameter $start of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1363
                imagefilledarc($this->img, $xc, $yc, 2 * $w, 2 * $h, /** @scrutinizer ignore-type */ $s, $e, $this->current_color, IMG_ARC_NOFILL | IMG_ARC_EDGED);
Loading history...
Bug introduced by
$yc of type double is incompatible with the type integer expected by parameter $cy of imagefilledarc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1363
                imagefilledarc($this->img, $xc, /** @scrutinizer ignore-type */ $yc, 2 * $w, 2 * $h, $s, $e, $this->current_color, IMG_ARC_NOFILL | IMG_ARC_EDGED);
Loading history...
1364
                $this->PopColor();
1365
            }
1366
        }
1367 3
    }
1368
1369
    public function Ellipse($xc, $yc, $w, $h)
1370
    {
1371
        $this->Arc($xc, $yc, $w, $h, 0, 360);
1372
    }
1373
1374 5
    public function Circle($xc, $yc, $r)
1375
    {
1376 5
        imageellipse($this->img, round($xc), round($yc), $r * 2, $r * 2, $this->current_color);
0 ignored issues
show
Bug introduced by
round($xc) of type double is incompatible with the type integer expected by parameter $cx of imageellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1376
        imageellipse($this->img, /** @scrutinizer ignore-type */ round($xc), round($yc), $r * 2, $r * 2, $this->current_color);
Loading history...
Bug introduced by
round($yc) of type double is incompatible with the type integer expected by parameter $cy of imageellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1376
        imageellipse($this->img, round($xc), /** @scrutinizer ignore-type */ round($yc), $r * 2, $r * 2, $this->current_color);
Loading history...
1377
        //        $this->DrawImageSmoothArc($this->img,round($xc),round($yc),$r*2+1,$r*2+1,0,360,$this->current_color);
1378
        //        $this->imageSmoothCircle($this->img, round($xc),round($yc), $r*2+1, $this->current_color);
1379 5
    }
1380
1381 5
    public function FilledCircle($xc, $yc, $r)
1382
    {
1383 5
        imagefilledellipse($this->img, round($xc), round($yc), 2 * $r, 2 * $r, $this->current_color);
0 ignored issues
show
Bug introduced by
round($xc) of type double is incompatible with the type integer expected by parameter $cx of imagefilledellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1383
        imagefilledellipse($this->img, /** @scrutinizer ignore-type */ round($xc), round($yc), 2 * $r, 2 * $r, $this->current_color);
Loading history...
Bug introduced by
round($yc) of type double is incompatible with the type integer expected by parameter $cy of imagefilledellipse(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1383
        imagefilledellipse($this->img, round($xc), /** @scrutinizer ignore-type */ round($yc), 2 * $r, 2 * $r, $this->current_color);
Loading history...
1384
        //        $this->DrawImageSmoothArc($this->img, round($xc), round($yc), 2*$r, 2*$r, 0, 360, $this->current_color);
1385 5
    }
1386
1387
    // Linear Color InterPolation
1388
    public function lip($f, $t, $p)
1389
    {
1390
        $p = round($p, 1);
1391
        $r = $f[0] + ($t[0] - $f[0]) * $p;
1392
        $g = $f[1] + ($t[1] - $f[1]) * $p;
1393
        $b = $f[2] + ($t[2] - $f[2]) * $p;
1394
1395
        return [$r, $g, $b];
1396
    }
1397
1398
    // Set line style dashed, dotted etc
1399 21
    public function SetLineStyle($s)
1400
    {
1401 21
        if (is_numeric($s)) {
1402 16
            if ($s < 1 || $s > 4) {
1403 16
                Util\JpGraphError::RaiseL(25101, $s); //(" Illegal numeric argument to SetLineStyle(): ($s)");
1404
            }
1405 21
        } elseif (is_string($s)) {
1406 21
            if ($s == 'solid') {
1407 21
                $s = 1;
1408 2
            } elseif ($s == 'dotted') {
1409 1
                $s = 2;
1410 1
            } elseif ($s == 'dashed') {
1411 1
                $s = 3;
1412
            } elseif ($s == 'longdashed') {
1413
                $s = 4;
1414
            } else {
1415 21
                Util\JpGraphError::RaiseL(25102, $s); //(" Illegal string argument to SetLineStyle(): $s");
1416
            }
1417
        } else {
1418
            Util\JpGraphError::RaiseL(25103, $s); //(" Illegal argument to SetLineStyle $s");
1419
        }
1420 21
        $old              = $this->line_style;
1421 21
        $this->line_style = $s;
1422
1423 21
        return $old;
1424
    }
1425
1426
    // Same as Line but take the line_style into account
1427 21
    public function StyleLine($x1, $y1, $x2, $y2, $aStyle = '', $from_grid_class = false)
1428
    {
1429 21
        if ($this->line_weight <= 0) {
1430 1
            return;
1431
        }
1432
1433 21
        if ($aStyle === '') {
1434 21
            $aStyle = $this->line_style;
1435
        }
1436
1437 21
        $dashed_line_method = 'DashedLine';
1438 21
        if ($from_grid_class) {
1439 19
            $dashed_line_method = 'DashedLineForGrid';
1440
        }
1441
1442
        // Add error check since dashed line will only work if anti-alias is disabled
1443
        // this is a limitation in GD
1444
1445 21
        if ($aStyle == 1) {
1446
            // Solid style. We can handle anti-aliasing for this
1447 21
            $this->Line($x1, $y1, $x2, $y2);
1448
        } else {
1449
            // Since the GD routines doesn't handle AA for styled line
1450
            // we have no option than to turn it off to get any lines at
1451
            // all if the weight > 1
1452 6
            $oldaa = $this->GetAntiAliasing();
1453 6
            if ($oldaa && $this->line_weight > 1) {
1454 1
                $this->SetAntiAliasing(false);
1455
            }
1456
1457
            switch ($aStyle) {
1458 6
                case 2: // Dotted
1459 3
                    $this->{$dashed_line_method}($x1, $y1, $x2, $y2, 2, 6);
1460
1461 3
                    break;
1462 3
                case 3: // Dashed
1463 3
                    $this->{$dashed_line_method}($x1, $y1, $x2, $y2, 5, 9);
1464
1465 3
                    break;
1466
                case 4: // Longdashes
1467
                    $this->{$dashed_line_method}($x1, $y1, $x2, $y2, 9, 13);
1468
1469
                    break;
1470
                default:
1471
                    Util\JpGraphError::RaiseL(25104, $this->line_style); //(" Unknown line style: $this->line_style ");
1472
                    break;
1473
            }
1474 6
            if ($oldaa) {
1475 5
                $this->SetAntiAliasing(true);
1476
            }
1477
        }
1478 21
    }
1479
1480 2
    public function DashedLine($x1, $y1, $x2, $y2, $dash_length = 1, $dash_space = 4)
1481
    {
1482 2
        if ($this->line_weight <= 0) {
1483
            return;
1484
        }
1485
1486
        // Add error check to make sure anti-alias is not enabled.
1487
        // Dashed line does not work with anti-alias enabled. This
1488
        // is a limitation in GD.
1489 2
        if ($this->use_anti_aliasing) {
1490
            //            Util\JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.
1491
        }
1492
1493 2
        $x1 = round($x1);
1494 2
        $x2 = round($x2);
1495 2
        $y1 = round($y1);
1496 2
        $y2 = round($y2);
1497
1498 2
        $dash_length *= SUPERSAMPLING_SCALE;
1499 2
        $dash_space *= SUPERSAMPLING_SCALE;
1500
1501 2
        $style = array_fill(0, $dash_length, $this->current_color);
1502 2
        $style = array_pad($style, $dash_space, IMG_COLOR_TRANSPARENT);
1503 2
        imagesetstyle($this->img, $style);
1504 2
        imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
0 ignored issues
show
Bug introduced by
$y2 of type double is incompatible with the type integer expected by parameter $y2 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1504
        imageline($this->img, $x1, $y1, $x2, /** @scrutinizer ignore-type */ $y2, IMG_COLOR_STYLED);
Loading history...
Bug introduced by
$x1 of type double is incompatible with the type integer expected by parameter $x1 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1504
        imageline($this->img, /** @scrutinizer ignore-type */ $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
Loading history...
Bug introduced by
$x2 of type double is incompatible with the type integer expected by parameter $x2 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1504
        imageline($this->img, $x1, $y1, /** @scrutinizer ignore-type */ $x2, $y2, IMG_COLOR_STYLED);
Loading history...
Bug introduced by
$y1 of type double is incompatible with the type integer expected by parameter $y1 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1504
        imageline($this->img, $x1, /** @scrutinizer ignore-type */ $y1, $x2, $y2, IMG_COLOR_STYLED);
Loading history...
1505
1506 2
        $this->lastx = $x2;
1507 2
        $this->lasty = $y2;
1508 2
    }
1509
1510 5
    public function DashedLineForGrid($x1, $y1, $x2, $y2, $dash_length = 1, $dash_space = 4)
1511
    {
1512 5
        if ($this->line_weight <= 0) {
1513
            return;
1514
        }
1515
1516
        // Add error check to make sure anti-alias is not enabled.
1517
        // Dashed line does not work with anti-alias enabled. This
1518
        // is a limitation in GD.
1519 5
        if ($this->use_anti_aliasing) {
1520
            //            Util\JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.
1521
        }
1522
1523 5
        $x1 = round($x1);
1524 5
        $x2 = round($x2);
1525 5
        $y1 = round($y1);
1526 5
        $y2 = round($y2);
1527
1528
        /*
1529
        $dash_length *= $this->scale;
1530
        $dash_space  *= $this->scale;
1531
         */
1532
1533 5
        $dash_length = 2;
0 ignored issues
show
Unused Code introduced by
The assignment to $dash_length is dead and can be removed.
Loading history...
1534 5
        $dash_length = 4;
1535 5
        imagesetthickness($this->img, 1);
1536 5
        $style = array_fill(0, $dash_length, $this->current_color); //hexdec('CCCCCC'));
1537 5
        $style = array_pad($style, $dash_space, IMG_COLOR_TRANSPARENT);
1538 5
        imagesetstyle($this->img, $style);
1539 5
        imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
0 ignored issues
show
Bug introduced by
$x2 of type double is incompatible with the type integer expected by parameter $x2 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1539
        imageline($this->img, $x1, $y1, /** @scrutinizer ignore-type */ $x2, $y2, IMG_COLOR_STYLED);
Loading history...
Bug introduced by
$y2 of type double is incompatible with the type integer expected by parameter $y2 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1539
        imageline($this->img, $x1, $y1, $x2, /** @scrutinizer ignore-type */ $y2, IMG_COLOR_STYLED);
Loading history...
Bug introduced by
$y1 of type double is incompatible with the type integer expected by parameter $y1 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1539
        imageline($this->img, $x1, /** @scrutinizer ignore-type */ $y1, $x2, $y2, IMG_COLOR_STYLED);
Loading history...
Bug introduced by
$x1 of type double is incompatible with the type integer expected by parameter $x1 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1539
        imageline($this->img, /** @scrutinizer ignore-type */ $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
Loading history...
1540
1541 5
        $this->lastx = $x2;
1542 5
        $this->lasty = $y2;
1543 5
    }
1544
1545 21
    public function Line($x1, $y1, $x2, $y2)
1546
    {
1547 21
        if ($this->line_weight <= 0) {
1548
            return;
1549
        }
1550
1551 21
        $x1 = round($x1);
1552 21
        $x2 = round($x2);
1553 21
        $y1 = round($y1);
1554 21
        $y2 = round($y2);
1555
1556 21
        imageline($this->img, $x1, $y1, $x2, $y2, $this->current_color);
0 ignored issues
show
Bug introduced by
$y2 of type double is incompatible with the type integer expected by parameter $y2 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1556
        imageline($this->img, $x1, $y1, $x2, /** @scrutinizer ignore-type */ $y2, $this->current_color);
Loading history...
Bug introduced by
$x1 of type double is incompatible with the type integer expected by parameter $x1 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1556
        imageline($this->img, /** @scrutinizer ignore-type */ $x1, $y1, $x2, $y2, $this->current_color);
Loading history...
Bug introduced by
$x2 of type double is incompatible with the type integer expected by parameter $x2 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1556
        imageline($this->img, $x1, $y1, /** @scrutinizer ignore-type */ $x2, $y2, $this->current_color);
Loading history...
Bug introduced by
$y1 of type double is incompatible with the type integer expected by parameter $y1 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1556
        imageline($this->img, $x1, /** @scrutinizer ignore-type */ $y1, $x2, $y2, $this->current_color);
Loading history...
1557
        //        $this->DrawLine($this->img, $x1, $y1, $x2, $y2, $this->line_weight, $this->current_color);
1558 21
        $this->lastx = $x2;
1559 21
        $this->lasty = $y2;
1560 21
    }
1561
1562 21
    public function Polygon($p, $closed = false, $fast = false)
1563
    {
1564 21
        if ($this->line_weight <= 0) {
1565 10
            return;
1566
        }
1567
1568 21
        $n    = safe_count($p);
1569 21
        $oldx = $p[0];
1570 21
        $oldy = $p[1];
1571 21
        if ($fast) {
1572
            for ($i = 2; $i < $n; $i += 2) {
1573
                imageline($this->img, $oldx, $oldy, $p[$i], $p[$i + 1], $this->current_color);
1574
                $oldx = $p[$i];
1575
                $oldy = $p[$i + 1];
1576
            }
1577
            if ($closed) {
1578
                imageline($this->img, $p[$n * 2 - 2], $p[$n * 2 - 1], $p[0], $p[1], $this->current_color);
1579
            }
1580
        } else {
1581 21
            for ($i = 2; $i < $n; $i += 2) {
1582 21
                $this->StyleLine($oldx, $oldy, $p[$i], $p[$i + 1]);
1583 21
                $oldx = $p[$i];
1584 21
                $oldy = $p[$i + 1];
1585
            }
1586 21
            if ($closed) {
1587 5
                $this->StyleLine($oldx, $oldy, $p[0], $p[1]);
1588
            }
1589
        }
1590 21
    }
1591
1592 21
    public function FilledPolygon($pts)
1593
    {
1594 21
        $n = safe_count($pts);
1595 21
        if ($n == 0) {
1596
            Util\JpGraphError::RaiseL(25105); //('NULL data specified for a filled polygon. Check that your data is not NULL.');
1597
        }
1598 21
        for ($i = 0; $i < $n; ++$i) {
1599 21
            $pts[$i] = round($pts[$i]);
1600
        }
1601 21
        $old = $this->line_weight;
1602 21
        imagesetthickness($this->img, 1);
1603 21
        imagefilledpolygon($this->img, $pts, safe_count($pts) / 2, $this->current_color);
1604 21
        $this->line_weight = $old;
1605 21
        imagesetthickness($this->img, $old);
1606 21
    }
1607
1608 21
    public function Rectangle($xl, $yu, $xr, $yl)
1609
    {
1610 21
        $this->Polygon([$xl, $yu, $xr, $yu, $xr, $yl, $xl, $yl, $xl, $yu]);
1611 21
    }
1612
1613
    public function FilledRectangle($xl, $yu, $xr, $yl)
1614
    {
1615
        $this->FilledPolygon([$xl, $yu, $xr, $yu, $xr, $yl, $xl, $yl]);
1616
    }
1617
1618 1
    public function FilledRectangle2($xl, $yu, $xr, $yl, $color1, $color2, $style = 1)
1619
    {
1620
        // Fill a rectangle with lines of two colors
1621 1
        if ($style === 1) {
1622
            // Horizontal stripe
1623 1
            if ($yl < $yu) {
1624
                $t  = $yl;
1625
                $yl = $yu;
1626
                $yu = $t;
1627
            }
1628 1
            for ($y = $yu; $y <= $yl; ++$y) {
1629 1
                $this->SetColor($color1);
1630 1
                $this->Line($xl, $y, $xr, $y);
1631 1
                ++$y;
1632 1
                $this->SetColor($color2);
1633 1
                $this->Line($xl, $y, $xr, $y);
1634
            }
1635
        } else {
1636
            if ($xl < $xl) {
1637
                $t  = $xl;
1638
                $xl = $xr;
1639
                $xr = $t;
1640
            }
1641
            for ($x = $xl; $x <= $xr; ++$x) {
1642
                $this->SetColor($color1);
1643
                $this->Line($x, $yu, $x, $yl);
1644
                ++$x;
1645
                $this->SetColor($color2);
1646
                $this->Line($x, $yu, $x, $yl);
1647
            }
1648
        }
1649 1
    }
1650
1651 4
    public function ShadowRectangle($xl, $yu, $xr, $yl, $fcolor = false, $shadow_width = 4, $shadow_color = 'darkgray', $useAlpha = true)
1652
    {
1653
        // This is complicated by the fact that we must also handle the case where
1654
        // the reactangle has no fill color
1655 4
        $xl = floor($xl);
1656 4
        $yu = floor($yu);
1657 4
        $xr = floor($xr);
1658 4
        $yl = floor($yl);
1659 4
        $this->PushColor($shadow_color);
1660 4
        $shadowAlpha = 0;
1661 4
        $this->SetLineWeight(1);
1662 4
        $this->SetLineStyle('solid');
1663 4
        $basecolor    = $this->rgb->Color($shadow_color);
1664 4
        $shadow_color = [$basecolor[0], $basecolor[1], $basecolor[2]];
1665 4
        for ($i = 0; $i < $shadow_width; ++$i) {
1666 4
            $this->SetColor($shadow_color, $shadowAlpha);
1667 4
            $this->Line(
1668 4
                $xr - $shadow_width + $i,
1669 4
                $yu + $shadow_width,
1670 4
                $xr - $shadow_width + $i,
1671 4
                $yl - $shadow_width - 1 + $i
1672
            );
1673 4
            $this->Line(
1674 4
                $xl + $shadow_width,
1675 4
                $yl - $shadow_width + $i,
1676 4
                $xr - $shadow_width + $i,
1677 4
                $yl - $shadow_width + $i
1678
            );
1679 4
            if ($useAlpha) {
1680 4
                $shadowAlpha += 1.0 / $shadow_width;
1681
            }
1682
        }
1683
1684 4
        $this->PopColor();
1685 4
        if ($fcolor == false) {
1686
            $this->Rectangle($xl, $yu, $xr - $shadow_width - 1, $yl - $shadow_width - 1);
1687
        } else {
1688 4
            $this->PushColor($fcolor);
1689 4
            $this->FilledRectangle($xl, $yu, $xr - $shadow_width - 1, $yl - $shadow_width - 1);
1690 4
            $this->PopColor();
1691 4
            $this->Rectangle($xl, $yu, $xr - $shadow_width - 1, $yl - $shadow_width - 1);
1692
        }
1693 4
    }
1694
1695
    public function FilledRoundedRectangle($xt, $yt, $xr, $yl, $r = 5)
1696
    {
1697
        if ($r == 0) {
1698
            $this->FilledRectangle($xt, $yt, $xr, $yl);
1699
1700
            return;
1701
        }
1702
1703
        // To avoid overlapping fillings (which will look strange
1704
        // when alphablending is enabled) we have no choice but
1705
        // to fill the five distinct areas one by one.
1706
1707
        // Center square
1708
        $this->FilledRectangle($xt + $r, $yt + $r, $xr - $r, $yl - $r);
1709
        // Top band
1710
        $this->FilledRectangle($xt + $r, $yt, $xr - $r, $yt + $r);
1711
        // Bottom band
1712
        $this->FilledRectangle($xt + $r, $yl - $r, $xr - $r, $yl);
1713
        // Left band
1714
        $this->FilledRectangle($xt, $yt + $r, $xt + $r, $yl - $r);
1715
        // Right band
1716
        $this->FilledRectangle($xr - $r, $yt + $r, $xr, $yl - $r);
1717
1718
        // Topleft & Topright arc
1719
        $this->FilledArc($xt + $r, $yt + $r, $r * 2, $r * 2, 180, 270);
1720
        $this->FilledArc($xr - $r, $yt + $r, $r * 2, $r * 2, 270, 360);
1721
1722
        // Bottomleft & Bottom right arc
1723
        $this->FilledArc($xt + $r, $yl - $r, $r * 2, $r * 2, 90, 180);
1724
        $this->FilledArc($xr - $r, $yl - $r, $r * 2, $r * 2, 0, 90);
1725
    }
1726
1727
    public function RoundedRectangle($xt, $yt, $xr, $yl, $r = 5)
1728
    {
1729
        if ($r == 0) {
1730
            $this->Rectangle($xt, $yt, $xr, $yl);
1731
1732
            return;
1733
        }
1734
1735
        // Top & Bottom line
1736
        $this->Line($xt + $r, $yt, $xr - $r, $yt);
1737
        $this->Line($xt + $r, $yl, $xr - $r, $yl);
1738
1739
        // Left & Right line
1740
        $this->Line($xt, $yt + $r, $xt, $yl - $r);
1741
        $this->Line($xr, $yt + $r, $xr, $yl - $r);
1742
1743
        // Topleft & Topright arc
1744
        $this->Arc($xt + $r, $yt + $r, $r * 2, $r * 2, 180, 270);
1745
        $this->Arc($xr - $r, $yt + $r, $r * 2, $r * 2, 270, 360);
1746
1747
        // Bottomleft & Bottomright arc
1748
        $this->Arc($xt + $r, $yl - $r, $r * 2, $r * 2, 90, 180);
1749
        $this->Arc($xr - $r, $yl - $r, $r * 2, $r * 2, 0, 90);
1750
    }
1751
1752
    public function FilledBevel($x1, $y1, $x2, $y2, $depth = 2, $color1 = '[email protected]', $color2 = '[email protected]')
1753
    {
1754
        $this->FilledRectangle($x1, $y1, $x2, $y2);
1755
        $this->Bevel($x1, $y1, $x2, $y2, $depth, $color1, $color2);
1756
    }
1757
1758 1
    public function Bevel($x1, $y1, $x2, $y2, $depth = 2, $color1 = '[email protected]', $color2 = '[email protected]')
1759
    {
1760 1
        $this->PushColor($color1);
1761 1
        for ($i = 0; $i < $depth; ++$i) {
1762 1
            $this->Line($x1 + $i, $y1 + $i, $x1 + $i, $y2 - $i);
1763 1
            $this->Line($x1 + $i, $y1 + $i, $x2 - $i, $y1 + $i);
1764
        }
1765 1
        $this->PopColor();
1766
1767 1
        $this->PushColor($color2);
1768 1
        for ($i = 0; $i < $depth; ++$i) {
1769 1
            $this->Line($x1 + $i, $y2 - $i, $x2 - $i, $y2 - $i);
1770 1
            $this->Line($x2 - $i, $y1 + $i, $x2 - $i, $y2 - $i - 1);
1771
        }
1772 1
        $this->PopColor();
1773 1
    }
1774
1775 16
    public function StyleLineTo($x, $y)
1776
    {
1777 16
        $this->StyleLine($this->lastx, $this->lasty, $x, $y);
1778 16
        $this->lastx = $x;
1779 16
        $this->lasty = $y;
1780 16
    }
1781
1782
    public function LineTo($x, $y)
1783
    {
1784
        $this->Line($this->lastx, $this->lasty, $x, $y);
1785
        $this->lastx = $x;
1786
        $this->lasty = $y;
1787
    }
1788
1789
    public function Point($x, $y)
1790
    {
1791
        imagesetpixel($this->img, round($x), round($y), $this->current_color);
0 ignored issues
show
Bug introduced by
round($y) of type double is incompatible with the type integer expected by parameter $y of imagesetpixel(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1791
        imagesetpixel($this->img, round($x), /** @scrutinizer ignore-type */ round($y), $this->current_color);
Loading history...
Bug introduced by
round($x) of type double is incompatible with the type integer expected by parameter $x of imagesetpixel(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1791
        imagesetpixel($this->img, /** @scrutinizer ignore-type */ round($x), round($y), $this->current_color);
Loading history...
1792
    }
1793
1794
    public function Fill($x, $y)
1795
    {
1796
        imagefill($this->img, round($x), round($y), $this->current_color);
0 ignored issues
show
Bug introduced by
round($x) of type double is incompatible with the type integer expected by parameter $x of imagefill(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1796
        imagefill($this->img, /** @scrutinizer ignore-type */ round($x), round($y), $this->current_color);
Loading history...
Bug introduced by
round($y) of type double is incompatible with the type integer expected by parameter $y of imagefill(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1796
        imagefill($this->img, round($x), /** @scrutinizer ignore-type */ round($y), $this->current_color);
Loading history...
1797
    }
1798
1799
    public function FillToBorder($x, $y, $aBordColor)
1800
    {
1801
        $bc = $this->rgb->allocate($aBordColor);
1802
        if ($bc == -1) {
1803
            Util\JpGraphError::RaiseL(25106); //('Image::FillToBorder : Can not allocate more colors');
1804
        }
1805
        imagefilltoborder($this->img, round($x), round($y), $bc, $this->current_color);
0 ignored issues
show
Bug introduced by
round($x) of type double is incompatible with the type integer expected by parameter $x of imagefilltoborder(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1805
        imagefilltoborder($this->img, /** @scrutinizer ignore-type */ round($x), round($y), $bc, $this->current_color);
Loading history...
Bug introduced by
round($y) of type double is incompatible with the type integer expected by parameter $y of imagefilltoborder(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1805
        imagefilltoborder($this->img, round($x), /** @scrutinizer ignore-type */ round($y), $bc, $this->current_color);
Loading history...
1806
    }
1807
1808
    public function SetExpired($aFlg = true)
1809
    {
1810
        $this->expired = $aFlg;
1811
    }
1812
1813
    // Generate image header
1814 21
    public function Headers()
1815
    {
1816
        // In case we are running from the command line with the client version of
1817
        // PHP we can't send any headers.
1818 21
        $sapi = php_sapi_name();
1819 21
        if ($sapi == 'cli') {
1820 21
            return;
1821
        }
1822
1823
        // These parameters are set by headers_sent() but they might cause
1824
        // an undefined variable error unless they are initilized
1825
        $file   = '';
1826
        $lineno = '';
1827
        if (headers_sent($file, $lineno)) {
0 ignored issues
show
Bug introduced by
$lineno of type string is incompatible with the type integer expected by parameter $line of headers_sent(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1827
        if (headers_sent($file, /** @scrutinizer ignore-type */ $lineno)) {
Loading history...
1828
            $file = basename($file);
1829
            $t    = new ErrMsgText();
1830
            $msg  = $t->Get(10, $file, $lineno);
1831
            die($msg);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1832
        }
1833
1834
        if ($this->expired) {
1835
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
1836
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT');
1837
            header('Cache-Control: no-cache, must-revalidate');
1838
            header('Pragma: no-cache');
1839
        }
1840
        header("Content-type: image/{$this->img_format}");
1841
    }
1842
1843
    // Adjust image quality for formats that allow this
1844
    public function SetQuality($q)
1845
    {
1846
        $this->quality = $q;
1847
    }
1848
1849
    // Stream image to browser or to file
1850 21
    public function Stream($aFile = '')
1851
    {
1852 21
        $this->DoSupersampling();
1853
1854 21
        $func = 'image' . $this->img_format;
1855 21
        if ($this->img_format == 'jpeg' && $this->quality != null) {
1856
            $res = @$func($this->img, $aFile, $this->quality);
0 ignored issues
show
Unused Code introduced by
The assignment to $res is dead and can be removed.
Loading history...
1857
        } else {
1858 21
            if ($aFile != '') {
1859
                $res = @$func($this->img, $aFile);
1860
                if (!$res) {
1861
                    Util\JpGraphError::RaiseL(25107, $aFile); //("Can't write to file '$aFile'. Check that the process running PHP has enough permission.");
1862
                }
1863
            } else {
1864 21
                $res = @$func($this->img);
1865 21
                if (!$res) {
1866
                    Util\JpGraphError::RaiseL(25108); //("Can't stream image. This is most likely due to a faulty PHP/GD setup. Try to recompile PHP and use the built-in GD library that comes with PHP.");
1867
                }
1868
            }
1869
        }
1870 21
    }
1871
1872
    // Do SuperSampling using $scale
1873 21
    public function DoSupersampling()
1874
    {
1875 21
        if (SUPERSAMPLING_SCALE <= 1) {
1876 21
            return $this->img;
1877
        }
1878
1879
        $dst_img = @imagecreatetruecolor($this->original_width, $this->original_height);
1880
        imagecopyresampled($dst_img, $this->img, 0, 0, 0, 0, $this->original_width, $this->original_height, $this->width, $this->height);
0 ignored issues
show
Bug introduced by
$this->width of type double is incompatible with the type integer expected by parameter $src_w of imagecopyresampled(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1880
        imagecopyresampled($dst_img, $this->img, 0, 0, 0, 0, $this->original_width, $this->original_height, /** @scrutinizer ignore-type */ $this->width, $this->height);
Loading history...
Bug introduced by
It seems like $dst_img can also be of type false; however, parameter $dst_image of imagecopyresampled() does only seem to accept GdImage|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1880
        imagecopyresampled(/** @scrutinizer ignore-type */ $dst_img, $this->img, 0, 0, 0, 0, $this->original_width, $this->original_height, $this->width, $this->height);
Loading history...
Bug introduced by
$this->height of type double is incompatible with the type integer expected by parameter $src_h of imagecopyresampled(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1880
        imagecopyresampled($dst_img, $this->img, 0, 0, 0, 0, $this->original_width, $this->original_height, $this->width, /** @scrutinizer ignore-type */ $this->height);
Loading history...
1881
        $this->Destroy();
1882
1883
        return $this->img = $dst_img;
1884
    }
1885
1886
    // Clear resources used by image (this is normally not used since all resources are/should be
1887
    // returned when the script terminates
1888 1
    public function Destroy()
1889
    {
1890 1
        imagedestroy($this->img);
1891 1
    }
1892
1893
    // Specify image format. Note depending on your installation
1894
    // of PHP not all formats may be supported.
1895 21
    public function SetImgFormat($aFormat, $aQuality = 75)
1896
    {
1897 21
        $this->quality = $aQuality;
1898 21
        $aFormat       = strtolower($aFormat);
1899 21
        $tst           = true;
1900 21
        $supported     = imagetypes();
1901 21
        if ($aFormat == 'auto') {
1902 21
            if ($supported & IMG_PNG) {
1903 21
                $this->img_format = 'png';
1904
            } elseif ($supported & IMG_JPG) {
1905
                $this->img_format = 'jpeg';
1906
            } elseif ($supported & IMG_GIF) {
1907
                $this->img_format = 'gif';
1908
            } elseif ($supported & IMG_WBMP) {
1909
                $this->img_format = 'wbmp';
1910
            } elseif ($supported & IMG_XPM) {
1911
                $this->img_format = 'xpm';
1912
            } else {
1913
                Util\JpGraphError::RaiseL(25109); //("Your PHP (and GD-lib) installation does not appear to support any known graphic formats. You need to first make sure GD is compiled as a module to PHP. If you also want to use JPEG images you must get the JPEG library. Please see the PHP docs for details.");
1914
            }
1915
1916 21
            return true;
1917
        }
1918
        if ($aFormat == 'jpeg' || $aFormat == 'png' || $aFormat == 'gif') {
1919
            if ($aFormat == 'jpeg' && !($supported & IMG_JPG)) {
1920
                $tst = false;
1921
            } elseif ($aFormat == 'png' && !($supported & IMG_PNG)) {
1922
                $tst = false;
1923
            } elseif ($aFormat == 'gif' && !($supported & IMG_GIF)) {
1924
                $tst = false;
1925
            } elseif ($aFormat == 'wbmp' && !($supported & IMG_WBMP)) {
1926
                $tst = false;
1927
            } elseif ($aFormat == 'xpm' && !($supported & IMG_XPM)) {
1928
                $tst = false;
1929
            } else {
1930
                $this->img_format = $aFormat;
1931
1932
                return true;
1933
            }
1934
        } else {
1935
            $tst = false;
1936
        }
1937
        if (!$tst) {
0 ignored issues
show
introduced by
The condition $tst is always false.
Loading history...
1938
            Util\JpGraphError::RaiseL(25110, $aFormat); //(" Your PHP installation does not support the chosen graphic format: $aFormat");
1939
        }
1940
    }
1941
1942
    /**
1943
     * Draw Line.
1944
     *
1945
     * @param mixed $im
1946
     * @param mixed $x1
1947
     * @param mixed $y1
1948
     * @param mixed $x2
1949
     * @param mixed $y2
1950
     * @param mixed $weight
1951
     * @param mixed $color
1952
     */
1953
    public function DrawLine($im, $x1, $y1, $x2, $y2, $weight, $color)
1954
    {
1955
        if ($weight == 1) {
1956
            return imageline($im, $x1, $y1, $x2, $y2, $color);
1957
        }
1958
1959
        $angle = (atan2(($y1 - $y2), ($x2 - $x1)));
1960
1961
        $dist_x = $weight * (sin($angle)) / 2;
1962
        $dist_y = $weight * (cos($angle)) / 2;
1963
1964
        $p1x = ceil(($x1 + $dist_x));
1965
        $p1y = ceil(($y1 + $dist_y));
1966
        $p2x = ceil(($x2 + $dist_x));
1967
        $p2y = ceil(($y2 + $dist_y));
1968
        $p3x = ceil(($x2 - $dist_x));
1969
        $p3y = ceil(($y2 - $dist_y));
1970
        $p4x = ceil(($x1 - $dist_x));
1971
        $p4y = ceil(($y1 - $dist_y));
1972
1973
        $array = [$p1x, $p1y, $p2x, $p2y, $p3x, $p3y, $p4x, $p4y];
1974
        imagefilledpolygon($im, $array, (safe_count($array) / 2), $color);
1975
1976
        // for antialias
1977
        imageline($im, $p1x, $p1y, $p2x, $p2y, $color);
0 ignored issues
show
Bug introduced by
$p2x of type double is incompatible with the type integer expected by parameter $x2 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1977
        imageline($im, $p1x, $p1y, /** @scrutinizer ignore-type */ $p2x, $p2y, $color);
Loading history...
Bug introduced by
$p2y of type double is incompatible with the type integer expected by parameter $y2 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1977
        imageline($im, $p1x, $p1y, $p2x, /** @scrutinizer ignore-type */ $p2y, $color);
Loading history...
Bug introduced by
$p1y of type double is incompatible with the type integer expected by parameter $y1 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1977
        imageline($im, $p1x, /** @scrutinizer ignore-type */ $p1y, $p2x, $p2y, $color);
Loading history...
Bug introduced by
$p1x of type double is incompatible with the type integer expected by parameter $x1 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1977
        imageline($im, /** @scrutinizer ignore-type */ $p1x, $p1y, $p2x, $p2y, $color);
Loading history...
1978
        imageline($im, $p3x, $p3y, $p4x, $p4y, $color);
1979
1980
        return;
1981
1982
        return imageline($this->img, $x1, $y1, $x2, $y2, $this->current_color);
0 ignored issues
show
Unused Code introduced by
return imageline($this->..., $this->current_color) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1983
        $weight = 8;
1984
        if ($weight <= 1) {
1985
            return imageline($this->img, $x1, $y1, $x2, $y2, $this->current_color);
1986
        }
1987
1988
        $pts = [];
1989
1990
        $weight /= 2;
1991
1992
        if ($y2 - $y1 == 0) {
1993
            // x line
1994
            $pts   = [];
1995
            $pts[] = $x1;
1996
            $pts[] = $y1 - $weight;
1997
            $pts[] = $x1;
1998
            $pts[] = $y1 + $weight;
1999
            $pts[] = $x2;
2000
            $pts[] = $y2 + $weight;
2001
            $pts[] = $x2;
2002
            $pts[] = $y2 - $weight;
2003
        } elseif ($x2 - $x1 == 0) {
2004
            // y line
2005
            $pts   = [];
2006
            $pts[] = $x1 - $weight;
2007
            $pts[] = $y1;
2008
            $pts[] = $x1 + $weight;
2009
            $pts[] = $y1;
2010
            $pts[] = $x2 + $weight;
2011
            $pts[] = $y2;
2012
            $pts[] = $x2 - $weight;
2013
            $pts[] = $y2;
2014
        } else {
2015
            $length = sqrt(pow($x2 - $x1, 2) + pow($y2 - $y1, 2));
2016
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
2017
2018
            /*
2019
        $lean = ($y2 - $y1) / ($x2 - $x1);
2020
        $lean2 = -1 / $lean;
2021
        $sin = $lean / ($y2 - $y1);
2022
        $cos = $lean / ($x2 - $x1);
2023
2024
        $pts[] = $x1 + (-$weight * $sin); $pts[] = $y1 + (-$weight * $cos);
2025
        $pts[] = $x1 + (+$weight * $sin); $pts[] = $y1 + (+$weight * $cos);
2026
        $pts[] = $x2 + (+$weight * $sin); $pts[] = $y2 + (+$weight * $cos);
2027
        $pts[] = $x2 + (-$weight * $sin); $pts[] = $y2 + (-$weight * $cos);
2028
         */
2029
        }
2030
2031
        //print_r($pts);exit;
2032
        if (safe_count($pts) / 2 < 3) {
2033
            return;
2034
        }
2035
2036
        imagesetthickness($im, 1);
2037
        imagefilledpolygon($im, $pts, safe_count($pts) / 2, $color);
2038
2039
        $weight *= 2;
2040
2041
        //        $this->DrawImageSmoothArc($im, $x1, $y1, $weight, $weight, 0, 360, $color);
2042
        //        $this->DrawImageSmoothArc($im, $x2, $y2, $weight, $weight, 0, 360, $color);
2043
    }
2044
2045
    public function DrawImageSmoothArc($im, $xc, $yc, $w, $h, $s, $e, $color, $style = null)
2046
    {
2047
        $tmp = $s;
2048
        $s   = (360 - $e) / 180 * M_PI;
2049
        $e   = (360 - $tmp) / 180 * M_PI;
2050
2051
        return $this->imageSmoothArc($im, round($xc), round($yc), round($w), round($h), $this->CreateColorForImageSmoothArc($color), $s, $e);
2052
    }
2053
2054
    public function CreateColorForImageSmoothArc($color)
2055
    {
2056
        $alpha = $color >> 24 & 0xFF;
2057
        $red   = $color >> 16 & 0xFF;
2058
        $green = $color >> 8 & 0xFF;
2059
        $blue  = $color & 0xFF;
2060
2061
        return [$red, $green, $blue, $alpha];
2062
    }
2063
2064
    public function imageSmoothCircle(&$img, $cx, $cy, $cr, $color)
2065
    {
2066
        $ir   = $cr;
2067
        $ix   = 0;
2068
        $iy   = $ir;
2069
        $ig   = 2 * $ir - 3;
2070
        $idgr = -6;
2071
        $idgd = 4 * $ir - 10;
2072
        $fill = imagecolorexactalpha($img, $color['R'], $color['G'], $color['B'], 0);
2073
        imageline($img, $cx + $cr - 1, $cy, $cx, $cy, $fill);
2074
        imageline($img, $cx - $cr + 1, $cy, $cx - 1, $cy, $fill);
2075
        imageline($img, $cx, $cy + $cr - 1, $cx, $cy + 1, $fill);
2076
        imageline($img, $cx, $cy - $cr + 1, $cx, $cy - 1, $fill);
2077
        $draw = imagecolorexactalpha($img, $color['R'], $color['G'], $color['B'], 42);
2078
        imagesetpixel($img, $cx + $cr, $cy, $draw);
2079
        imagesetpixel($img, $cx - $cr, $cy, $draw);
2080
        imagesetpixel($img, $cx, $cy + $cr, $draw);
2081
        imagesetpixel($img, $cx, $cy - $cr, $draw);
2082
        while ($ix <= $iy - 2) {
2083
            if ($ig < 0) {
2084
                $ig += $idgd;
2085
                $idgd -= 8;
2086
                --$iy;
2087
            } else {
2088
                $ig += $idgr;
2089
                $idgd -= 4;
2090
            }
2091
            $idgr -= 4;
2092
            ++$ix;
2093
            imageline($img, $cx + $ix, $cy + $iy - 1, $cx + $ix, $cy + $ix, $fill);
2094
            imageline($img, $cx + $ix, $cy - $iy + 1, $cx + $ix, $cy - $ix, $fill);
2095
            imageline($img, $cx - $ix, $cy + $iy - 1, $cx - $ix, $cy + $ix, $fill);
2096
            imageline($img, $cx - $ix, $cy - $iy + 1, $cx - $ix, $cy - $ix, $fill);
2097
            imageline($img, $cx + $iy - 1, $cy + $ix, $cx + $ix, $cy + $ix, $fill);
2098
            imageline($img, $cx + $iy - 1, $cy - $ix, $cx + $ix, $cy - $ix, $fill);
2099
            imageline($img, $cx - $iy + 1, $cy + $ix, $cx - $ix, $cy + $ix, $fill);
2100
            imageline($img, $cx - $iy + 1, $cy - $ix, $cx - $ix, $cy - $ix, $fill);
2101
            $filled = 0;
2102
            for ($xx = $ix - 0.45; $xx < $ix + 0.5; $xx += 0.2) {
2103
                for ($yy = $iy - 0.45; $yy < $iy + 0.5; $yy += 0.2) {
2104
                    if (sqrt(pow($xx, 2) + pow($yy, 2)) < $cr) {
2105
                        $filled += 4;
2106
                    }
2107
                }
2108
            }
2109
            $draw = imagecolorexactalpha($img, $color['R'], $color['G'], $color['B'], (100 - $filled));
2110
            imagesetpixel($img, $cx + $ix, $cy + $iy, $draw);
2111
            imagesetpixel($img, $cx + $ix, $cy - $iy, $draw);
2112
            imagesetpixel($img, $cx - $ix, $cy + $iy, $draw);
2113
            imagesetpixel($img, $cx - $ix, $cy - $iy, $draw);
2114
            imagesetpixel($img, $cx + $iy, $cy + $ix, $draw);
2115
            imagesetpixel($img, $cx + $iy, $cy - $ix, $draw);
2116
            imagesetpixel($img, $cx - $iy, $cy + $ix, $draw);
2117
            imagesetpixel($img, $cx - $iy, $cy - $ix, $draw);
2118
        }
2119
    }
2120
2121 21
    public function __get($name)
2122
    {
2123 21
        if (strpos($name, 'raw_') !== false) {
2124
            // if $name == 'raw_left_margin' , return $this->_left_margin;
2125 15
            $variable_name = '_' . str_replace('raw_', '', $name);
2126
2127 15
            return $this->{$variable_name};
2128
        }
2129
2130 21
        $variable_name = '_' . $name;
2131
2132 21
        if (isset($this->{$variable_name})) {
2133 21
            return $this->{$variable_name} * SUPERSAMPLING_SCALE;
2134
        }
2135
        Util\JpGraphError::RaiseL('25132', $name);
2136
    }
2137
2138 21
    public function __set($name, $value)
2139
    {
2140 21
        $this->{'_' . $name} = $value;
2141 21
    }
2142
2143
    /**
2144
     * Originally written from scratch by Ulrich Mierendorff, 06/2006
2145
     * Rewritten and improved, 04/2007, 07/2007.
2146
     *
2147
     * @param mixed $cx
2148
     * @param mixed $cy
2149
     * @param mixed $a
2150
     * @param mixed $b
2151
     * @param mixed $aaAngleX
2152
     * @param mixed $aaAngleY
2153
     * @param mixed $color
2154
     * @param mixed $start
2155
     * @param mixed $stop
2156
     * @param mixed $seg
2157
     * @param mixed $img
2158
     */
2159
    private function _imageSmoothArcDrawSegment(&$img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $start, $stop, $seg)
2160
    {
2161
        $fillColor = imagecolorexactalpha($img, $color[0], $color[1], $color[2], $color[3]);
2162
2163
        $xStart  = abs($a * cos($start));
2164
        $yStart  = abs($b * sin($start));
2165
        $xStop   = abs($a * cos($stop));
2166
        $yStop   = abs($b * sin($stop));
2167
        $dxStart = 0;
2168
        $dyStart = 0;
2169
        $dxStop  = 0;
2170
        $dyStop  = 0;
2171
        if ($xStart != 0) {
2172
            $dyStart = $yStart / $xStart;
2173
        }
2174
        if ($xStop != 0) {
2175
            $dyStop = $yStop / $xStop;
2176
        }
2177
        if ($yStart != 0) {
2178
            $dxStart = $xStart / $yStart;
2179
        }
2180
        if ($yStop != 0) {
2181
            $dxStop = $xStop / $yStop;
2182
        }
2183
        if (abs($xStart) >= abs($yStart)) {
2184
            $aaStartX = true;
2185
        } else {
2186
            $aaStartX = false;
2187
        }
2188
        if ($xStop >= $yStop) {
2189
            $aaStopX = true;
2190
        } else {
2191
            $aaStopX = false;
2192
        }
2193
        //$xp = +1; $yp = -1; $xa = +1; $ya = 0;
2194
        for ($x = 0; $x < $a; ++$x) {
2195
            /*$y = $b * sqrt( 1 - ($x*$x)/($a*$a) );
2196
2197
            $error = $y - (int)($y);
2198
            $y = (int)($y);
2199
2200
            $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );*/
2201
2202
            $_y1 = $dyStop * $x;
2203
            $_y2 = $dyStart * $x;
2204
            if ($xStart > $xStop) {
2205
                $error1 = $_y1 - (int) ($_y1);
2206
                $error2 = 1 - $_y2 + (int) $_y2;
2207
                $_y1    = $_y1 - $error1;
2208
                $_y2    = $_y2 + $error2;
2209
            } else {
2210
                $error1 = 1 - $_y1 + (int) $_y1;
2211
                $error2 = $_y2 - (int) ($_y2);
2212
                $_y1    = $_y1 + $error1;
2213
                $_y2    = $_y2 - $error2;
2214
            }
2215
            /*
2216
            if ($aaStopX)
2217
            $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 );
2218
            if ($aaStartX)
2219
            $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 );
2220
             */
2221
2222
            if ($seg == 0 || $seg == 2) {
2223
                $i = $seg;
2224
                if (!($start > $i * M_PI / 2 && $x > $xStart)) {
2225
                    if ($i == 0) {
2226
                        $xp = +1;
2227
                        $yp = -1;
2228
                        $xa = +1;
2229
                        $ya = 0;
2230
                    } else {
2231
                        $xp = -1;
2232
                        $yp = +1;
2233
                        $xa = 0;
2234
                        $ya = +1;
2235
                    }
2236
                    if ($stop < ($i + 1) * (M_PI / 2) && $x <= $xStop) {
2237
                        $diffColor1 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error1);
0 ignored issues
show
Bug introduced by
127 - 127 - $color[3] * $error1 of type double is incompatible with the type integer expected by parameter $alpha of imagecolorexactalpha(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2237
                        $diffColor1 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], /** @scrutinizer ignore-type */ 127 - (127 - $color[3]) * $error1);
Loading history...
2238
                        $y1         = $_y1;
2239
                        if ($aaStopX) {
2240
                            imagesetpixel($img, $cx + $xp * ($x) + $xa, $cy + $yp * ($y1 + 1) + $ya, $diffColor1);
0 ignored issues
show
Bug introduced by
$cy + $yp * $y1 + 1 + $ya of type double is incompatible with the type integer expected by parameter $y of imagesetpixel(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2240
                            imagesetpixel($img, $cx + $xp * ($x) + $xa, /** @scrutinizer ignore-type */ $cy + $yp * ($y1 + 1) + $ya, $diffColor1);
Loading history...
2241
                        }
2242
                    } else {
2243
                        $y         = $b * sqrt(1 - ($x * $x) / ($a * $a));
2244
                        $error     = $y - (int) ($y);
2245
                        $y         = (int) ($y);
2246
                        $diffColor = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error);
2247
                        $y1        = $y;
2248
                        if ($x < $aaAngleX) {
2249
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y1 + 1) + $ya, $diffColor);
2250
                        }
2251
                    }
2252
                    if ($start > $i * M_PI / 2 && $x <= $xStart) {
2253
                        $diffColor2 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error2);
2254
                        $y2         = $_y2;
2255
                        if ($aaStartX) {
2256
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y2 - 1) + $ya, $diffColor2);
2257
                        }
2258
                    } else {
2259
                        $y2 = 0;
2260
                    }
2261
                    if ($y2 <= $y1) {
2262
                        imageline($img, $cx + $xp * $x + $xa, $cy + $yp * $y1 + $ya, $cx + $xp * $x + $xa, $cy + $yp * $y2 + $ya, $fillColor);
0 ignored issues
show
Bug introduced by
$cy + $yp * $y2 + $ya of type double is incompatible with the type integer expected by parameter $y2 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2262
                        imageline($img, $cx + $xp * $x + $xa, $cy + $yp * $y1 + $ya, $cx + $xp * $x + $xa, /** @scrutinizer ignore-type */ $cy + $yp * $y2 + $ya, $fillColor);
Loading history...
Bug introduced by
$cy + $yp * $y1 + $ya of type double is incompatible with the type integer expected by parameter $y1 of imageline(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2262
                        imageline($img, $cx + $xp * $x + $xa, /** @scrutinizer ignore-type */ $cy + $yp * $y1 + $ya, $cx + $xp * $x + $xa, $cy + $yp * $y2 + $ya, $fillColor);
Loading history...
2263
                    }
2264
                }
2265
            }
2266
2267
            if ($seg == 1 || $seg == 3) {
2268
                $i = $seg;
2269
                if (!($stop < ($i + 1) * M_PI / 2 && $x > $xStop)) {
2270
                    if ($i == 1) {
2271
                        $xp = -1;
2272
                        $yp = -1;
2273
                        $xa = 0;
2274
                        $ya = 0;
2275
                    } else {
2276
                        $xp = +1;
2277
                        $yp = +1;
2278
                        $xa = 1;
2279
                        $ya = 1;
2280
                    }
2281
                    if ($start > $i * M_PI / 2 && $x < $xStart) {
2282
                        $diffColor2 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error2);
2283
                        $y1         = $_y2;
2284
                        if ($aaStartX) {
2285
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y1 + 1) + $ya, $diffColor2);
2286
                        }
2287
                    } else {
2288
                        $y         = $b * sqrt(1 - ($x * $x) / ($a * $a));
2289
                        $error     = $y - (int) ($y);
2290
                        $y         = (int) $y;
2291
                        $diffColor = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error);
2292
                        $y1        = $y;
2293
                        if ($x < $aaAngleX) {
2294
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y1 + 1) + $ya, $diffColor);
2295
                        }
2296
                    }
2297
                    if ($stop < ($i + 1) * M_PI / 2 && $x <= $xStop) {
2298
                        $diffColor1 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error1);
2299
                        $y2         = $_y1;
2300
                        if ($aaStopX) {
2301
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y2 - 1) + $ya, $diffColor1);
2302
                        }
2303
                    } else {
2304
                        $y2 = 0;
2305
                    }
2306
                    if ($y2 <= $y1) {
2307
                        imageline($img, $cx + $xp * $x + $xa, $cy + $yp * $y1 + $ya, $cx + $xp * $x + $xa, $cy + $yp * $y2 + $ya, $fillColor);
2308
                    }
2309
                }
2310
            }
2311
        }
2312
2313
        ///YYYYY
2314
2315
        for ($y = 0; $y < $b; ++$y) {
2316
            /*$x = $a * sqrt( 1 - ($y*$y)/($b*$b) );
2317
2318
            $error = $x - (int)($x);
2319
            $x = (int)($x);
2320
2321
            $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );
2322
             */
2323
            $_x1 = $dxStop * $y;
2324
            $_x2 = $dxStart * $y;
2325
            if ($yStart > $yStop) {
2326
                $error1 = $_x1 - (int) ($_x1);
2327
                $error2 = 1 - $_x2 + (int) $_x2;
2328
                $_x1    = $_x1 - $error1;
2329
                $_x2    = $_x2 + $error2;
2330
            } else {
2331
                $error1 = 1 - $_x1 + (int) $_x1;
2332
                $error2 = $_x2 - (int) ($_x2);
2333
                $_x1    = $_x1 + $error1;
2334
                $_x2    = $_x2 - $error2;
2335
            }
2336
            /*
2337
            if (!$aaStopX)
2338
            $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 );
2339
            if (!$aaStartX)
2340
            $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 );
2341
             */
2342
2343
            if ($seg == 0 || $seg == 2) {
2344
                $i = $seg;
2345
                if (!($start > $i * M_PI / 2 && $y > $yStop)) {
2346
                    if ($i == 0) {
2347
                        $xp = +1;
2348
                        $yp = -1;
2349
                        $xa = 1;
2350
                        $ya = 0;
2351
                    } else {
2352
                        $xp = -1;
2353
                        $yp = +1;
2354
                        $xa = 0;
2355
                        $ya = 1;
2356
                    }
2357
                    if ($stop < ($i + 1) * (M_PI / 2) && $y <= $yStop) {
2358
                        $diffColor1 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error1);
2359
                        $x1         = $_x1;
2360
                        if (!$aaStopX) {
2361
                            imagesetpixel($img, $cx + $xp * ($x1 - 1) + $xa, $cy + $yp * ($y) + $ya, $diffColor1);
0 ignored issues
show
Bug introduced by
$cx + $xp * $x1 - 1 + $xa of type double is incompatible with the type integer expected by parameter $x of imagesetpixel(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2361
                            imagesetpixel($img, /** @scrutinizer ignore-type */ $cx + $xp * ($x1 - 1) + $xa, $cy + $yp * ($y) + $ya, $diffColor1);
Loading history...
2362
                        }
2363
                    }
2364
                    if ($start > $i * M_PI / 2 && $y < $yStart) {
2365
                        $diffColor2 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error2);
2366
                        $x2         = $_x2;
2367
                        if (!$aaStartX) {
2368
                            imagesetpixel($img, $cx + $xp * ($x2 + 1) + $xa, $cy + $yp * ($y) + $ya, $diffColor2);
2369
                        }
2370
                    } else {
2371
                        $x         = $a * sqrt(1 - ($y * $y) / ($b * $b));
2372
                        $error     = $x - (int) ($x);
2373
                        $x         = (int) ($x);
2374
                        $diffColor = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error);
2375
                        $x1        = $x;
2376
                        if ($y < $aaAngleY && $y <= $yStop) {
2377
                            imagesetpixel($img, $cx + $xp * ($x1 + 1) + $xa, $cy + $yp * $y + $ya, $diffColor);
2378
                        }
2379
                    }
2380
                }
2381
            }
2382
2383
            if ($seg == 1 || $seg == 3) {
2384
                $i = $seg;
2385
                if (!($stop < ($i + 1) * M_PI / 2 && $y > $yStart)) {
2386
                    if ($i == 1) {
2387
                        $xp = -1;
2388
                        $yp = -1;
2389
                        $xa = 0;
2390
                        $ya = 0;
2391
                    } else {
2392
                        $xp = +1;
2393
                        $yp = +1;
2394
                        $xa = 1;
2395
                        $ya = 1;
2396
                    }
2397
                    if ($start > $i * M_PI / 2 && $y < $yStart) {
2398
                        $diffColor2 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error2);
2399
                        $x1         = $_x2;
2400
                        if (!$aaStartX) {
2401
                            imagesetpixel($img, $cx + $xp * ($x1 - 1) + $xa, $cy + $yp * $y + $ya, $diffColor2);
2402
                        }
2403
                    }
2404
                    if ($stop < ($i + 1) * M_PI / 2 && $y <= $yStop) {
2405
                        $diffColor1 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error1);
2406
                        $x2         = $_x1;
2407
                        if (!$aaStopX) {
2408
                            imagesetpixel($img, $cx + $xp * ($x2 + 1) + $xa, $cy + $yp * $y + $ya, $diffColor1);
2409
                        }
2410
                    } else {
2411
                        $x         = $a * sqrt(1 - ($y * $y) / ($b * $b));
2412
                        $error     = $x - (int) ($x);
2413
                        $x         = (int) ($x);
2414
                        $diffColor = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error);
2415
                        $x1        = $x;
2416
                        if ($y < $aaAngleY && $y < $yStart) {
2417
                            imagesetpixel($img, $cx + $xp * ($x1 + 1) + $xa, $cy + $yp * $y + $ya, $diffColor);
2418
                        }
2419
                    }
2420
                }
2421
            }
2422
        }
2423
    }
2424
2425
    public function imageSmoothArc(&$img, $cx, $cy, $w, $h, $color, $start, $stop)
2426
    {
2427
        // Originally written from scratch by Ulrich Mierendorff, 06/2006
2428
        // Rewritten and improved, 04/2007, 07/2007
2429
        // compared to old version:
2430
        // + Support for transparency added
2431
        // + Improved quality of edges & antialiasing
2432
2433
        // note: This function does not represent the fastest way to draw elliptical
2434
        // arcs. It was written without reading any papers on that subject. Better
2435
        // algorithms may be twice as fast or even more.
2436
2437
        // what it cannot do: It does not support outlined arcs, only filled
2438
2439
        // Parameters:
2440
        // $cx      - Center of ellipse, X-coord
2441
        // $cy      - Center of ellipse, Y-coord
2442
        // $w       - Width of ellipse ($w >= 2)
2443
        // $h       - Height of ellipse ($h >= 2 )
2444
        // $color   - Color of ellipse as a four component array with RGBA
2445
        // $start   - Starting angle of the arc, no limited range!
2446
        // $stop    - Stop     angle of the arc, no limited range!
2447
        // $start _can_ be greater than $stop!
2448
        // If any value is not in the given range, results are undefined!
2449
2450
        // This script does not use any special algorithms, everything is completely
2451
        // written from scratch; see http://de.wikipedia.org/wiki/Ellipse for formulas.
2452
2453
        while ($start < 0) {
2454
            $start += 2 * M_PI;
2455
        }
2456
        while ($stop < 0) {
2457
            $stop += 2 * M_PI;
2458
        }
2459
2460
        while ($start > 2 * M_PI) {
2461
            $start -= 2 * M_PI;
2462
        }
2463
2464
        while ($stop > 2 * M_PI) {
2465
            $stop -= 2 * M_PI;
2466
        }
2467
2468
        if ($start > $stop) {
2469
            $this->imageSmoothArc($img, $cx, $cy, $w, $h, $color, $start, 2 * M_PI);
2470
            $this->imageSmoothArc($img, $cx, $cy, $w, $h, $color, 0, $stop);
2471
2472
            return;
2473
        }
2474
2475
        $a  = 1.0 * round($w / 2);
2476
        $b  = 1.0 * round($h / 2);
2477
        $cx = 1.0 * round($cx);
2478
        $cy = 1.0 * round($cy);
2479
2480
        $aaAngle  = atan(($b * $b) / ($a * $a) * tan(0.25 * M_PI));
2481
        $aaAngleX = $a * cos($aaAngle);
2482
        $aaAngleY = $b * sin($aaAngle);
2483
2484
        $a -= 0.5; // looks better...
2485
        $b -= 0.5;
2486
2487
        for ($i = 0; $i < 4; ++$i) {
2488
            if ($start < ($i + 1) * M_PI / 2) {
2489
                if ($start > $i * M_PI / 2) {
2490
                    if ($stop > ($i + 1) * M_PI / 2) {
2491
                        $this->_imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $start, ($i + 1) * M_PI / 2, $i);
2492
                    } else {
2493
                        $this->_imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $start, $stop, $i);
2494
2495
                        break;
2496
                    }
2497
                } else {
2498
                    if ($stop > ($i + 1) * M_PI / 2) {
2499
                        $this->_imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $i * M_PI / 2, ($i + 1) * M_PI / 2, $i);
2500
                    } else {
2501
                        $this->_imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $i * M_PI / 2, $stop, $i);
2502
2503
                        break;
2504
                    }
2505
                }
2506
            }
2507
        }
2508
    }
2509
} // @class
2510