Passed
Pull Request — master (#135)
by
unknown
05:40
created

Image   F

Complexity

Total Complexity 402

Size/Duplication

Total Lines 2482
Duplicated Lines 0 %

Test Coverage

Coverage 45.49%

Importance

Changes 7
Bugs 1 Features 1
Metric Value
eloc 1349
c 7
b 1
f 1
dl 0
loc 2482
ccs 621
cts 1365
cp 0.4549
rs 0.8
wmc 402

85 Methods

Rating   Name   Duplication   Size   Complexity  
A AddTxtCR() 0 13 2
A GetBBoxHeight() 0 5 1
A GetAntiAliasing() 0 3 1
A GetHeight() 0 7 2
A SetCanvasH() 0 4 1
A CloneCanvasH() 0 7 1
A SetInterlace() 0 3 1
F StrokeBoxedText2() 0 162 18
A SetAlphaBlending() 0 3 1
A GetWidth() 0 7 2
A SetCanvasColor() 0 3 1
A SetFont() 0 19 6
A GetFontHeight() 0 5 1
A CreateImgCanvas() 0 27 3
A GetFontWidth() 0 5 1
A CreateFromString() 0 9 2
A CopyCanvasH() 0 10 2
A SetTextAlign() 0 4 1
A SetAntiAliasing() 0 5 2
A __construct() 0 21 3
A SetAutoMargin() 0 8 1
A CreateRawCanvas() 0 23 6
A Copy() 0 3 1
A NormAngle() 0 17 4
B GetBBoxTTF() 0 54 11
F StrokeBoxedText() 0 112 13
B imagettfbbox_fixed() 0 85 10
A GetTextHeight() 0 28 6
B CopyMerge() 0 42 9
A GetTTFBBox() 0 5 1
B GetTextWidth() 0 42 9
A GetBBoxWidth() 0 5 1
F _StrokeBuiltinFont() 0 62 19
A Stream() 0 17 6
B DrawLine() 0 87 6
A FillToBorder() 0 7 2
A Bevel() 0 15 3
A ShadowRectangle() 0 41 4
A Arc() 0 12 3
B Polygon() 0 26 7
B imageSmoothCircle() 0 54 6
A __get() 0 15 3
A Circle() 0 3 1
A SetStartPoint() 0 4 1
B StyleLine() 0 49 11
A FilledBevel() 0 4 1
A CakeSlice() 0 33 4
A Line() 0 15 2
A PopColor() 0 7 2
A DashedLineForGrid() 0 33 3
A StyleLineTo() 0 5 1
A FilledPolygon() 0 14 3
A Rectangle() 0 3 1
A SetQuality() 0 3 1
A SetTransparent() 0 3 1
A Point() 0 3 1
A FilledRoundedRectangle() 0 30 2
A FilledArc() 0 18 5
A DashedLine() 0 28 3
A lip() 0 8 1
A FilledCircle() 0 3 1
B FilledRectangle2() 0 29 6
A Fill() 0 3 1
A __set() 0 3 1
A SetMargin() 0 13 5
A SetLineWeight() 0 7 1
A DoSupersampling() 0 11 2
A LineTo() 0 5 1
A SetExpired() 0 3 1
B SetLineStyle() 0 25 9
A DrawImageSmoothArc() 0 7 1
B imageSmoothArc() 0 79 11
A PushColor() 0 9 2
F _StrokeTTF() 0 210 30
F _imageSmoothArcDrawSegment() 0 259 63
A Headers() 0 27 4
A FilledRectangle() 0 3 1
D SetImgFormat() 0 44 21
A Destroy() 0 3 1
A Ellipse() 0 3 1
A StrokeText() 0 21 6
A RoundedRectangle() 0 23 2
A CreateColorForImageSmoothArc() 0 8 1
A SetColor() 0 11 2
A FilledCakeSlice() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Image often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Image, and based on these observations, apply Extract Interface, too.

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 = null)
267
    {
268 4
        if ($aImg === null) {
269
            $aImg = $this->img;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using $this inside a static method is generally not recommended and can lead to errors in newer PHP versions.
Loading history...
270
        }
271
272 4
        return imagesx($aImg);
273
    }
274
275 4
    public static function GetHeight($aImg = null)
276
    {
277 4
        if ($aImg === null) {
278
            $aImg = $this->img;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using $this inside a static method is generally not recommended and can lead to errors in newer PHP versions.
Loading history...
279
        }
280
281 4
        return imagesy($aImg);
282
    }
283
284 4
    public static function CreateFromString($aStr)
285
    {
286 4
        $img = imagecreatefromstring($aStr);
287 4
        if ($img === false) {
288
            Util\JpGraphError::RaiseL(25085);
289
            //('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.');
290
        }
291
292 4
        return $img;
293
    }
294
295 1
    public function SetCanvasH($aHdl)
296
    {
297 1
        $this->img      = $aHdl;
298 1
        $this->rgb->img = $aHdl;
299 1
    }
300
301
    public function SetCanvasColor($aColor)
302
    {
303
        $this->canvascolor = $aColor;
304
    }
305
306 21
    public function SetAlphaBlending($aFlg = true)
307
    {
308 21
        imagealphablending($this->img, $aFlg);
309 21
    }
310
311 21
    public function SetAutoMargin()
312
    {
313 21
        $min_bm = 5;
314 21
        $lm     = min(40, $this->width / 7);
315 21
        $rm     = min(20, $this->width / 10);
316 21
        $tm     = max(5, $this->height / 7);
317 21
        $bm     = max($min_bm, $this->height / 6);
318 21
        $this->SetMargin($lm, $rm, $tm, $bm);
319 21
    }
320
321
    /**
322
     * PUBLIC METHODS.
323
     *
324
     * @param mixed $family
325
     * @param mixed $style
326
     * @param mixed $size
327
     */
328 21
    public function SetFont($family, $style = FS_NORMAL, $size = 10)
329
    {
330 21
        $this->font_family = $family;
331 21
        $this->font_style  = $style;
332 21
        $this->font_size   = $size * SUPERSAMPLING_SCALE;
333 21
        $this->font_file   = '';
334 21
        if (($this->font_family == FF_FONT1 || $this->font_family == FF_FONT2) && $this->font_style == FS_BOLD) {
335 12
            ++$this->font_family;
336
        }
337 21
        if ($this->font_family > FF_FONT2 + 1) {
338
            // A TTF font so get the font file
339
340
            // Check that this PHP has support for TTF fonts
341 21
            if (!function_exists('imagettfbbox')) {
342
                // use internal font when php is configured without '--with-ttf'
343
                $this->font_family = FF_FONT1;
344
            //  Util\JpGraphError::RaiseL(25087);//('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.');
345
            } else {
346 21
                $this->font_file = $this->ttf->File($this->font_family, $this->font_style);
347
            }
348
        }
349 21
    }
350
351
    // Get the specific height for a text string
352 21
    public function GetTextHeight($txt = '', $angle = 0)
353
    {
354 21
        $tmp = preg_split('/\n/', $txt);
355 21
        $n   = safe_count($tmp);
356 21
        $m   = 0;
357 21
        for ($i = 0; $i < $n; ++$i) {
358 21
            $m = max($m, strlen($tmp[$i]));
359
        }
360
361 21
        if ($this->font_family <= FF_FONT2 + 1) {
362 12
            if ($angle == 0) {
363 12
                $h = imagefontheight($this->font_family);
364 12
                if ($h === false) {
365
                    Util\JpGraphError::RaiseL(25088); //('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
366
                }
367
368 12
                return $n * $h;
369
            }
370
            $w = @imagefontwidth($this->font_family);
371
            if ($w === false) {
372
                Util\JpGraphError::RaiseL(25088); //('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
373
            }
374
375
            return $m * $w;
376
        }
377 21
        $bbox = $this->GetTTFBBox($txt, $angle);
378
379 21
        return $bbox[1] - $bbox[5] + 1;
380
    }
381
382
    // Estimate font height
383 21
    public function GetFontHeight($angle = 0)
384
    {
385 21
        $txt = 'XOMg';
386
387 21
        return $this->GetTextHeight($txt, $angle);
388
    }
389
390
    // Approximate font width with width of letter "O"
391
    public function GetFontWidth($angle = 0)
392
    {
393
        $txt = 'O';
394
395
        return $this->GetTextWidth($txt, $angle);
396
    }
397
398
    // Get actual width of text in absolute pixels. Note that the width is the
399
    // texts projected with onto the x-axis. Call with angle=0 to get the true
400
    // etxt width.
401 18
    public function GetTextWidth($txt, $angle = 0)
402
    {
403 18
        $tmp = preg_split('/\n/', $txt);
404 18
        $n   = safe_count($tmp);
405 18
        if ($this->font_family <= FF_FONT2 + 1) {
406 12
            $m = 0;
407 12
            for ($i = 0; $i < $n; ++$i) {
408 12
                $l = strlen($tmp[$i]);
409 12
                if ($l > $m) {
410 11
                    $m = $l;
411
                }
412
            }
413
414 12
            if ($angle == 0) {
415 12
                $w = @imagefontwidth($this->font_family);
416 12
                if ($w === false) {
417
                    Util\JpGraphError::RaiseL(25088); //('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
418
                }
419
420 12
                return $m * $w;
421
            }
422
            // 90 degrees internal so height becomes width
423
            $h = @imagefontheight($this->font_family);
424
            if ($h === false) {
425
                Util\JpGraphError::RaiseL(25089); //('You have a misconfigured GD font support. The call to imagefontheight() fails.');
426
            }
427
428
            return $n * $h;
429
        }
430
        // For TTF fonts we must walk through a lines and find the
431
        // widest one which we use as the width of the multi-line
432
        // paragraph
433 14
        $m = 0;
434 14
        for ($i = 0; $i < $n; ++$i) {
435 14
            $bbox = $this->GetTTFBBox($tmp[$i], $angle);
436 14
            $mm   = $bbox[2] - $bbox[0];
437 14
            if ($mm > $m) {
438 14
                $m = $mm;
439
            }
440
        }
441
442 14
        return $m;
443
    }
444
445
    // Draw text with a box around it
446
    public function StrokeBoxedText(
447
        $x,
448
        $y,
449
        $txt,
450
        $dir = 0,
451
        $fcolor = 'white',
452
        $bcolor = 'black',
453
        $shadowcolor = false,
454
        $paragraph_align = 'left',
455
        $xmarg = 6,
456
        $ymarg = 4,
457
        $cornerradius = 0,
458
        $dropwidth = 3
459
    ) {
460
        $oldx = $this->lastx;
461
        $oldy = $this->lasty;
462
463
        if (!is_numeric($dir)) {
464
            if ($dir == 'h') {
465
                $dir = 0;
466
            } elseif ($dir == 'v') {
467
                $dir = 90;
468
            } else {
469
                Util\JpGraphError::RaiseL(25090, $dir);
470
            }
471
            //(" Unknown direction specified in call to StrokeBoxedText() [$dir]");
472
        }
473
474
        if ($this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2 + 1) {
475
            $width  = $this->GetTextWidth($txt, $dir);
476
            $height = $this->GetTextHeight($txt, $dir);
477
        } else {
478
            $width  = $this->GetBBoxWidth($txt, $dir);
479
            $height = $this->GetBBoxHeight($txt, $dir);
480
        }
481
482
        $height += 2 * $ymarg;
483
        $width += 2 * $xmarg;
484
485
        if ($this->text_halign == 'right') {
486
            $x -= $width;
487
        } elseif ($this->text_halign == 'center') {
488
            $x -= $width / 2;
489
        }
490
491
        if ($this->text_valign == 'bottom') {
492
            $y -= $height;
493
        } elseif ($this->text_valign == 'center') {
494
            $y -= $height / 2;
495
        }
496
497
        $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

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

631
        $this->/** @scrutinizer ignore-call */ 
632
               SetCenter($x, $y);
Loading history...
632
        $olda = $this->SetAngle(-$dir);
633
634
        // We need to use adjusted coordinats for the box to be able
635
        // to draw the box below the baseline. This cannot be done before since
636
        // the rotating point must be the original x,y since that is arounbf the
637
        // point where the text will rotate and we cannot change this since
638
        // that is where the GD/GreeType will rotate the text
639
640
        // For smaller <14pt font we need to do some additional
641
        // adjustments to make it look good
642
        if ($this->font_size < 14) {
643
            $x -= 2;
644
            $y += 2;
645
        }
646
        //  $y += $baseline_offset;
647
648
        if ($shadowcolor) {
649
            $this->PushColor($shadowcolor);
650
            $this->FilledRectangle(
651
                $x - $xmarg + $dropwidth,
652
                $y + $ymarg + $dropwidth - $height,
653
                $x + $width + $dropwidth,
654
                $y + $ymarg + $dropwidth
655
            );
656
            //$cornerradius);
657
            $this->PopColor();
658
            $this->PushColor($fcolor);
659
            $this->FilledRectangle(
660
                $x - $xmarg,
661
                $y + $ymarg - $height,
662
                $x + $width,
663
                $y + $ymarg
664
            );
665
            //$cornerradius);
666
            $this->PopColor();
667
            $this->PushColor($bcolor);
668
            $this->Rectangle(
669
                $x - $xmarg,
670
                $y + $ymarg - $height,
671
                $x + $width,
672
                $y + $ymarg
673
            );
674
            //$cornerradius);
675
            $this->PopColor();
676
        } else {
677
            if ($fcolor) {
678
                $oc = $this->current_color;
679
                $this->SetColor($fcolor);
680
                $this->FilledRectangle($x - $xmarg, $y + $ymarg - $height, $x + $width, $y + $ymarg); //,$cornerradius);
681
                $this->current_color = $oc;
682
            }
683
            if ($bcolor) {
684
                $oc = $this->current_color;
685
                $this->SetColor($bcolor);
686
                $this->Rectangle($x - $xmarg, $y + $ymarg - $height, $x + $width, $y + $ymarg); //,$cornerradius);
687
                $this->current_color = $oc;
688
            }
689
        }
690
691
        if ($this->font_size < 14) {
692
            $x += 2;
693
            $y -= 2;
694
        }
695
696
        // Restore the original y before we stroke the text
697
        // $y -= $baseline_offset;
698
699
        $this->SetCenter(0, 0);
700
        $this->SetAngle($olda);
701
702
        $h = $this->text_halign;
703
        $v = $this->text_valign;
704
        if ($this->text_halign == 'center') {
705
            $this->SetTextAlign('center', 'basepoint');
706
        } else {
707
            $this->SetTextAlign('basepoint', 'basepoint');
708
        }
709
710
        $debug = false;
711
        $this->StrokeText($x, $y, $txt, $dir, $paragraph_align, $debug);
712
713
        $bb = [$x - $xmarg, $y + $height - $ymarg,
714
            $x + $width, $y + $height - $ymarg,
715
            $x + $width, $y - $ymarg,
716
            $x - $xmarg, $y - $ymarg, ];
717
718
        $this->SetTextAlign($h, $v);
719
        $this->SetAngle($olda);
720
721
        $this->lastx = $oldx;
722
        $this->lasty = $oldy;
723
724
        return $bb;
725
    }
726
727
    // Set text alignment
728 21
    public function SetTextAlign($halign, $valign = 'bottom')
729
    {
730 21
        $this->text_halign = $halign;
731 21
        $this->text_valign = $valign;
732 21
    }
733
734 12
    public function _StrokeBuiltinFont($x, $y, $txt, $dir, $paragraph_align, &$aBoundingBox, $aDebug = false)
735
    {
736 12
        if (is_numeric($dir) && $dir != 90 && $dir != 0) {
737
            Util\JpGraphError::RaiseL(25091);
738
        }
739
        //(" Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead.");
740
741 12
        $h  = $this->GetTextHeight($txt);
742 12
        $fh = $this->GetFontHeight();
743 12
        $w  = $this->GetTextWidth($txt);
744
745 12
        if ($this->text_halign == 'right') {
746 6
            $x -= $dir == 0 ? $w : $h;
747 12
        } elseif ($this->text_halign == 'center') {
748
            // For center we subtract 1 pixel since this makes the middle
749
            // be prefectly in the middle
750 11
            $x -= $dir == 0 ? $w / 2 - 1 : $h / 2;
751
        }
752 12
        if ($this->text_valign == 'top') {
753 10
            $y += $dir == 0 ? $h : $w;
754 9
        } elseif ($this->text_valign == 'center') {
755 7
            $y += $dir == 0 ? $h / 2 : $w / 2;
756
        }
757
758 12
        $use_font = $this->font_family;
759
760 12
        if ($dir == 90) {
761 4
            imagestringup($this->img, $use_font, $x, $y, $txt, $this->current_color);
762 4
            $aBoundingBox = [round($x), round($y), round($x), round($y - $w), round($x + $h), round($y - $w), round($x + $h), round($y)];
763 4
            if ($aDebug) {
764
                // Draw bounding box
765
                $this->PushColor('green');
766
                $this->Polygon($aBoundingBox, true);
767 4
                $this->PopColor();
768
            }
769
        } else {
770 12
            if (preg_match('/\n/', $txt)) {
771 2
                $tmp = preg_split('/\n/', $txt);
772 2
                for ($i = 0; $i < safe_count($tmp); ++$i) {
773 2
                    $w1 = $this->GetTextWidth($tmp[$i]);
774 2
                    if ($paragraph_align == 'left') {
775 1
                        imagestring($this->img, $use_font, $x, $y - $h + 1 + $i * $fh, $tmp[$i], $this->current_color);
776 1
                    } elseif ($paragraph_align == 'right') {
777
                        imagestring($this->img, $use_font, $x + ($w - $w1), $y - $h + 1 + $i * $fh, $tmp[$i], $this->current_color);
778
                    } else {
779 1
                        imagestring($this->img, $use_font, $x + $w / 2 - $w1 / 2, $y - $h + 1 + $i * $fh, $tmp[$i], $this->current_color);
780
                    }
781
                }
782
            } else {
783
                //Put the text
784 11
                imagestring($this->img, $use_font, $x, $y - $h + 1, $txt, $this->current_color);
785
            }
786 12
            if ($aDebug) {
787
                // Draw the bounding rectangle and the bounding box
788
                $p1 = [round($x), round($y), round($x), round($y - $h), round($x + $w), round($y - $h), round($x + $w), round($y)];
789
790
                // Draw bounding box
791
                $this->PushColor('green');
792
                $this->Polygon($p1, true);
793
                $this->PopColor();
794
            }
795 12
            $aBoundingBox = [round($x), round($y), round($x), round($y - $h), round($x + $w), round($y - $h), round($x + $w), round($y)];
796
        }
797 12
    }
798
799 21
    public function AddTxtCR($aTxt)
800
    {
801
        // If the user has just specified a '\n'
802
        // instead of '\n\t' we have to add '\r' since
803
        // the width will be too muchy otherwise since when
804
        // we print we stroke the individually lines by hand.
805 21
        $e = explode("\n", $aTxt);
806 21
        $n = safe_count($e);
807 21
        for ($i = 0; $i < $n; ++$i) {
808 21
            $e[$i] = str_replace("\r", '', $e[$i]);
809
        }
810
811 21
        return implode("\n\r", $e);
812
    }
813
814 21
    public function NormAngle($a)
815
    {
816
        // Normalize angle in degrees
817
        // Normalize angle to be between 0-360
818 21
        while ($a > 360) {
819
            $a -= 360;
820
        }
821
822 21
        while ($a < -360) {
823
            $a += 360;
824
        }
825
826 21
        if ($a < 0) {
827
            $a = 360 + $a;
828
        }
829
830 21
        return $a;
831
    }
832
833 21
    public function imagettfbbox_fixed($size, $angle, $fontfile, $text)
834
    {
835 21
        if (!USE_LIBRARY_IMAGETTFBBOX) {
836
            $bbox = @imagettfbbox($size, $angle, $fontfile, $text);
837
            if ($bbox === false) {
838
                Util\JpGraphError::RaiseL(25092, $this->font_file);
839
                //("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.");
840
            }
841
            $this->bbox_cache = $bbox;
842
843
            return $bbox;
844
        }
845
846
        // The built in imagettfbbox is buggy for angles != 0 so
847
        // we calculate this manually by getting the bounding box at
848
        // angle = 0 and then rotate the bounding box manually
849 21
        $bbox = @imagettfbbox($size, 0, $fontfile, $text);
850 21
        if ($bbox === false && !is_readable($this->font_file)) {
851
            Util\JpGraphError::RaiseL(25092, $this->font_file);
852
            //("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.");
853
        }
854
855 21
        $angle = $this->NormAngle($angle);
856
857 21
        $a   = $angle * M_PI / 180;
858 21
        $ca  = cos($a);
859 21
        $sa  = sin($a);
860 21
        $ret = [];
861
862
        // We always add 1 pixel to the left since the left edge of the bounding
863
        // box is sometimes coinciding with the first pixel of the text
864
        //$bbox[0] -= 1;
865
        //$bbox[6] -= 1;
866
867
        // For roatated text we need to add extra width for rotated
868
        // text since the kerning and stroking of the TTF is not the same as for
869
        // text at a 0 degree angle
870
871 21
        if ($angle > 0.001 && abs($angle - 360) > 0.001) {
872 18
            $h = abs($bbox[7] - $bbox[1]);
873 18
            $w = abs($bbox[2] - $bbox[0]);
874
875 18
            $bbox[0] -= 2;
876 18
            $bbox[6] -= 2;
877
            // The width is underestimated so compensate for that
878 18
            $bbox[2] += round($w * 0.06);
879 18
            $bbox[4] += round($w * 0.06);
880
881
            // and we also need to compensate with increased height
882 18
            $bbox[5] -= round($h * 0.1);
883 18
            $bbox[7] -= round($h * 0.1);
884
885 18
            if ($angle > 90) {
886
                // For angles > 90 we also need to extend the height further down
887
                // by the baseline since that is also one more problem
888
                $bbox[1] += round($h * 0.15);
889
                $bbox[3] += round($h * 0.15);
890
891
                // and also make it slighty less height
892
                $bbox[7] += round($h * 0.05);
893
                $bbox[5] += round($h * 0.05);
894
895
                // And we need to move the box slightly top the rright (from a tetx perspective)
896
                $bbox[0] += round($w * 0.02);
897
                $bbox[6] += round($w * 0.02);
898
899
                if ($angle > 180) {
900
                    // And we need to move the box slightly to the left (from a text perspective)
901
                    $bbox[0] -= round($w * 0.02);
902
                    $bbox[6] -= round($w * 0.02);
903
                    $bbox[2] -= round($w * 0.02);
904
                    $bbox[4] -= round($w * 0.02);
905
                }
906
            }
907 18
            for ($i = 0; $i < 7; $i += 2) {
908 18
                $ret[$i]     = round($bbox[$i] * $ca + $bbox[$i + 1] * $sa);
909 18
                $ret[$i + 1] = round($bbox[$i + 1] * $ca - $bbox[$i] * $sa);
910
            }
911 18
            $this->bbox_cache = $ret;
912
913 18
            return $ret;
914
        }
915 21
        $this->bbox_cache = $bbox;
916
917 21
        return $bbox;
918
    }
919
920
    // Deprecated
921 21
    public function GetTTFBBox($aTxt, $aAngle = 0)
922
    {
923 21
        $bbox = $this->imagettfbbox_fixed($this->font_size, $aAngle, $this->font_file, $aTxt);
924
925 21
        return $bbox;
926
    }
927
928 21
    public function GetBBoxTTF($aTxt, $aAngle = 0)
929
    {
930
        // Normalize the bounding box to become a minimum
931
        // enscribing rectangle
932
933 21
        $aTxt = $this->AddTxtCR($aTxt);
934
935 21
        if (!is_readable($this->font_file)) {
936
            Util\JpGraphError::RaiseL(25093, $this->font_file);
937
            //('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.');
938
        }
939 21
        $bbox = $this->imagettfbbox_fixed($this->font_size, $aAngle, $this->font_file, $aTxt);
940
941 21
        if ($aAngle == 0) {
942 21
            return $bbox;
943
        }
944
945 18
        if ($aAngle >= 0) {
946 18
            if ($aAngle <= 90) {
947
                //<=0
948 18
                $bbox = [$bbox[6], $bbox[1], $bbox[2], $bbox[1],
949 18
                    $bbox[2], $bbox[5], $bbox[6], $bbox[5], ];
950
            } elseif ($aAngle <= 180) {
951
                //<= 2
952
                $bbox = [$bbox[4], $bbox[7], $bbox[0], $bbox[7],
953
                    $bbox[0], $bbox[3], $bbox[4], $bbox[3], ];
954
            } elseif ($aAngle <= 270) {
955
                //<= 3
956
                $bbox = [$bbox[2], $bbox[5], $bbox[6], $bbox[5],
957
                    $bbox[6], $bbox[1], $bbox[2], $bbox[1], ];
958
            } else {
959
                $bbox = [$bbox[0], $bbox[3], $bbox[4], $bbox[3],
960 18
                    $bbox[4], $bbox[7], $bbox[0], $bbox[7], ];
961
            }
962
        } elseif ($aAngle < 0) {
963
            if ($aAngle <= -270) {
964
                // <= -3
965
                $bbox = [$bbox[6], $bbox[1], $bbox[2], $bbox[1],
966
                    $bbox[2], $bbox[5], $bbox[6], $bbox[5], ];
967
            } elseif ($aAngle <= -180) {
968
                // <= -2
969
                $bbox = [$bbox[0], $bbox[3], $bbox[4], $bbox[3],
970
                    $bbox[4], $bbox[7], $bbox[0], $bbox[7], ];
971
            } elseif ($aAngle <= -90) {
972
                // <= -1
973
                $bbox = [$bbox[2], $bbox[5], $bbox[6], $bbox[5],
974
                    $bbox[6], $bbox[1], $bbox[2], $bbox[1], ];
975
            } else {
976
                $bbox = [$bbox[0], $bbox[3], $bbox[4], $bbox[3],
977
                    $bbox[4], $bbox[7], $bbox[0], $bbox[7], ];
978
            }
979
        }
980
981 18
        return $bbox;
982
    }
983
984 21
    public function GetBBoxHeight($aTxt, $aAngle = 0)
985
    {
986 21
        $box = $this->GetBBoxTTF($aTxt, $aAngle);
987
988 21
        return abs($box[7] - $box[1]);
989
    }
990
991 21
    public function GetBBoxWidth($aTxt, $aAngle = 0)
992
    {
993 21
        $box = $this->GetBBoxTTF($aTxt, $aAngle);
994
995 21
        return $box[2] - $box[0] + 1;
996
    }
997
998 21
    public function _StrokeTTF($x, $y, $txt, $dir, $paragraph_align, &$aBoundingBox, $debug = false)
999
    {
1000
        // Setup default inter line margin for paragraphs to be
1001
        // 3% of the font height.
1002 21
        $ConstLineSpacing = 0.03;
1003
1004
        // Remember the anchor point before adjustment
1005 21
        if ($debug) {
1006
            $ox = $x;
1007
            $oy = $y;
1008
        }
1009
1010 21
        if (!preg_match('/\n/', $txt) || ($dir > 0 && preg_match('/\n/', $txt))) {
1011
            // Format a single line
1012
1013 21
            $txt    = $this->AddTxtCR($txt);
1014 21
            $bbox   = $this->GetBBoxTTF($txt, $dir);
1015 21
            $width  = $this->GetBBoxWidth($txt, $dir);
1016 21
            $height = $this->GetBBoxHeight($txt, $dir);
1017
1018
            // The special alignment "basepoint" is mostly used internally
1019
            // in the library. This will put the anchor position at the left
1020
            // basepoint of the tetx. This is the default anchor point for
1021
            // TTF text.
1022
1023 21
            if ($this->text_valign != 'basepoint') {
1024
                // Align x,y ot lower left corner of bbox
1025
1026 21
                if ($this->text_halign == 'right') {
1027 21
                    $x -= $width;
1028 21
                    $x -= $bbox[0];
1029 21
                } elseif ($this->text_halign == 'center') {
1030 21
                    $x -= $width / 2;
1031 21
                    $x -= $bbox[0];
1032 21
                } elseif ($this->text_halign == 'baseline') {
1033
                    // This is only support for text at 90 degree !!
1034
                    // Do nothing the text is drawn at baseline by default
1035
                }
1036
1037 21
                if ($this->text_valign == 'top') {
1038 21
                    $y -= $bbox[1]; // Adjust to bottom of text
1039 21
                    $y += $height;
1040 21
                } elseif ($this->text_valign == 'center') {
1041 20
                    $y -= $bbox[1]; // Adjust to bottom of text
1042 20
                    $y += $height / 2;
1043 21
                } elseif ($this->text_valign == 'baseline') {
1044
                    // This is only support for text at 0 degree !!
1045
                    // Do nothing the text is drawn at baseline by default
1046
                }
1047
            }
1048
1049 21
            $x = round($x);
1050 21
            $y = round($y);
1051
1052 21
            imagettftext(
1053 21
                $this->img,
1054 21
                $this->font_size,
1055 21
                $dir,
1056 21
                $x,
0 ignored issues
show
Bug introduced by
$x of type double is incompatible with the type integer expected by parameter $x 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

1056
                /** @scrutinizer ignore-type */ $x,
Loading history...
1057 21
                $y,
0 ignored issues
show
Bug introduced by
$y 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

1057
                /** @scrutinizer ignore-type */ $y,
Loading history...
1058 21
                $this->current_color,
1059 21
                $this->font_file,
1060 21
                $txt
1061
            );
1062
1063
            // Calculate and return the co-ordinates for the bounding box
1064 21
            $box = $this->imagettfbbox_fixed($this->font_size, $dir, $this->font_file, $txt);
1065 21
            $p1  = [];
1066
1067 21
            for ($i = 0; $i < 4; ++$i) {
1068 21
                $p1[] = round($box[$i * 2] + $x);
1069 21
                $p1[] = round($box[$i * 2 + 1] + $y);
1070
            }
1071 21
            $aBoundingBox = $p1;
1072
1073
            // Debugging code to highlight the bonding box and bounding rectangle
1074
            // For text at 0 degrees the bounding box and bounding rectangle are the
1075
            // same
1076 21
            if ($debug) {
1077
                // Draw the bounding rectangle and the bounding box
1078
1079
                $p  = [];
1080
                $p1 = [];
1081
1082
                for ($i = 0; $i < 4; ++$i) {
1083
                    $p[]  = $bbox[$i * 2] + $x;
1084
                    $p[]  = $bbox[$i * 2 + 1] + $y;
1085
                    $p1[] = $box[$i * 2] + $x;
1086
                    $p1[] = $box[$i * 2 + 1] + $y;
1087
                }
1088
1089
                // Draw bounding box
1090
                $this->PushColor('green');
1091
                $this->Polygon($p1, true);
1092
                $this->PopColor();
1093
1094
                // Draw bounding rectangle
1095
                $this->PushColor('darkgreen');
1096
                $this->Polygon($p, true);
1097
                $this->PopColor();
1098
1099
                // Draw a cross at the anchor point
1100
                $this->PushColor('red');
1101
                $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...
1102
                $this->Line($ox, $oy - 15, $ox, $oy + 15);
1103 21
                $this->PopColor();
1104
            }
1105
        } else {
1106
            // Format a text paragraph
1107 2
            $fh = $this->GetFontHeight();
1108
1109
            // Line margin is 25% of font height
1110 2
            $linemargin = round($fh * $ConstLineSpacing);
1111 2
            $fh += $linemargin;
1112 2
            $w = $this->GetTextWidth($txt);
1113
1114 2
            $y -= $linemargin / 2;
1115 2
            $tmp = preg_split('/\n/', $txt);
1116 2
            $nl  = safe_count($tmp);
1117 2
            $h   = $nl * $fh;
1118
1119 2
            if ($this->text_halign == 'right') {
1120
                $x -= $dir == 0 ? $w : $h;
1121 2
            } elseif ($this->text_halign == 'center') {
1122
                $x -= $dir == 0 ? $w / 2 : $h / 2;
1123
            }
1124
1125 2
            if ($this->text_valign == 'top') {
1126 1
                $y += $dir == 0 ? $h : $w;
1127 1
            } elseif ($this->text_valign == 'center') {
1128
                $y += $dir == 0 ? $h / 2 : $w / 2;
1129
            }
1130
1131
            // Here comes a tricky bit.
1132
            // Since we have to give the position for the string at the
1133
            // baseline this means thaht text will move slightly up
1134
            // and down depending on any of it's character descend below
1135
            // the baseline, for example a 'g'. To adjust the Y-position
1136
            // we therefore adjust the text with the baseline Y-offset
1137
            // as used for the current font and size. This will keep the
1138
            // baseline at a fixed positoned disregarding the actual
1139
            // characters in the string.
1140 2
            $standardbox  = $this->GetTTFBBox('Gg', $dir);
1141 2
            $yadj         = $standardbox[1];
1142 2
            $xadj         = $standardbox[0];
0 ignored issues
show
Unused Code introduced by
The assignment to $xadj is dead and can be removed.
Loading history...
1143 2
            $aBoundingBox = [];
1144 2
            for ($i = 0; $i < $nl; ++$i) {
1145 2
                $wl   = $this->GetTextWidth($tmp[$i]);
1146 2
                $bbox = $this->GetTTFBBox($tmp[$i], $dir);
1147 2
                if ($paragraph_align == 'left') {
1148 2
                    $xl = $x;
1149
                } elseif ($paragraph_align == 'right') {
1150
                    $xl = $x + ($w - $wl);
1151
                } else {
1152
                    // Center
1153
                    $xl = $x + $w / 2 - $wl / 2;
1154
                }
1155
1156
                // In theory we should adjust with full pre-lead to get the lines
1157
                // lined up but this doesn't look good so therfore we only adjust with
1158
                // half th pre-lead
1159 2
                $xl -= $bbox[0] / 2;
1160 2
                $yl = $y - $yadj;
1161
                //$xl = $xl- $xadj;
1162
1163 2
                $xl = round($xl);
1164 2
                $yl = round($yl - ($h - $fh) + $fh * $i);
1165
1166 2
                imagettftext(
1167 2
                    $this->img,
1168 2
                    $this->font_size,
1169 2
                    $dir,
1170 2
                    $xl,
1171 2
                    $yl,
1172 2
                    $this->current_color,
1173 2
                    $this->font_file,
1174 2
                    $tmp[$i]
1175
                );
1176
1177
                // echo "xl=$xl,".$tmp[$i]." <br>";
1178 2
                if ($debug) {
1179
                    // Draw the bounding rectangle around each line
1180
                    $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...
1181
                    $p   = [];
1182
                    for ($j = 0; $j < 4; ++$j) {
1183
                        $p[] = $bbox[$j * 2] + $xl;
1184
                        $p[] = $bbox[$j * 2 + 1] + $yl - ($h - $fh) + $fh * $i;
1185
                    }
1186
1187
                    // Draw bounding rectangle
1188
                    $this->PushColor('darkgreen');
1189
                    $this->Polygon($p, true);
1190
                    $this->PopColor();
1191
                }
1192
            }
1193
1194
            // Get the bounding box
1195 2
            $bbox = $this->GetBBoxTTF($txt, $dir);
1196 2
            for ($j = 0; $j < 4; ++$j) {
1197 2
                $bbox[$j * 2] += round($x);
1198 2
                $bbox[$j * 2 + 1] += round($y - ($h - $fh) - $yadj);
1199
            }
1200 2
            $aBoundingBox = $bbox;
1201
1202 2
            if ($debug) {
1203
                // Draw a cross at the anchor point
1204
                $this->PushColor('red');
1205
                $this->Line($ox - 25, $oy, $ox + 25, $oy);
1206
                $this->Line($ox, $oy - 25, $ox, $oy + 25);
1207
                $this->PopColor();
1208
            }
1209
        }
1210 21
    }
1211
1212 21
    public function StrokeText($x, $y, $txt, $dir = 0, $paragraph_align = 'left', $debug = false)
1213
    {
1214 21
        $x = round($x);
1215 21
        $y = round($y);
1216
1217
        // Do special language encoding
1218 21
        $txt = $this->langconv->Convert($txt, $this->font_family);
1219
1220 21
        if (!is_numeric($dir)) {
1221
            Util\JpGraphError::RaiseL(25094); //(" Direction for text most be given as an angle between 0 and 90.");
1222
        }
1223
1224 21
        if ($this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2 + 1) {
1225 12
            $this->_StrokeBuiltinFont($x, $y, $txt, $dir, $paragraph_align, $boundingbox, $debug);
1226 21
        } elseif ($this->font_family >= _FIRST_FONT && $this->font_family <= _LAST_FONT) {
1227 21
            $this->_StrokeTTF($x, $y, $txt, $dir, $paragraph_align, $boundingbox, $debug);
1228
        } else {
1229
            Util\JpGraphError::RaiseL(25095); //(" Unknown font font family specification. ");
1230
        }
1231
1232 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...
1233
    }
1234
1235 21
    public function SetMargin($lm, $rm, $tm, $bm)
1236
    {
1237 21
        $this->left_margin   = $lm;
1238 21
        $this->right_margin  = $rm;
1239 21
        $this->top_margin    = $tm;
1240 21
        $this->bottom_margin = $bm;
1241
1242 21
        $this->plotwidth  = $this->width - $this->left_margin - $this->right_margin;
1243 21
        $this->plotheight = $this->height - $this->top_margin - $this->bottom_margin;
1244
1245 21
        if ($this->width > 0 && $this->height > 0) {
1246 21
            if ($this->plotwidth < 0 || $this->plotheight < 0) {
1247
                Util\JpGraphError::RaiseL(25130, $this->plotwidth, $this->plotheight);
1248
                //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.");
1249
            }
1250
        }
1251 21
    }
1252
1253
    public function SetTransparent($color)
1254
    {
1255
        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

1255
        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...
1256
    }
1257
1258 21
    public function SetColor($color, $aAlpha = 0)
1259
    {
1260 21
        $this->current_color_name = $color;
1261 21
        $this->current_color      = $this->rgb->allocate($color, $aAlpha);
1262 21
        if ($this->current_color == -1) {
1263
            $tc = imagecolorstotal($this->img);
0 ignored issues
show
Unused Code introduced by
The assignment to $tc is dead and can be removed.
Loading history...
1264
            Util\JpGraphError::RaiseL(25096);
1265
            //("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.");
1266
        }
1267
1268 21
        return $this->current_color;
1269
    }
1270
1271 21
    public function PushColor($color)
1272
    {
1273 21
        if ($color != '') {
1274 21
            $this->colorstack[$this->colorstackidx]     = $this->current_color_name;
1275 21
            $this->colorstack[$this->colorstackidx + 1] = $this->current_color;
1276 21
            $this->colorstackidx += 2;
1277 21
            $this->SetColor($color);
1278
        } else {
1279
            Util\JpGraphError::RaiseL(25097); //("Color specified as empty string in PushColor().");
1280
        }
1281 21
    }
1282
1283 21
    public function PopColor()
1284
    {
1285 21
        if ($this->colorstackidx < 1) {
1286
            Util\JpGraphError::RaiseL(25098); //(" Negative Color stack index. Unmatched call to PopColor()");
1287
        }
1288 21
        $this->current_color      = $this->colorstack[--$this->colorstackidx];
1289 21
        $this->current_color_name = $this->colorstack[--$this->colorstackidx];
1290 21
    }
1291
1292 21
    public function SetLineWeight($weight)
1293
    {
1294 21
        $old = $this->line_weight;
1295 21
        imagesetthickness($this->img, $weight);
1296 21
        $this->line_weight = $weight;
1297
1298 21
        return $old;
1299
    }
1300
1301 16
    public function SetStartPoint($x, $y)
1302
    {
1303 16
        $this->lastx = round($x);
1304 16
        $this->lasty = round($y);
1305 16
    }
1306
1307
    public function Arc($cx, $cy, $w, $h, $s, $e)
1308
    {
1309
        // GD Arc doesn't like negative angles
1310
        while ($s < 0) {
1311
            $s += 360;
1312
        }
1313
1314
        while ($e < 0) {
1315
            $e += 360;
1316
        }
1317
1318
        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

1318
        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($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

1318
        imagearc($this->img, round($cx), round($cy), /** @scrutinizer ignore-type */ 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

1318
        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

1318
        imagearc($this->img, round($cx), round($cy), round($w), /** @scrutinizer ignore-type */ round($h), $s, $e, $this->current_color);
Loading history...
1319
    }
1320
1321 3
    public function FilledArc($xc, $yc, $w, $h, $s, $e, $style = '')
1322
    {
1323 3
        $s = round($s);
1324 3
        $e = round($e);
1325 3
        while ($s < 0) {
1326
            $s += 360;
1327
        }
1328
1329 3
        while ($e < 0) {
1330
            $e += 360;
1331
        }
1332
1333 3
        if ($style == '') {
1334 3
            $style = IMG_ARC_PIE;
1335
        }
1336
1337 3
        if (abs($s - $e) > 0) {
1338 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

1338
            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

1338
            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($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

1338
            imagefilledarc($this->img, round($xc), /** @scrutinizer ignore-type */ round($yc), round($w), 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

1338
            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
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

1338
            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
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

1338
            imagefilledarc($this->img, round($xc), round($yc), round($w), round($h), $s, /** @scrutinizer ignore-type */ $e, $this->current_color, $style);
Loading history...
1339
            //            $this->DrawImageSmoothArc($this->img,round($xc),round($yc),round($w),round($h),$s,$e,$this->current_color,$style);
1340
        }
1341 3
    }
1342
1343
    public function FilledCakeSlice($cx, $cy, $w, $h, $s, $e)
1344
    {
1345
        $this->CakeSlice($cx, $cy, $w, $h, $s, $e, $this->current_color_name);
1346
    }
1347
1348 3
    public function CakeSlice($xc, $yc, $w, $h, $s, $e, $fillcolor = '', $arccolor = '')
1349
    {
1350 3
        $s  = round($s);
1351 3
        $e  = round($e);
1352 3
        $w  = round($w);
1353 3
        $h  = round($h);
1354 3
        $xc = round($xc);
1355 3
        $yc = round($yc);
1356 3
        if ($s == $e) {
1357
            // A full circle. We draw this a plain circle
1358
            $this->PushColor($fillcolor);
1359
            imagefilledellipse($this->img, $xc, $yc, 2 * $w, 2 * $h, $this->current_color);
0 ignored issues
show
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

1359
            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

1359
            imagefilledellipse($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 imagefilledellipse(). ( Ignorable by Annotation )

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

1359
            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

1359
            imagefilledellipse($this->img, $xc, /** @scrutinizer ignore-type */ $yc, 2 * $w, 2 * $h, $this->current_color);
Loading history...
1360
1361
            // If antialiasing is used then we often don't have any color no the surrounding
1362
            // arc. So, we need to check for this special case so we don't send an empty
1363
            // color to the push function. In this case we use the fill color for the arc as well
1364
            if ($arccolor != '') {
1365
                $this->PopColor();
1366
                $this->PushColor($arccolor);
1367
            }
1368
            imageellipse($this->img, $xc, $yc, 2 * $w, 2 * $h, $this->current_color);
0 ignored issues
show
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

1368
            imageellipse($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 imageellipse(). ( Ignorable by Annotation )

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

1368
            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

1368
            imageellipse($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 imageellipse(). ( Ignorable by Annotation )

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

1368
            imageellipse($this->img, $xc, /** @scrutinizer ignore-type */ $yc, 2 * $w, 2 * $h, $this->current_color);
Loading history...
1369
            $this->Line($xc, $yc, cos($s * M_PI / 180) * $w + $xc, $yc + sin($s * M_PI / 180) * $h);
1370
            $this->PopColor();
1371
        } else {
1372 3
            $this->PushColor($fillcolor);
1373 3
            $this->FilledArc($xc, $yc, 2 * $w, 2 * $h, $s, $e);
1374 3
            $this->PopColor();
1375 3
            if ($arccolor != '') {
1376
                $this->PushColor($arccolor);
1377
                // We add 2 pixels to make the Arc() better aligned with
1378
                // the filled arc.
1379
                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 * $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

1379
                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
$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

1379
                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
$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

1379
                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...
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

1379
                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 * $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

1379
                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
$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

1379
                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...
1380
                $this->PopColor();
1381
            }
1382
        }
1383 3
    }
1384
1385
    public function Ellipse($xc, $yc, $w, $h)
1386
    {
1387
        $this->Arc($xc, $yc, $w, $h, 0, 360);
1388
    }
1389
1390 5
    public function Circle($xc, $yc, $r)
1391
    {
1392 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

1392
        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

1392
        imageellipse($this->img, round($xc), /** @scrutinizer ignore-type */ round($yc), $r * 2, $r * 2, $this->current_color);
Loading history...
1393
        //        $this->DrawImageSmoothArc($this->img,round($xc),round($yc),$r*2+1,$r*2+1,0,360,$this->current_color);
1394
        //        $this->imageSmoothCircle($this->img, round($xc),round($yc), $r*2+1, $this->current_color);
1395 5
    }
1396
1397 5
    public function FilledCircle($xc, $yc, $r)
1398
    {
1399 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

1399
        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

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

1520
        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

1520
        imageline($this->img, $x1, /** @scrutinizer ignore-type */ $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

1520
        imageline($this->img, $x1, $y1, /** @scrutinizer ignore-type */ $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

1520
        imageline($this->img, /** @scrutinizer ignore-type */ $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
Loading history...
1521
1522 2
        $this->lastx = $x2;
1523 2
        $this->lasty = $y2;
1524 2
    }
1525
1526 5
    public function DashedLineForGrid($x1, $y1, $x2, $y2, $dash_length = 1, $dash_space = 4)
1527
    {
1528 5
        if ($this->line_weight <= 0) {
1529
            return;
1530
        }
1531
1532
        // Add error check to make sure anti-alias is not enabled.
1533
        // Dashed line does not work with anti-alias enabled. This
1534
        // is a limitation in GD.
1535 5
        if ($this->use_anti_aliasing) {
1536
            //            Util\JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.
1537
        }
1538
1539 5
        $x1 = round($x1);
1540 5
        $x2 = round($x2);
1541 5
        $y1 = round($y1);
1542 5
        $y2 = round($y2);
1543
1544
        /*
1545
        $dash_length *= $this->scale;
1546
        $dash_space  *= $this->scale;
1547
         */
1548
1549 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...
1550 5
        $dash_length = 4;
1551 5
        imagesetthickness($this->img, 1);
1552 5
        $style = array_fill(0, $dash_length, $this->current_color); //hexdec('CCCCCC'));
1553 5
        $style = array_pad($style, $dash_space, IMG_COLOR_TRANSPARENT);
1554 5
        imagesetstyle($this->img, $style);
1555 5
        imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
0 ignored issues
show
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

1555
        imageline($this->img, /** @scrutinizer ignore-type */ $x1, $y1, $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

1555
        imageline($this->img, $x1, /** @scrutinizer ignore-type */ $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

1555
        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

1555
        imageline($this->img, $x1, $y1, $x2, /** @scrutinizer ignore-type */ $y2, IMG_COLOR_STYLED);
Loading history...
1556
1557 5
        $this->lastx = $x2;
1558 5
        $this->lasty = $y2;
1559 5
    }
1560
1561 21
    public function Line($x1, $y1, $x2, $y2)
1562
    {
1563 21
        if ($this->line_weight <= 0) {
1564
            return;
1565
        }
1566
1567 21
        $x1 = round($x1);
1568 21
        $x2 = round($x2);
1569 21
        $y1 = round($y1);
1570 21
        $y2 = round($y2);
1571
1572 21
        imageline($this->img, $x1, $y1, $x2, $y2, $this->current_color);
0 ignored issues
show
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

1572
        imageline($this->img, /** @scrutinizer ignore-type */ $x1, $y1, $x2, $y2, $this->current_color);
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

1572
        imageline($this->img, $x1, $y1, $x2, /** @scrutinizer ignore-type */ $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

1572
        imageline($this->img, $x1, /** @scrutinizer ignore-type */ $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

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

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

1807
        imagesetpixel($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 imagesetpixel(). ( Ignorable by Annotation )

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

1807
        imagesetpixel($this->img, round($x), /** @scrutinizer ignore-type */ round($y), $this->current_color);
Loading history...
1808
    }
1809
1810
    public function Fill($x, $y)
1811
    {
1812
        imagefill($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 imagefill(). ( Ignorable by Annotation )

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

1812
        imagefill($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 imagefill(). ( Ignorable by Annotation )

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

1812
        imagefill($this->img, /** @scrutinizer ignore-type */ round($x), round($y), $this->current_color);
Loading history...
1813
    }
1814
1815
    public function FillToBorder($x, $y, $aBordColor)
1816
    {
1817
        $bc = $this->rgb->allocate($aBordColor);
1818
        if ($bc == -1) {
1819
            Util\JpGraphError::RaiseL(25106); //('Image::FillToBorder : Can not allocate more colors');
1820
        }
1821
        imagefilltoborder($this->img, round($x), round($y), $bc, $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 imagefilltoborder(). ( Ignorable by Annotation )

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

1821
        imagefilltoborder($this->img, round($x), /** @scrutinizer ignore-type */ round($y), $bc, $this->current_color);
Loading history...
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

1821
        imagefilltoborder($this->img, /** @scrutinizer ignore-type */ round($x), round($y), $bc, $this->current_color);
Loading history...
1822
    }
1823
1824
    public function SetExpired($aFlg = true)
1825
    {
1826
        $this->expired = $aFlg;
1827
    }
1828
1829
    // Generate image header
1830 21
    public function Headers()
1831
    {
1832
        // In case we are running from the command line with the client version of
1833
        // PHP we can't send any headers.
1834 21
        $sapi = php_sapi_name();
1835 21
        if ($sapi == 'cli') {
1836 21
            return;
1837
        }
1838
1839
        // These parameters are set by headers_sent() but they might cause
1840
        // an undefined variable error unless they are initilized
1841
        $file   = '';
1842
        $lineno = '';
1843
        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

1843
        if (headers_sent($file, /** @scrutinizer ignore-type */ $lineno)) {
Loading history...
1844
            $file = basename($file);
1845
            $t    = new ErrMsgText();
1846
            $msg  = $t->Get(10, $file, $lineno);
1847
            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...
1848
        }
1849
1850
        if ($this->expired) {
1851
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
1852
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT');
1853
            header('Cache-Control: no-cache, must-revalidate');
1854
            header('Pragma: no-cache');
1855
        }
1856
        header("Content-type: image/{$this->img_format}");
1857
    }
1858
1859
    // Adjust image quality for formats that allow this
1860
    public function SetQuality($q)
1861
    {
1862
        $this->quality = $q;
1863
    }
1864
1865
    // Stream image to browser or to file
1866 21
    public function Stream($aFile = '')
1867
    {
1868 21
        $this->DoSupersampling();
1869
1870 21
        $func = 'image' . $this->img_format;
1871 21
        if ($this->img_format == 'jpeg' && $this->quality != null) {
1872
            $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...
1873
        } else {
1874 21
            if ($aFile != '') {
1875
                $res = @$func($this->img, $aFile);
1876
                if (!$res) {
1877
                    Util\JpGraphError::RaiseL(25107, $aFile); //("Can't write to file '$aFile'. Check that the process running PHP has enough permission.");
1878
                }
1879
            } else {
1880 21
                $res = @$func($this->img);
1881 21
                if (!$res) {
1882
                    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.");
1883
                }
1884
            }
1885
        }
1886 21
    }
1887
1888
    // Do SuperSampling using $scale
1889 21
    public function DoSupersampling()
1890
    {
1891 21
        if (SUPERSAMPLING_SCALE <= 1) {
1892 21
            return $this->img;
1893
        }
1894
1895
        $dst_img = @imagecreatetruecolor($this->original_width, $this->original_height);
1896
        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->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

1896
        imagecopyresampled($dst_img, $this->img, 0, 0, 0, 0, $this->original_width, $this->original_height, $this->width, /** @scrutinizer ignore-type */ $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

1896
        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->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

1896
        imagecopyresampled($dst_img, $this->img, 0, 0, 0, 0, $this->original_width, $this->original_height, /** @scrutinizer ignore-type */ $this->width, $this->height);
Loading history...
1897
        $this->Destroy();
1898
1899
        return $this->img = $dst_img;
1900
    }
1901
1902
    // Clear resources used by image (this is normally not used since all resources are/should be
1903
    // returned when the script terminates
1904 1
    public function Destroy()
1905
    {
1906 1
        imagedestroy($this->img);
1907 1
    }
1908
1909
    // Specify image format. Note depending on your installation
1910
    // of PHP not all formats may be supported.
1911 21
    public function SetImgFormat($aFormat, $aQuality = 75)
1912
    {
1913 21
        $this->quality = $aQuality;
1914 21
        $aFormat       = strtolower($aFormat);
1915 21
        $tst           = true;
1916 21
        $supported     = imagetypes();
1917 21
        if ($aFormat == 'auto') {
1918 21
            if ($supported & IMG_PNG) {
1919 21
                $this->img_format = 'png';
1920
            } elseif ($supported & IMG_JPG) {
1921
                $this->img_format = 'jpeg';
1922
            } elseif ($supported & IMG_GIF) {
1923
                $this->img_format = 'gif';
1924
            } elseif ($supported & IMG_WBMP) {
1925
                $this->img_format = 'wbmp';
1926
            } elseif ($supported & IMG_XPM) {
1927
                $this->img_format = 'xpm';
1928
            } else {
1929
                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.");
1930
            }
1931
1932 21
            return true;
1933
        }
1934
        if ($aFormat == 'jpeg' || $aFormat == 'png' || $aFormat == 'gif') {
1935
            if ($aFormat == 'jpeg' && !($supported & IMG_JPG)) {
1936
                $tst = false;
1937
            } elseif ($aFormat == 'png' && !($supported & IMG_PNG)) {
1938
                $tst = false;
1939
            } elseif ($aFormat == 'gif' && !($supported & IMG_GIF)) {
1940
                $tst = false;
1941
            } elseif ($aFormat == 'wbmp' && !($supported & IMG_WBMP)) {
1942
                $tst = false;
1943
            } elseif ($aFormat == 'xpm' && !($supported & IMG_XPM)) {
1944
                $tst = false;
1945
            } else {
1946
                $this->img_format = $aFormat;
1947
1948
                return true;
1949
            }
1950
        } else {
1951
            $tst = false;
1952
        }
1953
        if (!$tst) {
0 ignored issues
show
introduced by
The condition $tst is always false.
Loading history...
1954
            Util\JpGraphError::RaiseL(25110, $aFormat); //(" Your PHP installation does not support the chosen graphic format: $aFormat");
1955
        }
1956
    }
1957
1958
    /**
1959
     * Draw Line.
1960
     *
1961
     * @param mixed $im
1962
     * @param mixed $x1
1963
     * @param mixed $y1
1964
     * @param mixed $x2
1965
     * @param mixed $y2
1966
     * @param mixed $weight
1967
     * @param mixed $color
1968
     */
1969
    public function DrawLine($im, $x1, $y1, $x2, $y2, $weight, $color)
1970
    {
1971
        if ($weight == 1) {
1972
            return imageline($im, $x1, $y1, $x2, $y2, $color);
1973
        }
1974
1975
        $angle = (atan2(($y1 - $y2), ($x2 - $x1)));
1976
1977
        $dist_x = $weight * (sin($angle)) / 2;
1978
        $dist_y = $weight * (cos($angle)) / 2;
1979
1980
        $p1x = ceil(($x1 + $dist_x));
1981
        $p1y = ceil(($y1 + $dist_y));
1982
        $p2x = ceil(($x2 + $dist_x));
1983
        $p2y = ceil(($y2 + $dist_y));
1984
        $p3x = ceil(($x2 - $dist_x));
1985
        $p3y = ceil(($y2 - $dist_y));
1986
        $p4x = ceil(($x1 - $dist_x));
1987
        $p4y = ceil(($y1 - $dist_y));
1988
1989
        $array = [$p1x, $p1y, $p2x, $p2y, $p3x, $p3y, $p4x, $p4y];
1990
        imagefilledpolygon($im, $array, (safe_count($array) / 2), $color);
1991
1992
        // for antialias
1993
        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

1993
        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

1993
        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

1993
        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

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

2253
                        $diffColor1 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], /** @scrutinizer ignore-type */ 127 - (127 - $color[3]) * $error1);
Loading history...
2254
                        $y1         = $_y1;
2255
                        if ($aaStopX) {
2256
                            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

2256
                            imagesetpixel($img, $cx + $xp * ($x) + $xa, /** @scrutinizer ignore-type */ $cy + $yp * ($y1 + 1) + $ya, $diffColor1);
Loading history...
2257
                        }
2258
                    } else {
2259
                        $y         = $b * sqrt(1 - ($x * $x) / ($a * $a));
2260
                        $error     = $y - (int) ($y);
2261
                        $y         = (int) ($y);
2262
                        $diffColor = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error);
2263
                        $y1        = $y;
2264
                        if ($x < $aaAngleX) {
2265
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y1 + 1) + $ya, $diffColor);
2266
                        }
2267
                    }
2268
                    if ($start > $i * M_PI / 2 && $x <= $xStart) {
2269
                        $diffColor2 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error2);
2270
                        $y2         = $_y2;
2271
                        if ($aaStartX) {
2272
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y2 - 1) + $ya, $diffColor2);
2273
                        }
2274
                    } else {
2275
                        $y2 = 0;
2276
                    }
2277
                    if ($y2 <= $y1) {
2278
                        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

2278
                        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

2278
                        imageline($img, $cx + $xp * $x + $xa, /** @scrutinizer ignore-type */ $cy + $yp * $y1 + $ya, $cx + $xp * $x + $xa, $cy + $yp * $y2 + $ya, $fillColor);
Loading history...
2279
                    }
2280
                }
2281
            }
2282
2283
            if ($seg == 1 || $seg == 3) {
2284
                $i = $seg;
2285
                if (!($stop < ($i + 1) * M_PI / 2 && $x > $xStop)) {
2286
                    if ($i == 1) {
2287
                        $xp = -1;
2288
                        $yp = -1;
2289
                        $xa = 0;
2290
                        $ya = 0;
2291
                    } else {
2292
                        $xp = +1;
2293
                        $yp = +1;
2294
                        $xa = 1;
2295
                        $ya = 1;
2296
                    }
2297
                    if ($start > $i * M_PI / 2 && $x < $xStart) {
2298
                        $diffColor2 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error2);
2299
                        $y1         = $_y2;
2300
                        if ($aaStartX) {
2301
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y1 + 1) + $ya, $diffColor2);
2302
                        }
2303
                    } else {
2304
                        $y         = $b * sqrt(1 - ($x * $x) / ($a * $a));
2305
                        $error     = $y - (int) ($y);
2306
                        $y         = (int) $y;
2307
                        $diffColor = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error);
2308
                        $y1        = $y;
2309
                        if ($x < $aaAngleX) {
2310
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y1 + 1) + $ya, $diffColor);
2311
                        }
2312
                    }
2313
                    if ($stop < ($i + 1) * M_PI / 2 && $x <= $xStop) {
2314
                        $diffColor1 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error1);
2315
                        $y2         = $_y1;
2316
                        if ($aaStopX) {
2317
                            imagesetpixel($img, $cx + $xp * $x + $xa, $cy + $yp * ($y2 - 1) + $ya, $diffColor1);
2318
                        }
2319
                    } else {
2320
                        $y2 = 0;
2321
                    }
2322
                    if ($y2 <= $y1) {
2323
                        imageline($img, $cx + $xp * $x + $xa, $cy + $yp * $y1 + $ya, $cx + $xp * $x + $xa, $cy + $yp * $y2 + $ya, $fillColor);
2324
                    }
2325
                }
2326
            }
2327
        }
2328
2329
        ///YYYYY
2330
2331
        for ($y = 0; $y < $b; ++$y) {
2332
            /*$x = $a * sqrt( 1 - ($y*$y)/($b*$b) );
2333
2334
            $error = $x - (int)($x);
2335
            $x = (int)($x);
2336
2337
            $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );
2338
             */
2339
            $_x1 = $dxStop * $y;
2340
            $_x2 = $dxStart * $y;
2341
            if ($yStart > $yStop) {
2342
                $error1 = $_x1 - (int) ($_x1);
2343
                $error2 = 1 - $_x2 + (int) $_x2;
2344
                $_x1    = $_x1 - $error1;
2345
                $_x2    = $_x2 + $error2;
2346
            } else {
2347
                $error1 = 1 - $_x1 + (int) $_x1;
2348
                $error2 = $_x2 - (int) ($_x2);
2349
                $_x1    = $_x1 + $error1;
2350
                $_x2    = $_x2 - $error2;
2351
            }
2352
            /*
2353
            if (!$aaStopX)
2354
            $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 );
2355
            if (!$aaStartX)
2356
            $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 );
2357
             */
2358
2359
            if ($seg == 0 || $seg == 2) {
2360
                $i = $seg;
2361
                if (!($start > $i * M_PI / 2 && $y > $yStop)) {
2362
                    if ($i == 0) {
2363
                        $xp = +1;
2364
                        $yp = -1;
2365
                        $xa = 1;
2366
                        $ya = 0;
2367
                    } else {
2368
                        $xp = -1;
2369
                        $yp = +1;
2370
                        $xa = 0;
2371
                        $ya = 1;
2372
                    }
2373
                    if ($stop < ($i + 1) * (M_PI / 2) && $y <= $yStop) {
2374
                        $diffColor1 = imagecolorexactalpha($img, $color[0], $color[1], $color[2], 127 - (127 - $color[3]) * $error1);
2375
                        $x1         = $_x1;
2376
                        if (!$aaStopX) {
2377
                            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

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