Graph::StrokeFrameBackground()   C
last analyzed

Complexity

Conditions 12
Paths 34

Size

Total Lines 144
Code Lines 105

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 101
CRAP Score 12.4987

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 105
c 1
b 0
f 0
nc 34
nop 0
dl 0
loc 144
ccs 101
cts 119
cp 0.8487
crap 12.4987
rs 5.5733

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * JPGraph v4.0.3
5
 */
6
7
namespace Amenadiel\JpGraph\Graph;
8
9 1
require_once __DIR__ . '/../config.inc.php';
10
11
use Amenadiel\JpGraph\Image;
12
use Amenadiel\JpGraph\Plot;
13
use Amenadiel\JpGraph\Text;
14
use Amenadiel\JpGraph\Util;
15
16
/**
17
 * @class Graph
18
 * // Description: Main class to handle graphs
19
 */
20
class Graph
21
{
22
    public $gDateLocale;
23
    public $gJpgDateLocale;
24
    public $cache; // Cache object (singleton)
25
    public $img; // Img object (singleton)
26
    public $plots   = []; // Array of all plot object in the graph (for Y 1 axis)
27
    public $y2plots = []; // Array of all plot object in the graph (for Y 2 axis)
28
    public $ynplots = [];
29
    public $xscale; // X Scale object (could be instance of LinearScale or LogScale
30
    public $yscale;
31
    public $y2scale;
32
    public $ynscale = [];
33
    public $iIcons  = []; // Array of Icons to add to
34
    public $cache_name; // File name to be used for the current graph in the cache directory
35
    public $xgrid; // X Grid object (linear or logarithmic)
36
    public $ygrid;
37
    public $y2grid; //dito for Y
38
    public $doframe;
39
    public $frame_color;
40
    public $frame_weight; // Frame around graph
41
    public $boxed        = false;
42
    public $box_color    = 'black';
43
    public $box_weight   = 1; // Box around plot area
44
    public $doshadow     = false;
45
    public $shadow_width = 4;
46
    public $shadow_color = '[email protected]'; // Shadow for graph
47
    public $xaxis; // X-axis (instane of Axis class)
48
    public $yaxis;
49
    public $y2axis;
50
    public $ynaxis = []; // Y axis (instance of Axis class)
51
    public $margin_color; // Margin color of graph
52
    public $plotarea_color = [255, 255, 255]; // Plot area color
53
    public $title;
54
    public $subtitle;
55
    public $subsubtitle; // Title and subtitle(s) text object
56
    public $axtype = 'linlin'; // Type of axis
57
    public $xtick_factor;
58
    public $ytick_factor; // Factor to determine the maximum number of ticks depending on the plot width
59
    public $texts;
60
    public $y2texts; // Text object to ge shown in the graph
61
    public $lines;
62
    public $y2lines;
63
    public $bands;
64
    public $y2bands;
65
    public $text_scale_off          = 0;
66
    public $text_scale_abscenteroff = -1; // Text scale in fractions and for centering bars
67
    public $background_image        = '';
68
    public $background_image_type   = -1;
69
    public $background_image_format = 'png';
70
    public $background_image_bright = 0;
71
    public $background_image_contr  = 0;
72
    public $background_image_sat    = 0;
73
    public $background_image_xpos   = 0;
74
    public $background_image_ypos   = 0;
75
    public $image_bright            = 0;
76
    public $image_contr             = 0;
77
    public $image_sat               = 0;
78
    public $inline;
79
    public $showcsim     = 0;
80
    public $csimcolor    = 'red'; //debug stuff, draw the csim boundaris on the image if <>0
81
    public $grid_depth   = DEPTH_BACK; // Draw grid under all plots as default
82
    public $iAxisStyle   = AXSTYLE_SIMPLE;
83
    public $iCSIMdisplay = false;
84
    public $iHasStroked  = false;
85
    public $footer;
86
    public $csimcachename    = '';
87
    public $csimcachetimeout = 0;
88
    public $iCSIMImgAlt      = '';
89
    public $iDoClipping      = false;
90
    public $y2orderback      = true;
91
    public $tabtitle;
92
    public $bkg_gradtype   = -1;
93
    public $bkg_gradstyle  = BGRAD_MARGIN;
94
    public $bkg_gradfrom   = 'navy';
95
    public $bkg_gradto     = 'silver';
96
    public $plot_gradtype  = -1;
97
    public $plot_gradstyle = BGRAD_MARGIN;
98
    public $plot_gradfrom  = 'silver';
99
    public $plot_gradto    = 'navy';
100
101
    public $titlebackground       = false;
102
    public $titlebackground_color = 'lightblue';
103
    public $titlebackground_style = 1;
104
    public $titlebackground_framecolor;
105
    public $titlebackground_framestyle;
106
    public $titlebackground_frameweight;
107
    public $titlebackground_bevelheight;
108
    public $titlebkg_fillstyle = TITLEBKG_FILLSTYLE_SOLID;
109
    public $titlebkg_scolor1   = 'black';
110
    public $titlebkg_scolor2   = 'white';
111
    public $framebevel;
112
    public $framebeveldepth;
113
    public $framebevelborder;
114
    public $framebevelbordercolor;
115
    public $framebevelcolor1;
116
    public $framebevelcolor2;
117
    public $background_image_mix  = 100;
118
    public $background_cflag      = '';
119
    public $background_cflag_type = BGIMG_FILLPLOT;
120
    public $background_cflag_mix  = 100;
121
    public $iImgTrans             = false;
122
    public $iImgTransHorizon      = 100;
123
    public $iImgTransSkewDist     = 150;
124
    public $iImgTransDirection    = 1;
125
    public $iImgTransMinSize      = true;
126
    public $iImgTransFillColor    = 'white';
127
    public $iImgTransHighQ        = false;
128
    public $iImgTransBorder       = false;
129
    public $iImgTransHorizonPos   = 0.5;
130
    public $legend;
131
    public $graph_theme;
132
    protected $iYAxisDeltaPos       = 50;
133
    protected $iIconDepth           = DEPTH_BACK;
134
    protected $iAxisLblBgType       = 0;
135
    protected $iXAxisLblBgFillColor = 'lightgray';
136
    protected $iXAxisLblBgColor     = 'black';
137
    protected $iYAxisLblBgFillColor = 'lightgray';
138
    protected $iYAxisLblBgColor     = 'black';
139
    protected $iTables;
140
141
    protected $isRunningClear = false;
142
    protected $inputValues;
143
    protected $isAfterSetScale = false;
144
145
    // aWIdth   Width in pixels of image
146
    // aHeight   Height in pixels of image
147
    // aCachedName Name for image file in cache directory
148
    // aTimeOut  Timeout in minutes for image in cache
149
    // aInline  If true the image is streamed back in the call to Stroke()
150
    //   If false the image is just created in the cache
151 21
    public function __construct($aWidth = 300, $aHeight = 200, $aCachedName = '', $aTimeout = 0, $aInline = true)
152
    {
153 21
        $this->gDateLocale    = new Util\DateLocale();
154 21
        $this->gJpgDateLocale = new Util\DateLocale();
155 21
        if (!is_numeric($aWidth) || !is_numeric($aHeight)) {
156
            Util\JpGraphError::RaiseL(25008); //('Image width/height argument in Graph::Graph() must be numeric');
157
        }
158
159
        // Initialize frame and margin
160 21
        $this->InitializeFrameAndMargin();
161
162
        // Automatically generate the image file name based on the name of the script that
163
        // generates the graph
164 21
        if ($aCachedName == 'auto') {
165
            $aCachedName = Util\Helper::GenImgName();
166
        }
167
168
        // Should the image be streamed back to the browser or only to the cache?
169 21
        $this->inline = $aInline;
170
171 21
        $this->img   = new Image\RotImage($aWidth, $aHeight);
172 21
        $this->cache = new Image\ImgStreamCache();
173
174
        // Window doesn't like '?' in the file name so replace it with an '_'
175 21
        $aCachedName = str_replace('?', '_', $aCachedName);
176 21
        $this->SetupCache($aCachedName, $aTimeout);
177
178 21
        $this->title = new Text\Text();
179 21
        $this->title->ParagraphAlign('center');
180 21
        $this->title->SetFont(FF_DEFAULT, FS_NORMAL); //FF_FONT2, FS_BOLD
181 21
        $this->title->SetMargin(5);
182 21
        $this->title->SetAlign('center');
183
184 21
        $this->subtitle = new Text\Text();
185 21
        $this->subtitle->ParagraphAlign('center');
186 21
        $this->subtitle->SetMargin(3);
187 21
        $this->subtitle->SetAlign('center');
188
189 21
        $this->subsubtitle = new Text\Text();
190 21
        $this->subsubtitle->ParagraphAlign('center');
191 21
        $this->subsubtitle->SetMargin(3);
192 21
        $this->subsubtitle->SetAlign('center');
193
194 21
        $this->legend = new Legend();
195 21
        $this->footer = new Image\Footer();
196
197
        // If the cached version exist just read it directly from the
198
        // cache, stream it back to browser and exit
199 21
        if ($aCachedName != '' && READ_CACHE && $aInline) {
200
            if ($this->cache->GetAndStream($this->img, $aCachedName)) {
201
                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...
202
            }
203
        }
204
205 21
        $this->SetTickDensity(); // Normal density
206
207 21
        $this->tabtitle = new Text\GraphTabTitle();
208
209 21
        if (!$this->isRunningClear) {
210 21
            $this->inputValues                = [];
211 21
            $this->inputValues['aWidth']      = $aWidth;
212 21
            $this->inputValues['aHeight']     = $aHeight;
213 21
            $this->inputValues['aCachedName'] = $aCachedName;
214 21
            $this->inputValues['aTimeout']    = $aTimeout;
215 21
            $this->inputValues['aInline']     = $aInline;
216
217 21
            $theme_class = '\Amenadiel\JpGraph\Themes\\' . DEFAULT_THEME_CLASS;
218
219 21
            if (class_exists($theme_class)) {
220 21
                $this->graph_theme = new $theme_class();
221
            }
222
        }
223 21
    }
224
225 21
    public function InitializeFrameAndMargin()
226
    {
227 21
        $this->doframe      = true;
228 21
        $this->frame_color  = 'black';
229 21
        $this->frame_weight = 1;
230
231 21
        $this->titlebackground_framecolor  = 'blue';
232 21
        $this->titlebackground_framestyle  = 2;
233 21
        $this->titlebackground_frameweight = 1;
234 21
        $this->titlebackground_bevelheight = 3;
235 21
        $this->titlebkg_fillstyle          = TITLEBKG_FILLSTYLE_SOLID;
236 21
        $this->titlebkg_scolor1            = 'black';
237 21
        $this->titlebkg_scolor2            = 'white';
238 21
        $this->framebevel                  = false;
239 21
        $this->framebeveldepth             = 2;
240 21
        $this->framebevelborder            = false;
241 21
        $this->framebevelbordercolor       = 'black';
242 21
        $this->framebevelcolor1            = '[email protected]';
243 21
        $this->framebevelcolor2            = '[email protected]';
244
245 21
        $this->margin_color = [250, 250, 250];
246 21
    }
247
248 21
    public function SetupCache($aFilename, $aTimeout = 60)
249
    {
250 21
        $this->cache_name = $aFilename;
251 21
        $this->cache->SetTimeOut($aTimeout);
252 21
    }
253
254
    // Enable final image perspective transformation
255
    public function Set3DPerspective($aDir = 1, $aHorizon = 100, $aSkewDist = 120, $aQuality = false, $aFillColor = '#FFFFFF', $aBorder = false, $aMinSize = true, $aHorizonPos = 0.5)
256
    {
257
        $this->iImgTrans           = true;
258
        $this->iImgTransHorizon    = $aHorizon;
259
        $this->iImgTransSkewDist   = $aSkewDist;
260
        $this->iImgTransDirection  = $aDir;
261
        $this->iImgTransMinSize    = $aMinSize;
262
        $this->iImgTransFillColor  = $aFillColor;
263
        $this->iImgTransHighQ      = $aQuality;
264
        $this->iImgTransBorder     = $aBorder;
265
        $this->iImgTransHorizonPos = $aHorizonPos;
266
    }
267
268
    public function SetUserFont($aNormal, $aBold = '', $aItalic = '', $aBoldIt = '')
269
    {
270
        $this->img->ttf->SetUserFont($aNormal, $aBold, $aItalic, $aBoldIt);
271
    }
272
273
    public function SetUserFont1($aNormal, $aBold = '', $aItalic = '', $aBoldIt = '')
274
    {
275
        $this->img->ttf->SetUserFont1($aNormal, $aBold, $aItalic, $aBoldIt);
276
    }
277
278
    public function SetUserFont2($aNormal, $aBold = '', $aItalic = '', $aBoldIt = '')
279
    {
280
        $this->img->ttf->SetUserFont2($aNormal, $aBold, $aItalic, $aBoldIt);
281
    }
282
283
    public function SetUserFont3($aNormal, $aBold = '', $aItalic = '', $aBoldIt = '')
284
    {
285
        $this->img->ttf->SetUserFont3($aNormal, $aBold, $aItalic, $aBoldIt);
286
    }
287
288
    // Set Image format and optional quality
289
    public function SetImgFormat($aFormat, $aQuality = 75)
290
    {
291
        $this->img->SetImgFormat($aFormat, $aQuality);
292
    }
293
294
    // Should the grid be in front or back of the plot?
295 1
    public function SetGridDepth($aDepth)
296
    {
297 1
        $this->grid_depth = $aDepth;
298 1
    }
299
300
    public function SetIconDepth($aDepth)
301
    {
302
        $this->iIconDepth = $aDepth;
303
    }
304
305
    // Specify graph angle 0-360 degrees.
306 2
    public function SetAngle($aAngle)
307
    {
308 2
        $this->img->SetAngle($aAngle);
309 2
    }
310
311 1
    public function SetAlphaBlending($aFlg = true)
312
    {
313 1
        $this->img->SetAlphaBlending($aFlg);
314 1
    }
315
316
    // Shortcut to image margin
317 17
    public function SetMargin($lm, $rm, $tm, $bm)
318
    {
319 17
        $this->img->SetMargin($lm, $rm, $tm, $bm);
320 17
    }
321
322
    public function SetY2OrderBack($aBack = true)
323
    {
324
        $this->y2orderback = $aBack;
325
    }
326
327
    // Rotate the graph 90 degrees and set the margin
328
    // when we have done a 90 degree rotation
329 1
    public function Set90AndMargin($lm = 0, $rm = 0, $tm = 0, $bm = 0)
330
    {
331 1
        $lm = $lm == 0 ? floor(0.2 * $this->img->width) : $lm;
332 1
        $rm = $rm == 0 ? floor(0.1 * $this->img->width) : $rm;
333 1
        $tm = $tm == 0 ? floor(0.2 * $this->img->height) : $tm;
334 1
        $bm = $bm == 0 ? floor(0.1 * $this->img->height) : $bm;
335
336 1
        $adj = ($this->img->height - $this->img->width) / 2;
337 1
        $this->img->SetMargin($tm - $adj, $bm - $adj, $rm + $adj, $lm + $adj);
338 1
        $this->img->SetCenter(floor($this->img->width / 2), floor($this->img->height / 2));
339 1
        $this->SetAngle(90);
340 1
        if (empty($this->yaxis) || empty($this->xaxis)) {
341
            Util\JpGraphError::RaiseL(25009); //('You must specify what scale to use with a call to Graph::SetScale()');
342
        }
343 1
        $this->xaxis->SetLabelAlign('right', 'center');
344 1
        $this->yaxis->SetLabelAlign('center', 'bottom');
345 1
    }
346
347 1
    public function SetClipping($aFlg = true)
348
    {
349 1
        $this->iDoClipping = $aFlg;
350 1
    }
351
352
    // Add a plot object to the graph
353 19
    public function Add($aPlot)
354
    {
355 19
        if ($aPlot == null) {
356
            Util\JpGraphError::RaiseL(25010); //("Graph::Add() You tried to add a null plot to the graph.");
357
        }
358 19
        if (is_array($aPlot) && safe_count($aPlot) > 0) {
359 1
            $cl = $aPlot[0];
360
        } else {
361 19
            $cl = $aPlot;
362
        }
363
364 19
        if ($cl instanceof Text\Text) {
365 1
            $this->AddText($aPlot);
366 19
        } elseif (($cl instanceof Plot\PlotLine)) {
367 1
            $this->AddLine($aPlot);
368 19
        } elseif (($cl instanceof Plot\PlotBand)) {
369
            $this->AddBand($aPlot);
370 19
        } elseif (($cl instanceof Plot\IconPlot)) {
371
            $this->AddIcon($aPlot);
372 19
        } elseif (($cl instanceof Text\GTextTable)) {
373
            $this->AddTable($aPlot);
374
        } else {
375 19
            if (is_array($aPlot)) {
376 1
                $this->plots = array_merge($this->plots, $aPlot);
377
            } else {
378 19
                $this->plots[] = $aPlot;
379
            }
380
        }
381
382 19
        if ($this->graph_theme) {
383 19
            $this->graph_theme->SetupPlot($aPlot);
384
        }
385 19
    }
386
387
    public function AddTable($aTable)
388
    {
389
        if (is_array($aTable)) {
390
            for ($i = 0; $i < safe_count($aTable); ++$i) {
391
                $this->iTables[] = $aTable[$i];
392
            }
393
        } else {
394
            $this->iTables[] = $aTable;
395
        }
396
    }
397
398
    public function AddIcon($aIcon)
399
    {
400
        if (is_array($aIcon)) {
401
            for ($i = 0; $i < safe_count($aIcon); ++$i) {
402
                $this->iIcons[] = $aIcon[$i];
403
            }
404
        } else {
405
            $this->iIcons[] = $aIcon;
406
        }
407
    }
408
409
    // Add plot to second Y-scale
410 3
    public function AddY2($aPlot)
411
    {
412 3
        if ($aPlot == null) {
413
            Util\JpGraphError::RaiseL(25011); //("Graph::AddY2() You tried to add a null plot to the graph.");
414
        }
415
416 3
        if (is_array($aPlot) && safe_count($aPlot) > 0) {
417
            $cl = $aPlot[0];
418
        } else {
419 3
            $cl = $aPlot;
420
        }
421
422 3
        if ($cl instanceof Text\Text) {
423
            $this->AddText($aPlot, true);
424 3
        } elseif (($cl instanceof Plot\PlotLine)) {
425
            $this->AddLine($aPlot, true);
426 3
        } elseif (($cl instanceof Plot\PlotBand)) {
427
            $this->AddBand($aPlot, true);
428
        } else {
429 3
            $this->y2plots[] = $aPlot;
430
        }
431
432 3
        if ($this->graph_theme) {
433 3
            $this->graph_theme->SetupPlot($aPlot);
434
        }
435 3
    }
436
437
    // Add plot to the extra Y-axises
438
    public function AddY($aN, $aPlot)
439
    {
440
        if ($aPlot == null) {
441
            Util\JpGraphError::RaiseL(25012); //("Graph::AddYN() You tried to add a null plot to the graph.");
442
        }
443
444
        if (is_array($aPlot) && safe_count($aPlot) > 0) {
445
            $cl = $aPlot[0];
446
        } else {
447
            $cl = $aPlot;
448
        }
449
450
        if (($cl instanceof Text\Text) ||
451
            ($cl instanceof Plot\PlotLine) ||
452
            ($cl instanceof Plot\PlotBand)) {
453
            Util\JpGraphError::RaiseL(25013); //('You can only add standard plots to multiple Y-axis');
454
        } else {
455
            $this->ynplots[$aN][] = $aPlot;
456
        }
457
458
        if ($this->graph_theme) {
459
            $this->graph_theme->SetupPlot($aPlot);
460
        }
461
    }
462
463
    // Add text object to the graph
464 1
    public function AddText($aTxt, $aToY2 = false)
465
    {
466 1
        if ($aTxt == null) {
467
            Util\JpGraphError::RaiseL(25014); //("Graph::AddText() You tried to add a null text to the graph.");
468
        }
469 1
        if ($aToY2) {
470
            if (is_array($aTxt)) {
471
                for ($i = 0; $i < safe_count($aTxt); ++$i) {
472
                    $this->y2texts[] = $aTxt[$i];
473
                }
474
            } else {
475
                $this->y2texts[] = $aTxt;
476
            }
477
        } else {
478 1
            if (is_array($aTxt)) {
479
                for ($i = 0; $i < safe_count($aTxt); ++$i) {
480
                    $this->texts[] = $aTxt[$i];
481
                }
482
            } else {
483 1
                $this->texts[] = $aTxt;
484
            }
485
        }
486 1
    }
487
488
    // Add a line object (class PlotLine) to the graph
489 2
    public function AddLine($aLine, $aToY2 = false)
490
    {
491 2
        if ($aLine == null) {
492
            Util\JpGraphError::RaiseL(25015); //("Graph::AddLine() You tried to add a null line to the graph.");
493
        }
494
495 2
        if ($aToY2) {
496
            if (is_array($aLine)) {
497
                for ($i = 0; $i < safe_count($aLine); ++$i) {
498
                    //$this->y2lines[]=$aLine[$i];
499
                    $this->y2plots[] = $aLine[$i];
500
                }
501
            } else {
502
                //$this->y2lines[] = $aLine;
503
                $this->y2plots[] = $aLine;
504
            }
505
        } else {
506 2
            if (is_array($aLine)) {
507
                for ($i = 0; $i < safe_count($aLine); ++$i) {
508
                    //$this->lines[]=$aLine[$i];
509
                    $this->plots[] = $aLine[$i];
510
                }
511
            } else {
512
                //$this->lines[] = $aLine;
513 2
                $this->plots[] = $aLine;
514
            }
515
        }
516 2
    }
517
518
    // Add vertical or horizontal band
519
    public function AddBand($aBand, $aToY2 = false)
520
    {
521
        if ($aBand == null) {
522
            Util\JpGraphError::RaiseL(25016); //(" Graph::AddBand() You tried to add a null band to the graph.");
523
        }
524
525
        if ($aToY2) {
526
            if (is_array($aBand)) {
527
                for ($i = 0; $i < safe_count($aBand); ++$i) {
528
                    $this->y2bands[] = $aBand[$i];
529
                }
530
            } else {
531
                $this->y2bands[] = $aBand;
532
            }
533
        } else {
534
            if (is_array($aBand)) {
535
                for ($i = 0; $i < safe_count($aBand); ++$i) {
536
                    $this->bands[] = $aBand[$i];
537
                }
538
            } else {
539
                $this->bands[] = $aBand;
540
            }
541
        }
542
    }
543
544 1
    public function SetPlotGradient($aFrom = 'navy', $aTo = 'silver', $aGradType = 2)
545
    {
546 1
        $this->plot_gradtype = $aGradType;
547 1
        $this->plot_gradfrom = $aFrom;
548 1
        $this->plot_gradto   = $aTo;
549 1
    }
550
551 3
    public function SetBackgroundGradient($aFrom = 'navy', $aTo = 'silver', $aGradType = 2, $aStyle = BGRAD_FRAME)
552
    {
553 3
        $this->bkg_gradtype  = $aGradType;
554 3
        $this->bkg_gradstyle = $aStyle;
555 3
        $this->bkg_gradfrom  = $aFrom;
556 3
        $this->bkg_gradto    = $aTo;
557 3
    }
558
559
    // Set a country flag in the background
560
    public function SetBackgroundCFlag($aName, $aBgType = BGIMG_FILLPLOT, $aMix = 100)
561
    {
562
        $this->background_cflag      = $aName;
563
        $this->background_cflag_type = $aBgType;
564
        $this->background_cflag_mix  = $aMix;
565
    }
566
567
    // Alias for the above method
568 1
    public function SetBackgroundCountryFlag($aName, $aBgType = BGIMG_FILLPLOT, $aMix = 100)
569
    {
570 1
        $this->background_cflag      = $aName;
571 1
        $this->background_cflag_type = $aBgType;
572 1
        $this->background_cflag_mix  = $aMix;
573 1
    }
574
575
    // Specify a background image
576 4
    public function SetBackgroundImage($aFileName, $aBgType = BGIMG_FILLPLOT, $aImgFormat = 'auto')
577
    {
578
        // Get extension to determine image type
579 4
        if ($aImgFormat == 'auto') {
580 4
            $e = explode('.', $aFileName);
581 4
            if (empty($e)) {
582
                Util\JpGraphError::RaiseL(25018, $aFileName); //('Incorrect file name for Graph::SetBackgroundImage() : '.$aFileName.' Must have a valid image extension (jpg,gif,png) when using autodetection of image type');
583
            }
584
585 4
            $valid_formats = ['png', 'jpg', 'gif'];
586 4
            $aImgFormat    = strtolower($e[count($e) - 1]);
587 4
            if ($aImgFormat == 'jpeg') {
588
                $aImgFormat = 'jpg';
589 4
            } elseif (!in_array($aImgFormat, $valid_formats, true)) {
590
                Util\JpGraphError::RaiseL(25019, $aImgFormat); //('Unknown file extension ($aImgFormat) in Graph::SetBackgroundImage() for filename: '.$aFileName);
591
            }
592
        }
593
594 4
        $this->background_image        = $aFileName;
595 4
        $this->background_image_type   = $aBgType;
596 4
        $this->background_image_format = $aImgFormat;
597 4
    }
598
599 1
    public function SetBackgroundImageMix($aMix)
600
    {
601 1
        $this->background_image_mix = $aMix;
602 1
    }
603
604
    // Adjust background image position
605
    public function SetBackgroundImagePos($aXpos, $aYpos)
606
    {
607
        $this->background_image_xpos = $aXpos;
608
        $this->background_image_ypos = $aYpos;
609
    }
610
611
    // Specify axis style (boxed or single)
612 3
    public function SetAxisStyle($aStyle)
613
    {
614 3
        $this->iAxisStyle = $aStyle;
615 3
    }
616
617
    // Set a frame around the plot area
618 19
    public function SetBox($aDrawPlotFrame = true, $aPlotFrameColor = [0, 0, 0], $aPlotFrameWeight = 1)
619
    {
620 19
        $this->boxed      = $aDrawPlotFrame;
621 19
        $this->box_weight = $aPlotFrameWeight;
622 19
        $this->box_color  = $aPlotFrameColor;
623 19
    }
624
625
    // Specify color for the plotarea (not the margins)
626 3
    public function SetColor($aColor)
627
    {
628 3
        $this->plotarea_color = $aColor;
629 3
    }
630
631
    // Specify color for the margins (all areas outside the plotarea)
632 21
    public function SetMarginColor($aColor)
633
    {
634 21
        $this->margin_color = $aColor;
635 21
    }
636
637
    // Set a frame around the entire image
638 21
    public function SetFrame($aDrawImgFrame = true, $aImgFrameColor = [0, 0, 0], $aImgFrameWeight = 1)
639
    {
640 21
        $this->doframe      = $aDrawImgFrame;
641 21
        $this->frame_color  = $aImgFrameColor;
642 21
        $this->frame_weight = $aImgFrameWeight;
643 21
    }
644
645
    public function SetFrameBevel($aDepth = 3, $aBorder = false, $aBorderColor = 'black', $aColor1 = '[email protected]', $aColor2 = '[email protected]', $aFlg = true)
646
    {
647
        $this->framebevel            = $aFlg;
648
        $this->framebeveldepth       = $aDepth;
649
        $this->framebevelborder      = $aBorder;
650
        $this->framebevelbordercolor = $aBorderColor;
651
        $this->framebevelcolor1      = $aColor1;
652
        $this->framebevelcolor2      = $aColor2;
653
654
        $this->doshadow = false;
655
    }
656
657
    // Set the shadow around the whole image
658 11
    public function SetShadow($aShowShadow = true, $aShadowWidth = 5, $aShadowColor = 'darkgray')
659
    {
660 11
        $this->doshadow     = $aShowShadow;
661 11
        $this->shadow_color = $aShadowColor;
662 11
        $this->shadow_width = $aShadowWidth;
663 11
        $this->footer->iBottomMargin += $aShadowWidth;
664 11
        $this->footer->iRightMargin += $aShadowWidth;
665 11
    }
666
667
    // Specify x,y scale. Note that if you manually specify the scale
668
    // you must also specify the tick distance with a call to Ticks::Set()
669 19
    public function SetScale($aAxisType, $aYMin = 1, $aYMax = 1, $aXMin = 1, $aXMax = 1)
670
    {
671 19
        $this->axtype = $aAxisType;
672
673 19
        if ($aYMax < $aYMin || $aXMax < $aXMin) {
674
            Util\JpGraphError::RaiseL(25020); //('Graph::SetScale(): Specified Max value must be larger than the specified Min value.');
675
        }
676
677 19
        $yt = substr($aAxisType, -3, 3);
678 19
        if ($yt == 'lin') {
679 17
            $this->yscale = new LinearScale($aYMin, $aYMax);
680 4
        } elseif ($yt == 'int') {
681 2
            $this->yscale = new LinearScale($aYMin, $aYMax);
682 2
            $this->yscale->SetIntScale();
683 3
        } elseif ($yt == 'log') {
684 3
            $this->yscale = new LogScale($aYMin, $aYMax);
685
        } else {
686
            Util\JpGraphError::RaiseL(25021, $aAxisType); //("Unknown scale specification for Y-scale. ($aAxisType)");
687
        }
688
689 19
        $xt = substr($aAxisType, 0, 3);
690 19
        if ($xt == 'lin' || $xt == 'tex') {
691 17
            $this->xscale            = new LinearScale($aXMin, $aXMax, 'x');
692 17
            $this->xscale->textscale = ($xt == 'tex');
693 5
        } elseif ($xt == 'int') {
694 5
            $this->xscale = new LinearScale($aXMin, $aXMax, 'x');
695 5
            $this->xscale->SetIntScale();
696 2
        } elseif ($xt == 'dat') {
697 1
            $this->xscale = new DateScale($aXMin, $aXMax, 'x');
698 1
        } elseif ($xt == 'log') {
699 1
            $this->xscale = new LogScale($aXMin, $aXMax, 'x');
700
        } else {
701
            Util\JpGraphError::RaiseL(25022, $aAxisType); //(" Unknown scale specification for X-scale. ($aAxisType)");
702
        }
703
704 19
        $this->xaxis = new Axis($this->img, $this->xscale);
705 19
        $this->yaxis = new Axis($this->img, $this->yscale);
706 19
        $this->xgrid = new Grid($this->xaxis);
707 19
        $this->ygrid = new Grid($this->yaxis);
708 19
        $this->ygrid->Show();
709
710 19
        if (!$this->isRunningClear) {
711 19
            $this->inputValues['aAxisType'] = $aAxisType;
712 19
            $this->inputValues['aYMin']     = $aYMin;
713 19
            $this->inputValues['aYMax']     = $aYMax;
714 19
            $this->inputValues['aXMin']     = $aXMin;
715 19
            $this->inputValues['aXMax']     = $aXMax;
716
717 19
            if ($this->graph_theme) {
718 19
                $this->graph_theme->ApplyGraph($this);
719
            }
720
        }
721
722 19
        $this->isAfterSetScale = true;
723 19
    }
724
725
    // Specify secondary Y scale
726 3
    public function SetY2Scale($aAxisType = 'lin', $aY2Min = 1, $aY2Max = 1)
727
    {
728 3
        if ($aAxisType == 'lin') {
729 3
            $this->y2scale = new LinearScale($aY2Min, $aY2Max);
730 1
        } elseif ($aAxisType == 'int') {
731
            $this->y2scale = new LinearScale($aY2Min, $aY2Max);
732
            $this->y2scale->SetIntScale();
733 1
        } elseif ($aAxisType == 'log') {
734 1
            $this->y2scale = new LogScale($aY2Min, $aY2Max);
735
        } else {
736
            Util\JpGraphError::RaiseL(25023, $aAxisType); //("JpGraph: Unsupported Y2 axis type: $aAxisType\nMust be one of (lin,log,int)");
737
        }
738
739 3
        $this->y2axis = new Axis($this->img, $this->y2scale);
740 3
        $this->y2axis->scale->ticks->SetDirection(SIDE_LEFT);
741 3
        $this->y2axis->SetLabelSide(SIDE_RIGHT);
742 3
        $this->y2axis->SetPos('max');
743 3
        $this->y2axis->SetTitleSide(SIDE_RIGHT);
744
745
        // Deafult position is the max x-value
746 3
        $this->y2grid = new Grid($this->y2axis);
747
748 3
        if ($this->graph_theme) {
749 3
            $this->graph_theme->ApplyGraph($this);
750
        }
751 3
    }
752
753
    // Set the delta position (in pixels) between the multiple Y-axis
754
    public function SetYDeltaDist($aDist)
755
    {
756
        $this->iYAxisDeltaPos = $aDist;
757
    }
758
759
    // Specify secondary Y scale
760
    public function SetYScale($aN, $aAxisType = 'lin', $aYMin = 1, $aYMax = 1)
761
    {
762
        if ($aAxisType == 'lin') {
763
            $this->ynscale[$aN] = new LinearScale($aYMin, $aYMax);
764
        } elseif ($aAxisType == 'int') {
765
            $this->ynscale[$aN] = new LinearScale($aYMin, $aYMax);
766
            $this->ynscale[$aN]->SetIntScale();
767
        } elseif ($aAxisType == 'log') {
768
            $this->ynscale[$aN] = new LogScale($aYMin, $aYMax);
769
        } else {
770
            Util\JpGraphError::RaiseL(25024, $aAxisType); //("JpGraph: Unsupported Y axis type: $aAxisType\nMust be one of (lin,log,int)");
771
        }
772
773
        $this->ynaxis[$aN] = new Axis($this->img, $this->ynscale[$aN]);
774
        $this->ynaxis[$aN]->scale->ticks->SetDirection(SIDE_LEFT);
775
        $this->ynaxis[$aN]->SetLabelSide(SIDE_RIGHT);
776
777
        if ($this->graph_theme) {
778
            $this->graph_theme->ApplyGraph($this);
779
        }
780
    }
781
782
    // Specify density of ticks when autoscaling 'normal', 'dense', 'sparse', 'verysparse'
783
    // The dividing factor have been determined heuristically according to my aesthetic
784
    // sense (or lack off) y.m.m.v !
785 21
    public function SetTickDensity($aYDensity = TICKD_NORMAL, $aXDensity = TICKD_NORMAL)
786
    {
787 21
        $this->xtick_factor = 30;
788 21
        $this->ytick_factor = 25;
789
        switch ($aYDensity) {
790 21
            case TICKD_DENSE:
791
                $this->ytick_factor = 12;
792
793
                break;
794 21
            case TICKD_NORMAL:
795 21
                $this->ytick_factor = 25;
796
797 21
                break;
798
            case TICKD_SPARSE:
799
                $this->ytick_factor = 40;
800
801
                break;
802
            case TICKD_VERYSPARSE:
803
                $this->ytick_factor = 100;
804
805
                break;
806
            default:
807
                Util\JpGraphError::RaiseL(25025, $densy); //("JpGraph: Unsupported Tick density: $densy");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $densy seems to be never defined.
Loading history...
808
        }
809
        switch ($aXDensity) {
810 21
            case TICKD_DENSE:
811
                $this->xtick_factor = 15;
812
813
                break;
814 21
            case TICKD_NORMAL:
815 21
                $this->xtick_factor = 30;
816
817 21
                break;
818
            case TICKD_SPARSE:
819
                $this->xtick_factor = 45;
820
821
                break;
822
            case TICKD_VERYSPARSE:
823
                $this->xtick_factor = 60;
824
825
                break;
826
            default:
827
                Util\JpGraphError::RaiseL(25025, $densx); //("JpGraph: Unsupported Tick density: $densx");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $densx seems to be never defined.
Loading history...
828
        }
829 21
    }
830
831
    // Get a string of all image map areas
832
    public function GetCSIMareas()
833
    {
834
        if (!$this->iHasStroked) {
835
            $this->Stroke(_CSIM_SPECIALFILE);
836
        }
837
838
        $csim = $this->title->GetCSIMAreas();
839
        $csim .= $this->subtitle->GetCSIMAreas();
840
        $csim .= $this->subsubtitle->GetCSIMAreas();
841
        $csim .= $this->legend->GetCSIMAreas();
842
843
        if ($this->y2axis != null) {
844
            $csim .= $this->y2axis->title->GetCSIMAreas();
845
        }
846
847
        if ($this->texts != null) {
848
            $n = safe_count($this->texts);
849
            for ($i = 0; $i < $n; ++$i) {
850
                $csim .= $this->texts[$i]->GetCSIMAreas();
851
            }
852
        }
853
854
        if ($this->y2texts != null && $this->y2scale != null) {
855
            $n = safe_count($this->y2texts);
856
            for ($i = 0; $i < $n; ++$i) {
857
                $csim .= $this->y2texts[$i]->GetCSIMAreas();
858
            }
859
        }
860
861
        if ($this->yaxis != null && $this->xaxis != null) {
862
            $csim .= $this->yaxis->title->GetCSIMAreas();
863
            $csim .= $this->xaxis->title->GetCSIMAreas();
864
        }
865
866
        $n = safe_count($this->plots);
867
        for ($i = 0; $i < $n; ++$i) {
868
            $csim .= $this->plots[$i]->GetCSIMareas();
869
        }
870
871
        $n = safe_count($this->y2plots);
872
        for ($i = 0; $i < $n; ++$i) {
873
            $csim .= $this->y2plots[$i]->GetCSIMareas();
874
        }
875
876
        $n = safe_count($this->ynaxis);
877
        for ($i = 0; $i < $n; ++$i) {
878
            $m = safe_count($this->ynplots[$i]);
879
            for ($j = 0; $j < $m; ++$j) {
880
                $csim .= $this->ynplots[$i][$j]->GetCSIMareas();
881
            }
882
        }
883
884
        $n = safe_count($this->iTables);
885
        for ($i = 0; $i < $n; ++$i) {
886
            $csim .= $this->iTables[$i]->GetCSIMareas();
887
        }
888
889
        return $csim;
890
    }
891
892
    // Get a complete <MAP>..</MAP> tag for the final image map
893
    public function GetHTMLImageMap($aMapName)
894
    {
895
        $im = "<map name=\"${aMapName}\" id=\"${aMapName}\" >\n";
896
        $im .= $this->GetCSIMareas();
897
        $im .= '</map>';
898
899
        return $im;
900
    }
901
902
    public function CheckCSIMCache($aCacheName, $aTimeOut = 60)
903
    {
904
        global $_SERVER;
905
906
        if ($aCacheName == 'auto') {
907
            $aCacheName = basename($_SERVER['PHP_SELF']);
908
        }
909
910
        $urlarg                 = $this->GetURLArguments();
911
        $this->csimcachename    = CSIMCACHE_DIR . $aCacheName . $urlarg;
912
        $this->csimcachetimeout = $aTimeOut;
913
914
        // First determine if we need to check for a cached version
915
        // This differs from the standard cache in the sense that the
916
        // image and CSIM map HTML file is written relative to the directory
917
        // the script executes in and not the specified cache directory.
918
        // The reason for this is that the cache directory is not necessarily
919
        // accessible from the HTTP server.
920
        if ($this->csimcachename != '') {
921
            $dir      = dirname($this->csimcachename);
922
            $base     = basename($this->csimcachename);
923
            $base     = strtok($base, '.');
924
            $suffix   = strtok('.');
0 ignored issues
show
Unused Code introduced by
The assignment to $suffix is dead and can be removed.
Loading history...
925
            $basecsim = $dir . '/' . $base . '?' . $urlarg . '_csim_.html';
926
            $baseimg  = $dir . '/' . $base . '?' . $urlarg . '.' . $this->img->img_format;
927
928
            $timedout = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $timedout is dead and can be removed.
Loading history...
929
            // Does it exist at all ?
930
931
            if (file_exists($basecsim) && file_exists($baseimg)) {
932
                // Check that it hasn't timed out
933
                $diff = time() - filemtime($basecsim);
934
                if ($this->csimcachetimeout > 0 && ($diff > $this->csimcachetimeout * 60)) {
935
                    $timedout = true;
936
                    @unlink($basecsim);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

936
                    /** @scrutinizer ignore-unhandled */ @unlink($basecsim);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
937
                    @unlink($baseimg);
938
                } else {
939
                    if ($fh = @fopen($basecsim, 'r')) {
940
                        fpassthru($fh);
941
942
                        return true;
943
                    }
944
                    Util\JpGraphError::RaiseL(25027, $basecsim); //(" Can't open cached CSIM \"$basecsim\" for reading.");
945
                }
946
            }
947
        }
948
949
        return false;
950
    }
951
952
    // Build the argument string to be used with the csim images
953
    public static function GetURLArguments($aAddRecursiveBlocker = false)
954
    {
955
        if ($aAddRecursiveBlocker) {
956
            // This is a JPGRAPH internal defined that prevents
957
            // us from recursively coming here again
958
            $urlarg = _CSIM_DISPLAY . '=1';
959
        }
960
961
        // Now reconstruct any user URL argument
962
        reset($_GET);
963
        foreach ($_GET as $key => $value) {
964
            if (is_array($value)) {
965
                foreach ($value as $k => $v) {
966
                    $urlarg .= '&amp;' . $key . '%5B' . $k . '%5D=' . urlencode($v);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $urlarg does not seem to be defined for all execution paths leading up to this point.
Loading history...
967
                }
968
            } else {
969
                $urlarg .= '&amp;' . $key . '=' . urlencode($value);
970
            }
971
        }
972
973
        // It's not ideal to convert POST argument to GET arguments
974
        // but there is little else we can do. One idea for the
975
        // future might be recreate the POST header in case.
976
        reset($_POST);
977
        foreach ($_POST as $key => $value) {
978
            if (is_array($value)) {
979
                foreach ($value as $k => $v) {
980
                    $urlarg .= '&amp;' . $key . '%5B' . $k . '%5D=' . urlencode($v);
981
                }
982
            } else {
983
                $urlarg .= '&amp;' . $key . '=' . urlencode($value);
984
            }
985
        }
986
987
        return $urlarg;
988
    }
989
990
    public function SetCSIMImgAlt($aAlt)
991
    {
992
        $this->iCSIMImgAlt = $aAlt;
993
    }
994
995
    public function StrokeCSIM($aScriptName = 'auto', $aCSIMName = '', $aBorder = 0)
996
    {
997
        if ($aCSIMName == '') {
998
            // create a random map name
999
            srand((int) (microtime() * 1000000));
1000
            $r         = rand(0, 100000);
1001
            $aCSIMName = '__mapname' . $r . '__';
1002
        }
1003
1004
        if ($aScriptName == 'auto') {
1005
            $aScriptName = basename($_SERVER['PHP_SELF']);
1006
        }
1007
1008
        $urlarg = $this->GetURLArguments(true);
1009
1010
        if (empty($_GET[_CSIM_DISPLAY])) {
1011
            // First determine if we need to check for a cached version
1012
            // This differs from the standard cache in the sense that the
1013
            // image and CSIM map HTML file is written relative to the directory
1014
            // the script executes in and not the specified cache directory.
1015
            // The reason for this is that the cache directory is not necessarily
1016
            // accessible from the HTTP server.
1017
            if ($this->csimcachename != '') {
1018
                $dir      = dirname($this->csimcachename);
1019
                $base     = basename($this->csimcachename);
1020
                $base     = strtok($base, '.');
1021
                $suffix   = strtok('.');
0 ignored issues
show
Unused Code introduced by
The assignment to $suffix is dead and can be removed.
Loading history...
1022
                $basecsim = $dir . '/' . $base . '?' . $urlarg . '_csim_.html';
1023
                $baseimg  = $base . '?' . $urlarg . '.' . $this->img->img_format;
1024
1025
                // Check that apache can write to directory specified
1026
1027
                if (file_exists($dir) && !is_writeable($dir)) {
1028
                    Util\JpGraphError::RaiseL(25028, $dir); //('Apache/PHP does not have permission to write to the CSIM cache directory ('.$dir.'). Check permissions.');
1029
                }
1030
1031
                // Make sure directory exists
1032
                $this->cache->MakeDirs($dir);
1033
1034
                // Write the image file
1035
                $this->Stroke(CSIMCACHE_DIR . $baseimg);
1036
1037
                // Construct wrapper HTML and write to file and send it back to browser
1038
1039
                // In the src URL we must replace the '?' with its encoding to prevent the arguments
1040
                // to be converted to real arguments.
1041
                $tmp      = str_replace('?', '%3f', $baseimg);
1042
                $htmlwrap = $this->GetHTMLImageMap($aCSIMName) . "\n" .
1043
                '<img src="' . CSIMCACHE_HTTP_DIR . $tmp . '" ismap="ismap" usemap="#' . $aCSIMName . ' width="' . $this->img->width . '" height="' . $this->img->height . '" alt="' . $this->iCSIMImgAlt . "\" />\n";
1044
1045
                if ($fh = @fopen($basecsim, 'w')) {
1046
                    fwrite($fh, $htmlwrap);
1047
                    fclose($fh);
1048
                    echo $htmlwrap;
1049
                } else {
1050
                    Util\JpGraphError::RaiseL(25029, $basecsim); //(" Can't write CSIM \"$basecsim\" for writing. Check free space and permissions.");
1051
                }
1052
            } else {
1053
                if ($aScriptName == '') {
1054
                    Util\JpGraphError::RaiseL(25030); //('Missing script name in call to StrokeCSIM(). You must specify the name of the actual image script as the first parameter to StrokeCSIM().');
1055
                }
1056
                echo $this->GetHTMLImageMap($aCSIMName) . $this->GetCSIMImgHTML($aCSIMName, $aScriptName, $aBorder);
1057
            }
1058
        } else {
1059
            $this->Stroke();
1060
        }
1061
    }
1062
1063
    public function StrokeCSIMImage()
1064
    {
1065
        if (@$_GET[_CSIM_DISPLAY] == 1) {
1066
            $this->Stroke();
1067
        }
1068
    }
1069
1070
    public function GetCSIMImgHTML($aCSIMName, $aScriptName = 'auto', $aBorder = 0)
0 ignored issues
show
Unused Code introduced by
The parameter $aBorder is not used and could be removed. ( Ignorable by Annotation )

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

1070
    public function GetCSIMImgHTML($aCSIMName, $aScriptName = 'auto', /** @scrutinizer ignore-unused */ $aBorder = 0)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1071
    {
1072
        if ($aScriptName == 'auto') {
1073
            $aScriptName = basename($_SERVER['PHP_SELF']);
1074
        }
1075
        $urlarg = $this->GetURLArguments(true);
1076
1077
        return '<img src="' . $aScriptName . '?' . $urlarg . '" ismap="ismap" usemap="#' . $aCSIMName . '" height="' . $this->img->height . '" alt="' . $this->iCSIMImgAlt . "\" />\n";
1078
    }
1079
1080 17
    public function GetTextsYMinMax($aY2 = false)
1081
    {
1082 17
        if ($aY2) {
1083 3
            $txts = $this->y2texts;
1084
        } else {
1085 17
            $txts = $this->texts;
1086
        }
1087 17
        $n   = safe_count($txts);
1088 17
        $min = null;
1089 17
        $max = null;
1090 17
        for ($i = 0; $i < $n; ++$i) {
1091
            if ($txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null) {
1092
                if ($min === null) {
1093
                    $min = $max = $txts[$i]->iScalePosY;
1094
                } else {
1095
                    $min = min($min, $txts[$i]->iScalePosY);
1096
                    $max = max($max, $txts[$i]->iScalePosY);
1097
                }
1098
            }
1099
        }
1100 17
        if ($min !== null) {
1101
            return [$min, $max];
1102
        }
1103
1104 17
        return null;
1105
    }
1106
1107 7
    public function GetTextsXMinMax($aY2 = false)
1108
    {
1109 7
        if ($aY2) {
1110 7
            $txts = $this->y2texts;
1111
        } else {
1112 7
            $txts = $this->texts;
1113
        }
1114 7
        $n   = safe_count($txts);
1115 7
        $min = null;
1116 7
        $max = null;
1117 7
        for ($i = 0; $i < $n; ++$i) {
1118
            if ($txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null) {
1119
                if ($min === null) {
1120
                    $min = $max = $txts[$i]->iScalePosX;
1121
                } else {
1122
                    $min = min($min, $txts[$i]->iScalePosX);
1123
                    $max = max($max, $txts[$i]->iScalePosX);
1124
                }
1125
            }
1126
        }
1127 7
        if ($min !== null) {
1128
            return [$min, $max];
1129
        }
1130
1131 7
        return null;
1132
    }
1133
1134 7
    public function GetXMinMax()
1135
    {
1136 7
        list($min, $ymin) = $this->plots[0]->Min();
1137 7
        list($max, $ymax) = $this->plots[0]->Max();
1138
1139 7
        $i = 0;
1140
        // Some plots, e.g. PlotLine should not affect the scale
1141
        // and will return (null,null). We should ignore those
1142
        // values.
1143 7
        while (($min === null || $max === null) && ($i < safe_count($this->plots) - 1)) {
1144 1
            ++$i;
1145 1
            list($min, $ymin) = $this->plots[$i]->Min();
1146 1
            list($max, $ymax) = $this->plots[$i]->Max();
1147
        }
1148
1149 7
        foreach ($this->plots as $p) {
1150 7
            list($xmin, $ymin) = $p->Min();
1151 7
            list($xmax, $ymax) = $p->Max();
1152
1153 7
            if ($xmin !== null && $xmax !== null) {
1154 7
                $min = min($xmin, $min);
1155 7
                $max = max($xmax, $max);
1156
            }
1157
        }
1158
1159 7
        if ($this->y2axis != null) {
1160 1
            foreach ($this->y2plots as $p) {
1161 1
                list($xmin, $ymin) = $p->Min();
1162 1
                list($xmax, $ymax) = $p->Max();
1163 1
                $min               = min($xmin, $min);
1164 1
                $max               = max($xmax, $max);
1165
            }
1166
        }
1167
1168 7
        $n = safe_count($this->ynaxis);
1169 7
        for ($i = 0; $i < $n; ++$i) {
1170
            if ($this->ynaxis[$i] != null) {
1171
                foreach ($this->ynplots[$i] as $p) {
1172
                    list($xmin, $ymin) = $p->Min();
1173
                    list($xmax, $ymax) = $p->Max();
1174
                    $min               = min($xmin, $min);
1175
                    $max               = max($xmax, $max);
1176
                }
1177
            }
1178
        }
1179
1180 7
        return [$min, $max];
1181
    }
1182
1183 19
    public function AdjustMarginsForTitles()
1184
    {
1185
        $totrequired =
1186 19
            ($this->title->t != ''
1187 15
            ? $this->title->GetTextHeight($this->img) + $this->title->margin + 5 * SUPERSAMPLING_SCALE
1188 7
            : 0) +
1189 19
            ($this->subtitle->t != ''
1190 6
            ? $this->subtitle->GetTextHeight($this->img) + $this->subtitle->margin + 5 * SUPERSAMPLING_SCALE
1191 19
            : 0) +
1192 19
            ($this->subsubtitle->t != ''
1193
            ? $this->subsubtitle->GetTextHeight($this->img) + $this->subsubtitle->margin + 5 * SUPERSAMPLING_SCALE
1194 19
            : 0);
1195
1196 19
        $btotrequired = 0;
1197 19
        if ($this->xaxis != null && !$this->xaxis->hide && !$this->xaxis->hide_labels) {
1198
            // Minimum bottom margin
1199 19
            if ($this->xaxis->title->t != '') {
1200 5
                if ($this->img->a == 90) {
1201 1
                    $btotrequired = $this->yaxis->title->GetTextHeight($this->img) + 7;
1202
                } else {
1203 5
                    $btotrequired = $this->xaxis->title->GetTextHeight($this->img) + 7;
1204
                }
1205
            } else {
1206 16
                $btotrequired = 0;
1207
            }
1208
1209 19
            if ($this->img->a == 90) {
1210 2
                $this->img->SetFont(
1211 2
                    $this->yaxis->font_family,
1212 2
                    $this->yaxis->font_style,
1213 2
                    $this->yaxis->font_size
1214
                );
1215 2
                $lh = $this->img->GetTextHeight('Mg', $this->yaxis->label_angle);
1216
            } else {
1217 19
                $this->img->SetFont(
1218 19
                    $this->xaxis->font_family,
1219 19
                    $this->xaxis->font_style,
1220 19
                    $this->xaxis->font_size
1221
                );
1222 19
                $lh = $this->img->GetTextHeight('Mg', $this->xaxis->label_angle);
1223
            }
1224
1225 19
            $btotrequired += $lh + 6;
1226
        }
1227
1228 19
        if ($this->img->a == 90) {
1229
            // DO Nothing. It gets too messy to do this properly for 90 deg...
1230
        } else {
1231
            // need more top margin
1232 19
            if ($this->img->top_margin < $totrequired) {
1233 5
                $this->SetMargin(
1234 5
                    $this->img->raw_left_margin,
1235 5
                    $this->img->raw_right_margin,
1236 5
                    $totrequired / SUPERSAMPLING_SCALE,
1237 5
                    $this->img->raw_bottom_margin
1238
                );
1239
            }
1240
1241
            // need more bottom margin
1242 19
            if ($this->img->bottom_margin < $btotrequired) {
1243 1
                $this->SetMargin(
1244 1
                    $this->img->raw_left_margin,
1245 1
                    $this->img->raw_right_margin,
1246 1
                    $this->img->raw_top_margin,
1247 1
                    $btotrequired / SUPERSAMPLING_SCALE
1248
                );
1249
            }
1250
        }
1251 19
    }
1252
1253
    public function StrokeStore($aStrokeFileName)
1254
    {
1255
        // Get the handler to prevent the library from sending the
1256
        // image to the browser
1257
        $ih = $this->Stroke(_IMG_HANDLER);
0 ignored issues
show
Unused Code introduced by
The assignment to $ih is dead and can be removed.
Loading history...
1258
1259
        // Stroke it to a file
1260
        $this->img->Stream($aStrokeFileName);
1261
1262
        // Send it back to browser
1263
        $this->img->Headers();
1264
        $this->img->Stream();
1265
    }
1266
1267 19
    public function doAutoscaleXAxis()
1268
    {
1269
        $aPlots = array_filter($this->plots, function ($plot) {
1270
            //\Kint::dump($plot, $plot instanceof Plot\Plot);
1271 19
            return $plot instanceof Plot\Plot;
1272 19
        });
1273
1274
        //Check if we should autoscale x-axis
1275 19
        if (!$this->xscale->IsSpecified()) {
1276 17
            if (substr($this->axtype, 0, 4) == 'text') {
1277 13
                $max = 0;
1278 13
                $n   = safe_count($aPlots);
1279
1280 13
                for ($i = 0; $i < $n; ++$i) {
1281 13
                    $p = $aPlots[$i];
1282
1283
                    // We need some unfortunate sub class knowledge here in order
1284
                    // to increase number of data points in case it is a line plot
1285
                    // which has the barcenter set. If not it could mean that the
1286
                    // last point of the data is outside the scale since the barcenter
1287
                    // settings means that we will shift the entire plot half a tick step
1288
                    // to the right in oder to align with the center of the bars.
1289
1290 13
                    $cl = strtolower(get_class($p));
0 ignored issues
show
Unused Code introduced by
The assignment to $cl is dead and can be removed.
Loading history...
1291 13
                    if (empty($p->barcenter)) {
1292 13
                        $max = max($max, $p->numpoints - 1);
1293
                    } else {
1294
                        $max = max($max, $p->numpoints);
1295
                    }
1296
                }
1297 13
                $min = 0;
1298 13
                if ($this->y2axis != null) {
1299 2
                    foreach ($this->y2plots as $p) {
1300 2
                        $max = max($max, $p->numpoints - 1);
1301
                    }
1302
                }
1303 13
                $n = safe_count($this->ynaxis);
1304 13
                for ($i = 0; $i < $n; ++$i) {
1305
                    if ($this->ynaxis[$i] != null) {
1306
                        foreach ($this->ynplots[$i] as $p) {
1307
                            $max = max($max, $p->numpoints - 1);
1308
                        }
1309
                    }
1310
                }
1311
1312 13
                $this->xscale->Update($this->img, $min, $max);
1313 13
                $this->xscale->ticks->Set($this->xaxis->tick_step, 1);
1314 13
                $this->xscale->ticks->SupressMinorTickMarks();
1315
            } else {
1316 7
                list($min, $max) = $this->GetXMinMax();
1317
1318 7
                $lres = $this->GetLinesXMinMax($this->lines);
1319 7
                if ($lres) {
0 ignored issues
show
introduced by
The condition $lres is always false.
Loading history...
1320
                    list($linmin, $linmax) = $lres;
1321
                    $min                   = min($min, $linmin);
1322
                    $max                   = max($max, $linmax);
1323
                }
1324
1325 7
                $lres = $this->GetLinesXMinMax($this->y2lines);
1326 7
                if ($lres) {
0 ignored issues
show
introduced by
The condition $lres is always false.
Loading history...
1327
                    list($linmin, $linmax) = $lres;
1328
                    $min                   = min($min, $linmin);
1329
                    $max                   = max($max, $linmax);
1330
                }
1331
1332 7
                $tres = $this->GetTextsXMinMax();
1333 7
                if ($tres) {
1334
                    list($tmin, $tmax) = $tres;
1335
                    $min               = min($min, $tmin);
1336
                    $max               = max($max, $tmax);
1337
                }
1338
1339 7
                $tres = $this->GetTextsXMinMax(true);
1340 7
                if ($tres) {
1341
                    list($tmin, $tmax) = $tres;
1342
                    $min               = min($min, $tmin);
1343
                    $max               = max($max, $tmax);
1344
                }
1345
1346 7
                $this->xscale->AutoScale($this->img, $min, $max, round($this->img->plotwidth / $this->xtick_factor));
1347
            }
1348
1349
            //Adjust position of y-axis and y2-axis to minimum/maximum of x-scale
1350 17
            if (!is_numeric($this->yaxis->pos) && !is_string($this->yaxis->pos)) {
1351 17
                $this->yaxis->SetPos($this->xscale->GetMinVal());
1352
            }
1353 4
        } elseif ($this->xscale->IsSpecified() &&
1354 4
            ($this->xscale->auto_ticks || !$this->xscale->ticks->IsSpecified())) {
1355
            // The tick calculation will use the user suplied min/max values to determine
1356
            // the ticks. If auto_ticks is false the exact user specifed min and max
1357
            // values will be used for the scale.
1358
            // If auto_ticks is true then the scale might be slightly adjusted
1359
            // so that the min and max values falls on an even major step.
1360 4
            $min = $this->xscale->scale[0];
1361 4
            $max = $this->xscale->scale[1];
1362 4
            $this->xscale->AutoScale($this->img, $min, $max, round($this->img->plotwidth / $this->xtick_factor), false);
1363
1364
            // Now make sure we show enough precision to accurate display the
1365
            // labels. If this is not done then the user might end up with
1366
            // a scale that might actually start with, say 13.5, butdue to rounding
1367
            // the scale label will ony show 14.
1368 4
            if (abs(floor($min) - $min) > 0) {
1369
                // If the user has set a format then we bail out
1370
                if ($this->xscale->ticks->label_formatstr == '' && $this->xscale->ticks->label_dateformatstr == '') {
1371
                    $this->xscale->ticks->precision = abs(floor(log10(abs(floor($min) - $min)))) + 1;
1372
                }
1373
            }
1374
        }
1375
1376
        // Position the optional Y2 and Yn axis to the rightmost position of the x-axis
1377 19
        if ($this->y2axis != null) {
1378 3
            if (!is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos)) {
1379
                $this->y2axis->SetPos($this->xscale->GetMaxVal());
1380
            }
1381 3
            $this->y2axis->SetTitleSide(SIDE_RIGHT);
1382
        }
1383
1384 19
        $n      = safe_count($this->ynaxis);
1385 19
        $nY2adj = $this->y2axis != null ? $this->iYAxisDeltaPos : 0;
1386 19
        for ($i = 0; $i < $n; ++$i) {
1387
            if ($this->ynaxis[$i] != null) {
1388
                if (!is_numeric($this->ynaxis[$i]->pos) && !is_string($this->ynaxis[$i]->pos)) {
1389
                    $this->ynaxis[$i]->SetPos($this->xscale->GetMaxVal());
1390
                    $this->ynaxis[$i]->SetPosAbsDelta($i * $this->iYAxisDeltaPos + $nY2adj);
1391
                }
1392
                $this->ynaxis[$i]->SetTitleSide(SIDE_RIGHT);
1393
            }
1394
        }
1395 19
    }
1396
1397 19
    public function doAutoScaleYnAxis()
1398
    {
1399 19
        if ($this->y2scale != null) {
1400 3
            if (!$this->y2scale->IsSpecified() && safe_count($this->y2plots) > 0) {
1401 3
                list($min, $max) = $this->GetPlotsYMinMax($this->y2plots);
1402
1403 3
                $lres = $this->GetLinesYMinMax($this->y2lines);
1404 3
                if (is_array($lres)) {
0 ignored issues
show
introduced by
The condition is_array($lres) is always false.
Loading history...
1405
                    list($linmin, $linmax) = $lres;
1406
                    $min                   = min($min, $linmin);
1407
                    $max                   = max($max, $linmax);
1408
                }
1409 3
                $tres = $this->GetTextsYMinMax(true);
1410 3
                if (is_array($tres)) {
1411
                    list($tmin, $tmax) = $tres;
1412
                    $min               = min($min, $tmin);
1413
                    $max               = max($max, $tmax);
1414
                }
1415 3
                $this->y2scale->AutoScale($this->img, $min, $max, $this->img->plotheight / $this->ytick_factor);
1416
            } elseif ($this->y2scale->IsSpecified() && ($this->y2scale->auto_ticks || !$this->y2scale->ticks->IsSpecified())) {
1417
                // The tick calculation will use the user suplied min/max values to determine
1418
                // the ticks. If auto_ticks is false the exact user specifed min and max
1419
                // values will be used for the scale.
1420
                // If auto_ticks is true then the scale might be slightly adjusted
1421
                // so that the min and max values falls on an even major step.
1422
                $min = $this->y2scale->scale[0];
1423
                $max = $this->y2scale->scale[1];
1424
                $this->y2scale->AutoScale(
1425
                    $this->img,
1426
                    $min,
1427
                    $max,
1428
                    $this->img->plotheight / $this->ytick_factor,
1429
                    $this->y2scale->auto_ticks
1430
                );
1431
1432
                // Now make sure we show enough precision to accurate display the
1433
                // labels. If this is not done then the user might end up with
1434
                // a scale that might actually start with, say 13.5, butdue to rounding
1435
                // the scale label will ony show 14.
1436
                if (abs(floor($min) - $min) > 0) {
1437
                    // If the user has set a format then we bail out
1438
                    if ($this->y2scale->ticks->label_formatstr == '' && $this->y2scale->ticks->label_dateformatstr == '') {
1439
                        $this->y2scale->ticks->precision = abs(floor(log10(abs(floor($min) - $min)))) + 1;
1440
                    }
1441
                }
1442
            }
1443
        }
1444
1445
        //
1446
        // Autoscale the extra Y-axises
1447
        //
1448 19
        $n = safe_count($this->ynaxis);
1449 19
        for ($i = 0; $i < $n; ++$i) {
1450
            if ($this->ynscale[$i] != null) {
1451
                if (!$this->ynscale[$i]->IsSpecified() && safe_count($this->ynplots[$i]) > 0) {
1452
                    list($min, $max) = $this->GetPlotsYMinMax($this->ynplots[$i]);
1453
                    $this->ynscale[$i]->AutoScale($this->img, $min, $max, $this->img->plotheight / $this->ytick_factor);
1454
                } elseif ($this->ynscale[$i]->IsSpecified() && ($this->ynscale[$i]->auto_ticks || !$this->ynscale[$i]->ticks->IsSpecified())) {
1455
                    // The tick calculation will use the user suplied min/max values to determine
1456
                    // the ticks. If auto_ticks is false the exact user specifed min and max
1457
                    // values will be used for the scale.
1458
                    // If auto_ticks is true then the scale might be slightly adjusted
1459
                    // so that the min and max values falls on an even major step.
1460
                    $min = $this->ynscale[$i]->scale[0];
1461
                    $max = $this->ynscale[$i]->scale[1];
1462
                    $this->ynscale[$i]->AutoScale(
1463
                        $this->img,
1464
                        $min,
1465
                        $max,
1466
                        $this->img->plotheight / $this->ytick_factor,
1467
                        $this->ynscale[$i]->auto_ticks
1468
                    );
1469
1470
                    // Now make sure we show enough precision to accurate display the
1471
                    // labels. If this is not done then the user might end up with
1472
                    // a scale that might actually start with, say 13.5, butdue to rounding
1473
                    // the scale label will ony show 14.
1474
                    if (abs(floor($min) - $min) > 0) {
1475
                        // If the user has set a format then we bail out
1476
                        if ($this->ynscale[$i]->ticks->label_formatstr == '' && $this->ynscale[$i]->ticks->label_dateformatstr == '') {
1477
                            $this->ynscale[$i]->ticks->precision = abs(floor(log10(abs(floor($min) - $min)))) + 1;
1478
                        }
1479
                    }
1480
                }
1481
            }
1482
        }
1483 19
    }
1484
1485 19
    public function doAutoScaleYAxis()
1486
    {
1487
        //Check if we should autoscale y-axis
1488 19
        if (!$this->yscale->IsSpecified() && safe_count($this->plots) > 0) {
1489 17
            list($min, $max) = $this->GetPlotsYMinMax($this->plots);
1490 17
            $lres            = $this->GetLinesYMinMax($this->lines);
1491 17
            if (is_array($lres)) {
0 ignored issues
show
introduced by
The condition is_array($lres) is always false.
Loading history...
1492
                list($linmin, $linmax) = $lres;
1493
                $min                   = min($min, $linmin);
1494
                $max                   = max($max, $linmax);
1495
            }
1496 17
            $tres = $this->GetTextsYMinMax();
1497 17
            if (is_array($tres)) {
1498
                list($tmin, $tmax) = $tres;
1499
                $min               = min($min, $tmin);
1500
                $max               = max($max, $tmax);
1501
            }
1502 17
            $this->yscale->AutoScale(
1503 17
                $this->img,
1504 17
                $min,
1505 17
                $max,
1506 17
                $this->img->plotheight / $this->ytick_factor
1507
            );
1508 4
        } elseif ($this->yscale->IsSpecified() && ($this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified())) {
1509
            // The tick calculation will use the user suplied min/max values to determine
1510
            // the ticks. If auto_ticks is false the exact user specifed min and max
1511
            // values will be used for the scale.
1512
            // If auto_ticks is true then the scale might be slightly adjusted
1513
            // so that the min and max values falls on an even major step.
1514 4
            $min = $this->yscale->scale[0];
1515 4
            $max = $this->yscale->scale[1];
1516 4
            $this->yscale->AutoScale(
1517 4
                $this->img,
1518 4
                $min,
1519 4
                $max,
1520 4
                $this->img->plotheight / $this->ytick_factor,
1521 4
                $this->yscale->auto_ticks
1522
            );
1523
1524
            // Now make sure we show enough precision to accurate display the
1525
            // labels. If this is not done then the user might end up with
1526
            // a scale that might actually start with, say 13.5, butdue to rounding
1527
            // the scale label will ony show 14.
1528 4
            if (abs(floor($min) - $min) > 0) {
1529
                // If the user has set a format then we bail out
1530
                if ($this->yscale->ticks->label_formatstr == '' && $this->yscale->ticks->label_dateformatstr == '') {
1531
                    $this->yscale->ticks->precision = abs(floor(log10(abs(floor($min) - $min)))) + 1;
1532
                }
1533
            }
1534
        }
1535 19
    }
1536
1537 19
    public function InitScaleConstants()
1538
    {
1539
        // Setup scale constants
1540 19
        if ($this->yscale) {
1541 19
            $this->yscale->InitConstants($this->img);
1542
        }
1543
1544 19
        if ($this->xscale) {
1545 19
            $this->xscale->InitConstants($this->img);
1546
        }
1547
1548 19
        if ($this->y2scale) {
1549 3
            $this->y2scale->InitConstants($this->img);
1550
        }
1551
1552 19
        $n = safe_count($this->ynscale);
1553 19
        for ($i = 0; $i < $n; ++$i) {
1554
            if ($this->ynscale[$i]) {
1555
                $this->ynscale[$i]->InitConstants($this->img);
1556
            }
1557
        }
1558 19
    }
1559
1560 19
    public function doPrestrokeAdjustments()
1561
    {
1562
        // Do any pre-stroke adjustment that is needed by the different plot types
1563
        // (i.e bar plots want's to add an offset to the x-labels etc)
1564 19
        for ($i = 0; $i < safe_count($this->plots); ++$i) {
1565 19
            if ($this->plots[$i] instanceof Plot\Plot) {
1566 19
                $this->plots[$i]->PreStrokeAdjust($this);
1567 19
                $this->plots[$i]->DoLegend($this);
1568
            }
1569
        }
1570
1571
        // Any plots on the second Y scale?
1572 19
        if ($this->y2scale != null) {
1573 3
            for ($i = 0; $i < safe_count($this->y2plots); ++$i) {
1574 3
                if ($this->plots[$i] instanceof Plot\Plot) {
1575 3
                    $this->y2plots[$i]->PreStrokeAdjust($this);
1576 3
                    $this->y2plots[$i]->DoLegend($this);
1577
                }
1578
            }
1579
        }
1580
1581
        // Any plots on the extra Y axises?
1582 19
        $n = safe_count($this->ynaxis);
1583 19
        for ($i = 0; $i < $n; ++$i) {
1584
            if ($this->ynplots == null || $this->ynplots[$i] == null) {
1585
                Util\JpGraphError::RaiseL(25032, $i); //("No plots for Y-axis nbr:$i");
1586
            }
1587
            $m = safe_count($this->ynplots[$i]);
1588
            for ($j = 0; $j < $m; ++$j) {
1589
                $this->ynplots[$i][$j]->PreStrokeAdjust($this);
1590
                $this->ynplots[$i][$j]->DoLegend($this);
1591
            }
1592
        }
1593 19
    }
1594
1595 19
    public function StrokeBands($aDepth, $aCSIM)
1596
    {
1597
        // Stroke bands
1598 19
        if ($this->bands != null && !$aCSIM) {
1599
            for ($i = 0; $i < safe_count($this->bands); ++$i) {
1600
                // Stroke all bands that asks to be in the background
1601
                if ($this->bands[$i]->depth == $aDepth) {
1602
                    $this->bands[$i]->Stroke($this->img, $this->xscale, $this->yscale);
1603
                }
1604
            }
1605
        }
1606
1607 19
        if ($this->y2bands != null && $this->y2scale != null && !$aCSIM) {
1608
            for ($i = 0; $i < safe_count($this->y2bands); ++$i) {
1609
                // Stroke all bands that asks to be in the foreground
1610
                if ($this->y2bands[$i]->depth == $aDepth) {
1611
                    $this->y2bands[$i]->Stroke($this->img, $this->xscale, $this->y2scale);
1612
                }
1613
            }
1614
        }
1615 19
    }
1616
1617
    // Stroke the graph
1618
    // $aStrokeFileName If != "" the image will be written to this file and NOT
1619
    // streamed back to the browser
1620 19
    public function Stroke($aStrokeFileName = '')
1621
    {
1622
        // Fist make a sanity check that user has specified a scale
1623 19
        if (empty($this->yscale)) {
1624
            Util\JpGraphError::RaiseL(25031); //('You must specify what scale to use with a call to Graph::SetScale().');
1625
        }
1626
1627
        // Start by adjusting the margin so that potential titles will fit.
1628 19
        $this->AdjustMarginsForTitles();
1629
1630
        // Give the plot a chance to do any scale adjuments the individual plots
1631
        // wants to do. Right now this is only used by the contour plot to set scale
1632
        // limits
1633 19
        for ($i = 0; $i < safe_count($this->plots); ++$i) {
1634 19
            if ($this->plots[$i] instanceof Plot\Plot) {
1635 19
                $this->plots[$i]->PreScaleSetup($this);
1636
            }
1637
            //\Kint::dump($this->plots[$i]);
1638
        }
1639
1640
        // Init scale constants that are used to calculate the transformation from
1641
        // world to pixel coordinates
1642 19
        $this->InitScaleConstants();
1643
1644
        // If the filename is the predefined value = '_csim_special_'
1645
        // we assume that the call to stroke only needs to do enough
1646
        // to correctly generate the CSIM maps.
1647
        // We use this variable to skip things we don't strictly need
1648
        // to do to generate the image map to improve performance
1649
        // a best we can. Therefor you will see a lot of tests !$_csim in the
1650
        // code below.
1651 19
        $_csim = ($aStrokeFileName === _CSIM_SPECIALFILE);
1652
1653
        // If we are called the second time (perhaps the user has called GetHTMLImageMap()
1654
        // himself then the legends have alsready been populated once in order to get the
1655
        // CSIM coordinats. Since we do not want the legends to be populated a second time
1656
        // we clear the legends
1657 19
        $this->legend->Clear();
1658
1659
        // We need to know if we have stroked the plot in the
1660
        // GetCSIMareas. Otherwise the CSIM hasn't been generated
1661
        // and in the case of GetCSIM called before stroke to generate
1662
        // CSIM without storing an image to disk GetCSIM must call Stroke.
1663 19
        $this->iHasStroked = true;
1664
1665
        // Setup pre-stroked adjustments and Legends
1666 19
        $this->doPrestrokeAdjustments();
1667
1668 19
        if ($this->graph_theme) {
1669 19
            $this->graph_theme->PreStrokeApply($this);
1670
        }
1671
1672
        // Bail out if any of the Y-axis not been specified and
1673
        // has no plots. (This means it is impossible to do autoscaling and
1674
        // no other scale was given so we can't possible draw anything). If you use manual
1675
        // scaling you also have to supply the tick steps as well.
1676 19
        if ((!$this->yscale->IsSpecified() && safe_count($this->plots) == 0) ||
1677 19
            ($this->y2scale != null && !$this->y2scale->IsSpecified() && safe_count($this->y2plots) == 0)) {
1678
            //$e = "n=". safe_count($this->y2plots)."\n";
1679
            // $e = "Can't draw unspecified Y-scale.<br>\nYou have either:<br>\n";
1680
            // $e .= "1. Specified an Y axis for autoscaling but have not supplied any plots<br>\n";
1681
            // $e .= "2. Specified a scale manually but have forgot to specify the tick steps";
1682
            Util\JpGraphError::RaiseL(25026);
1683
        }
1684
1685
        // Bail out if no plots and no specified X-scale
1686 19
        if ((!$this->xscale->IsSpecified() && safe_count($this->plots) == 0 && safe_count($this->y2plots) == 0)) {
1687
            Util\JpGraphError::RaiseL(25034); //("<strong>JpGraph: Can't draw unspecified X-scale.</strong><br>No plots.<br>");
1688
        }
1689
1690
        // Autoscale the normal Y-axis
1691 19
        $this->doAutoScaleYAxis();
1692
1693
        // Autoscale all additiopnal y-axis
1694 19
        $this->doAutoScaleYnAxis();
1695
1696
        // Autoscale the regular x-axis and position the y-axis properly
1697 19
        $this->doAutoScaleXAxis();
1698
1699
        // If we have a negative values and x-axis position is at 0
1700
        // we need to supress the first and possible the last tick since
1701
        // they will be drawn on top of the y-axis (and possible y2 axis)
1702
        // The test below might seem strange the reasone being that if
1703
        // the user hasn't specified a value for position this will not
1704
        // be set until we do the stroke for the axis so as of now it
1705
        // is undefined.
1706
        // For X-text scale we ignore all this since the tick are usually
1707
        // much further in and not close to the Y-axis. Hence the test
1708
        // for 'text'
1709 19
        if (($this->yaxis->pos == $this->xscale->GetMinVal() || (is_string($this->yaxis->pos) && $this->yaxis->pos == 'min')) &&
1710 19
            !is_numeric($this->xaxis->pos) && $this->yscale->GetMinVal() < 0 &&
1711 19
            substr($this->axtype, 0, 4) != 'text' && $this->xaxis->pos != 'min') {
1712
            //$this->yscale->ticks->SupressZeroLabel(false);
1713 2
            $this->xscale->ticks->SupressFirst();
1714 2
            if ($this->y2axis != null) {
1715 2
                $this->xscale->ticks->SupressLast();
1716
            }
1717 19
        } elseif (!is_numeric($this->yaxis->pos) && $this->yaxis->pos == 'max') {
1718
            $this->xscale->ticks->SupressLast();
1719
        }
1720
1721 19
        if (!$_csim) {
1722 19
            $this->StrokePlotArea();
1723 19
            if ($this->iIconDepth == DEPTH_BACK) {
1724 19
                $this->StrokeIcons();
1725
            }
1726
        }
1727 19
        $this->StrokeAxis(false);
1728
1729
        // Stroke colored bands
1730 19
        $this->StrokeBands(DEPTH_BACK, $_csim);
1731
1732 19
        if ($this->grid_depth == DEPTH_BACK && !$_csim) {
1733 19
            $this->ygrid->Stroke();
1734 19
            $this->xgrid->Stroke();
1735
        }
1736
1737
        // Stroke Y2-axis
1738 19
        if ($this->y2axis != null && !$_csim) {
1739 3
            $this->y2axis->Stroke($this->xscale);
1740 3
            $this->y2grid->Stroke();
1741
        }
1742
1743
        // Stroke yn-axis
1744 19
        $n = safe_count($this->ynaxis);
1745 19
        for ($i = 0; $i < $n; ++$i) {
1746
            $this->ynaxis[$i]->Stroke($this->xscale);
1747
        }
1748
1749 19
        $oldoff = $this->xscale->off;
1750 19
        if (substr($this->axtype, 0, 4) == 'text') {
1751 13
            if ($this->text_scale_abscenteroff > -1) {
1752
                // For a text scale the scale factor is the number of pixel per step.
1753
                // Hence we can use the scale factor as a substitute for number of pixels
1754
                // per major scale step and use that in order to adjust the offset so that
1755
                // an object of width "abscenteroff" becomes centered.
1756 1
                $this->xscale->off += round($this->xscale->scale_factor / 2) - round($this->text_scale_abscenteroff / 2);
1757
            } else {
1758 12
                $this->xscale->off += ceil($this->xscale->scale_factor * $this->text_scale_off * $this->xscale->ticks->minor_step);
1759
            }
1760
        }
1761
1762 19
        if ($this->iDoClipping) {
1763 1
            $oldimage = $this->img->CloneCanvasH();
1764
        }
1765
1766 19
        if (!$this->y2orderback) {
1767
            // Stroke all plots for Y1 axis
1768
            for ($i = 0; $i < safe_count($this->plots); ++$i) {
1769
                $this->plots[$i]->Stroke($this->img, $this->xscale, $this->yscale);
1770
                if ($this->plots[$i] instanceof Plot\Plot) {
1771
                    $this->plots[$i]->StrokeMargin($this->img);
1772
                }
1773
            }
1774
        }
1775
1776
        // Stroke all plots for Y2 axis
1777 19
        if ($this->y2scale != null) {
1778 3
            for ($i = 0; $i < safe_count($this->y2plots); ++$i) {
1779 3
                $this->y2plots[$i]->Stroke($this->img, $this->xscale, $this->y2scale);
1780
            }
1781
        }
1782
1783 19
        if ($this->y2orderback) {
1784
            // Stroke all plots for Y1 axis
1785 19
            for ($i = 0; $i < safe_count($this->plots); ++$i) {
1786 19
                $this->plots[$i]->Stroke($this->img, $this->xscale, $this->yscale);
1787 19
                if ($this->plots[$i] instanceof Plot\Plot) {
1788 19
                    $this->plots[$i]->StrokeMargin($this->img);
1789
                }
1790
            }
1791
        }
1792
1793 19
        $n = safe_count($this->ynaxis);
1794 19
        for ($i = 0; $i < $n; ++$i) {
1795
            $m = safe_count($this->ynplots[$i]);
1796
            for ($j = 0; $j < $m; ++$j) {
1797
                $this->ynplots[$i][$j]->Stroke($this->img, $this->xscale, $this->ynscale[$i]);
1798
                if ($this->ynplots[$i][$j] instanceof Plot\Plot) {
1799
                    $this->ynplots[$i][$j]->StrokeMargin($this->img);
1800
                }
1801
            }
1802
        }
1803
1804 19
        if ($this->iIconDepth == DEPTH_FRONT) {
1805
            $this->StrokeIcons();
1806
        }
1807
1808 19
        if ($this->iDoClipping) {
1809
            // Clipping only supports graphs at 0 and 90 degrees
1810 1
            if ($this->img->a == 0) {
1811 1
                $this->img->CopyCanvasH(
1812 1
                    $oldimage,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $oldimage does not seem to be defined for all execution paths leading up to this point.
Loading history...
1813 1
                    $this->img->img,
1814 1
                    $this->img->left_margin,
1815 1
                    $this->img->top_margin,
1816 1
                    $this->img->left_margin,
1817 1
                    $this->img->top_margin,
1818 1
                    $this->img->plotwidth + 1,
1819 1
                    $this->img->plotheight
1820
                );
1821
            } elseif ($this->img->a == 90) {
1822
                $adj = ($this->img->height - $this->img->width) / 2;
1823
                $this->img->CopyCanvasH(
1824
                    $oldimage,
1825
                    $this->img->img,
1826
                    $this->img->bottom_margin - $adj,
1827
                    $this->img->left_margin + $adj,
1828
                    $this->img->bottom_margin - $adj,
1829
                    $this->img->left_margin + $adj,
1830
                    $this->img->plotheight + 1,
1831
                    $this->img->plotwidth
1832
                );
1833
            } else {
1834
                Util\JpGraphError::RaiseL(25035, $this->img->a); //('You have enabled clipping. Cliping is only supported for graphs at 0 or 90 degrees rotation. Please adjust you current angle (='.$this->img->a.' degrees) or disable clipping.');
1835
            }
1836 1
            $this->img->Destroy();
1837 1
            $this->img->SetCanvasH($oldimage);
1838
        }
1839
1840 19
        $this->xscale->off = $oldoff;
1841
1842 19
        if ($this->grid_depth == DEPTH_FRONT && !$_csim) {
1843 1
            $this->ygrid->Stroke();
1844 1
            $this->xgrid->Stroke();
1845
        }
1846
1847
        // Stroke colored bands
1848 19
        $this->StrokeBands(DEPTH_FRONT, $_csim);
1849
1850
        // Finally draw the axis again since some plots may have nagged
1851
        // the axis in the edges.
1852 19
        if (!$_csim) {
1853 19
            $this->StrokeAxis();
1854
        }
1855
1856 19
        if ($this->y2scale != null && !$_csim) {
1857 3
            $this->y2axis->Stroke($this->xscale, false);
1858
        }
1859
1860 19
        if (!$_csim) {
1861 19
            $this->StrokePlotBox();
1862
        }
1863
1864
        // The titles and legends never gets rotated so make sure
1865
        // that the angle is 0 before stroking them
1866 19
        $aa = $this->img->SetAngle(0);
1867 19
        $this->StrokeTitles();
1868 19
        $this->footer->Stroke($this->img);
1869 19
        $this->legend->Stroke($this->img);
1870 19
        $this->img->SetAngle($aa);
1871 19
        $this->StrokeTexts();
1872 19
        $this->StrokeTables();
1873
1874 19
        if (!$_csim) {
1875 19
            $this->img->SetAngle($aa);
1876
1877
            // Draw an outline around the image map
1878 19
            if (_JPG_DEBUG) {
1879
                $this->DisplayClientSideaImageMapAreas();
1880
            }
1881
1882
            // Should we do any final image transformation
1883 19
            if ($this->iImgTrans) {
1884
                $tform          = new Image\ImgTrans($this->img->img);
1885
                $this->img->img = $tform->Skew3D(
1886
                    $this->iImgTransHorizon,
1887
                    $this->iImgTransSkewDist,
1888
                    $this->iImgTransDirection,
1889
                    $this->iImgTransHighQ,
1890
                    $this->iImgTransMinSize,
1891
                    $this->iImgTransFillColor,
1892
                    $this->iImgTransBorder
1893
                );
1894
            }
1895
1896
            // If the filename is given as the special "__handle"
1897
            // then the image handler is returned and the image is NOT
1898
            // streamed back
1899 19
            if ($aStrokeFileName == _IMG_HANDLER) {
1900
                return $this->img->img;
1901
            }
1902
            // Finally stream the generated picture
1903 19
            $this->cache->PutAndStream($this->img, $this->cache_name, $this->inline, $aStrokeFileName);
1904
        }
1905 19
    }
1906
1907
    public function SetAxisLabelBackground($aType, $aXFColor = 'lightgray', $aXColor = 'black', $aYFColor = 'lightgray', $aYColor = 'black')
1908
    {
1909
        $this->iAxisLblBgType       = $aType;
1910
        $this->iXAxisLblBgFillColor = $aXFColor;
1911
        $this->iXAxisLblBgColor     = $aXColor;
1912
        $this->iYAxisLblBgFillColor = $aYFColor;
1913
        $this->iYAxisLblBgColor     = $aYColor;
1914
    }
1915
1916 19
    public function StrokeAxisLabelBackground()
1917
    {
1918
        // Types
1919
        // 0 = No background
1920
        // 1 = Only X-labels, length of axis
1921
        // 2 = Only Y-labels, length of axis
1922
        // 3 = As 1 but extends to width of graph
1923
        // 4 = As 2 but extends to height of graph
1924
        // 5 = Combination of 3 & 4
1925
        // 6 = Combination of 1 & 2
1926
1927 19
        $t = $this->iAxisLblBgType;
1928 19
        if ($t < 1) {
1929 19
            return;
1930
        }
1931
1932
        // Stroke optional X-axis label background color
1933
        if ($t == 1 || $t == 3 || $t == 5 || $t == 6) {
1934
            $this->img->PushColor($this->iXAxisLblBgFillColor);
1935
            if ($t == 1 || $t == 6) {
1936
                $xl = $this->img->left_margin;
1937
                $yu = $this->img->height - $this->img->bottom_margin + 1;
1938
                $xr = $this->img->width - $this->img->right_margin;
1939
                $yl = $this->img->height - 1 - $this->frame_weight;
1940
            } else {
1941
                // t==3 || t==5
1942
                $xl = $this->frame_weight;
1943
                $yu = $this->img->height - $this->img->bottom_margin + 1;
1944
                $xr = $this->img->width - 1 - $this->frame_weight;
1945
                $yl = $this->img->height - 1 - $this->frame_weight;
1946
            }
1947
1948
            $this->img->FilledRectangle($xl, $yu, $xr, $yl);
1949
            $this->img->PopColor();
1950
1951
            // Check if we should add the vertical lines at left and right edge
1952
            if ($this->iXAxisLblBgColor !== '') {
1953
                // Hardcode to one pixel wide
1954
                $this->img->SetLineWeight(1);
1955
                $this->img->PushColor($this->iXAxisLblBgColor);
1956
                if ($t == 1 || $t == 6) {
1957
                    $this->img->Line($xl, $yu, $xl, $yl);
1958
                    $this->img->Line($xr, $yu, $xr, $yl);
1959
                } else {
1960
                    $xl = $this->img->width - $this->img->right_margin;
1961
                    $this->img->Line($xl, $yu - 1, $xr, $yu - 1);
1962
                }
1963
                $this->img->PopColor();
1964
            }
1965
        }
1966
1967
        if ($t == 2 || $t == 4 || $t == 5 || $t == 6) {
1968
            $this->img->PushColor($this->iYAxisLblBgFillColor);
1969
            if ($t == 2 || $t == 6) {
1970
                $xl = $this->frame_weight;
1971
                $yu = $this->frame_weight + $this->img->top_margin;
1972
                $xr = $this->img->left_margin - 1;
1973
                $yl = $this->img->height - $this->img->bottom_margin + 1;
1974
            } else {
1975
                $xl = $this->frame_weight;
1976
                $yu = $this->frame_weight;
1977
                $xr = $this->img->left_margin - 1;
1978
                $yl = $this->img->height - 1 - $this->frame_weight;
1979
            }
1980
1981
            $this->img->FilledRectangle($xl, $yu, $xr, $yl);
1982
            $this->img->PopColor();
1983
1984
            // Check if we should add the vertical lines at left and right edge
1985
            if ($this->iXAxisLblBgColor !== '') {
1986
                $this->img->PushColor($this->iXAxisLblBgColor);
1987
                if ($t == 2 || $t == 6) {
1988
                    $this->img->Line($xl, $yu - 1, $xr, $yu - 1);
1989
                    $this->img->Line($xl, $yl - 1, $xr, $yl - 1);
1990
                } else {
1991
                    $this->img->Line($xr + 1, $yu, $xr + 1, $this->img->top_margin);
1992
                }
1993
                $this->img->PopColor();
1994
            }
1995
        }
1996
    }
1997
1998 19
    public function StrokeAxis($aStrokeLabels = true)
1999
    {
2000 19
        if ($aStrokeLabels) {
2001 19
            $this->StrokeAxisLabelBackground();
2002
        }
2003
2004
        // Stroke axis
2005 19
        if ($this->iAxisStyle != AXSTYLE_SIMPLE) {
2006 3
            switch ($this->iAxisStyle) {
2007 3
                case AXSTYLE_BOXIN:
2008 2
                    $toppos    = SIDE_DOWN;
2009 2
                    $bottompos = SIDE_UP;
2010 2
                    $leftpos   = SIDE_RIGHT;
2011 2
                    $rightpos  = SIDE_LEFT;
2012
2013 2
                    break;
2014 2
                case AXSTYLE_BOXOUT:
2015 2
                    $toppos    = SIDE_UP;
2016 2
                    $bottompos = SIDE_DOWN;
2017 2
                    $leftpos   = SIDE_LEFT;
2018 2
                    $rightpos  = SIDE_RIGHT;
2019
2020 2
                    break;
2021
                case AXSTYLE_YBOXIN:
2022
                    $toppos    = false;
2023
                    $bottompos = SIDE_UP;
2024
                    $leftpos   = SIDE_RIGHT;
2025
                    $rightpos  = SIDE_LEFT;
2026
2027
                    break;
2028
                case AXSTYLE_YBOXOUT:
2029
                    $toppos    = false;
2030
                    $bottompos = SIDE_DOWN;
2031
                    $leftpos   = SIDE_LEFT;
2032
                    $rightpos  = SIDE_RIGHT;
2033
2034
                    break;
2035
                default:
2036
                    Util\JpGraphError::RaiseL(25036, $this->iAxisStyle); //('Unknown AxisStyle() : '.$this->iAxisStyle);
2037
                    break;
2038
            }
2039
2040
            // By default we hide the first label so it doesn't cross the
2041
            // Y-axis in case the positon hasn't been set by the user.
2042
            // However, if we use a box we always want the first value
2043
            // displayed so we make sure it will be displayed.
2044 3
            $this->xscale->ticks->SupressFirst(false);
2045
2046
            // Now draw the bottom X-axis
2047 3
            $this->xaxis->SetPos('min');
2048 3
            $this->xaxis->SetLabelSide(SIDE_DOWN);
2049 3
            $this->xaxis->scale->ticks->SetSide($bottompos);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $bottompos does not seem to be defined for all execution paths leading up to this point.
Loading history...
2050 3
            $this->xaxis->Stroke($this->yscale, $aStrokeLabels);
2051
2052 3
            if ($toppos !== false) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $toppos does not seem to be defined for all execution paths leading up to this point.
Loading history...
2053
                // We also want a top X-axis
2054 3
                $this->xaxis = $this->xaxis;
2055 3
                $this->xaxis->SetPos('max');
2056 3
                $this->xaxis->SetLabelSide(SIDE_UP);
2057
                // No title for the top X-axis
2058 3
                if ($aStrokeLabels) {
2059 3
                    $this->xaxis->title->Set('');
2060
                }
2061 3
                $this->xaxis->scale->ticks->SetSide($toppos);
2062 3
                $this->xaxis->Stroke($this->yscale, $aStrokeLabels);
2063
            }
2064
2065
            // Stroke the left Y-axis
2066 3
            $this->yaxis->SetPos('min');
2067 3
            $this->yaxis->SetLabelSide(SIDE_LEFT);
2068 3
            $this->yaxis->scale->ticks->SetSide($leftpos);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $leftpos does not seem to be defined for all execution paths leading up to this point.
Loading history...
2069 3
            $this->yaxis->Stroke($this->xscale, $aStrokeLabels);
2070
2071
            // Stroke the  right Y-axis
2072 3
            $this->yaxis->SetPos('max');
2073
            // No title for the right side
2074 3
            if ($aStrokeLabels) {
2075 3
                $this->yaxis->title->Set('');
2076
            }
2077 3
            $this->yaxis->SetLabelSide(SIDE_RIGHT);
2078 3
            $this->yaxis->scale->ticks->SetSide($rightpos);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $rightpos does not seem to be defined for all execution paths leading up to this point.
Loading history...
2079 3
            $this->yaxis->Stroke($this->xscale, $aStrokeLabels);
2080
        } else {
2081 19
            $this->xaxis->Stroke($this->yscale, $aStrokeLabels);
2082 19
            $this->yaxis->Stroke($this->xscale, $aStrokeLabels);
2083
        }
2084 19
    }
2085
2086
    // Private helper function for backgound image
2087 5
    public static function LoadBkgImage($aImgFormat = '', $aFile = '', $aImgStr = '')
2088
    {
2089 5
        if ($aImgStr != '') {
2090
            return Image::CreateFromString($aImgStr);
2091
        }
2092
2093
        // Remove case sensitivity and setup appropriate function to create image
2094
        // Get file extension. This should be the LAST '.' separated part of the filename
2095 5
        $e   = explode('.', $aFile);
2096 5
        $ext = strtolower($e[count($e) - 1]);
2097 5
        if ($ext == 'jpeg') {
2098
            $ext = 'jpg';
2099
        }
2100
2101 5
        if (trim($ext) == '') {
2102
            $ext = 'png'; // Assume PNG if no extension specified
2103
        }
2104
2105 5
        if ($aImgFormat == '') {
2106 2
            $imgtag = $ext;
2107
        } else {
2108 4
            $imgtag = $aImgFormat;
2109
        }
2110
2111 5
        $supported = imagetypes();
2112 5
        if (($ext == 'jpg' && !($supported & IMG_JPG)) ||
2113 5
            ($ext == 'gif' && !($supported & IMG_GIF)) ||
2114 5
            ($ext == 'png' && !($supported & IMG_PNG)) ||
2115 5
            ($ext == 'bmp' && !($supported & IMG_WBMP)) ||
2116 5
            ($ext == 'xpm' && !($supported & IMG_XPM))) {
2117
            Util\JpGraphError::RaiseL(25037, $aFile); //('The image format of your background image ('.$aFile.') is not supported in your system configuration. ');
2118
        }
2119
2120 5
        if ($imgtag == 'jpg' || $imgtag == 'jpeg') {
2121 3
            $f      = 'imagecreatefromjpeg';
2122 3
            $imgtag = 'jpg';
2123
        } else {
2124 2
            $f = 'imagecreatefrom' . $imgtag;
2125
        }
2126
2127
        // Compare specified image type and file extension
2128 5
        if ($imgtag != $ext) {
2129
            //$t = "Background image seems to be of different type (has different file extension) than specified imagetype. Specified: '".$aImgFormat."'File: '".$aFile."'";
2130
            Util\JpGraphError::RaiseL(25038, $aImgFormat, $aFile);
2131
        }
2132
2133 5
        $img = @$f($aFile);
2134 5
        if (!$img) {
2135
            Util\JpGraphError::RaiseL(25039, $aFile); //(" Can't read background image: '".$aFile."'");
2136
        }
2137
2138 5
        return $img;
2139
    }
2140
2141 15
    public function StrokePlotGrad()
2142
    {
2143 15
        if ($this->plot_gradtype < 0) {
2144 15
            return;
2145
        }
2146
2147 1
        $grad = new Plot\Gradient($this->img);
2148 1
        $xl   = $this->img->left_margin;
2149 1
        $yt   = $this->img->top_margin;
2150 1
        $xr   = $xl + $this->img->plotwidth + 1;
2151 1
        $yb   = $yt + $this->img->plotheight;
2152 1
        $grad->FilledRectangle($xl, $yt, $xr, $yb, $this->plot_gradfrom, $this->plot_gradto, $this->plot_gradtype);
2153 1
    }
2154
2155 17
    public function StrokeBackgroundGrad()
2156
    {
2157 17
        if ($this->bkg_gradtype < 0) {
2158 15
            return;
2159
        }
2160
2161 3
        $grad = new Plot\Gradient($this->img);
2162 3
        if ($this->bkg_gradstyle == BGRAD_PLOT) {
2163 2
            $xl = $this->img->left_margin;
2164 2
            $yt = $this->img->top_margin;
2165 2
            $xr = $xl + $this->img->plotwidth + 1;
2166 2
            $yb = $yt + $this->img->plotheight;
2167 2
            $grad->FilledRectangle($xl, $yt, $xr, $yb, $this->bkg_gradfrom, $this->bkg_gradto, $this->bkg_gradtype);
2168
        } else {
2169 1
            $xl = 0;
2170 1
            $yt = 0;
2171 1
            $xr = $xl + $this->img->width - 1;
2172 1
            $yb = $yt + $this->img->height - 1;
2173 1
            if ($this->doshadow) {
2174
                $xr -= $this->shadow_width;
2175
                $yb -= $this->shadow_width;
2176
            }
2177 1
            if ($this->doframe) {
2178
                $yt += $this->frame_weight;
2179
                $yb -= $this->frame_weight;
2180
                $xl += $this->frame_weight;
2181
                $xr -= $this->frame_weight;
2182
            }
2183 1
            $aa = $this->img->SetAngle(0);
2184 1
            $grad->FilledRectangle($xl, $yt, $xr, $yb, $this->bkg_gradfrom, $this->bkg_gradto, $this->bkg_gradtype);
2185 1
            $aa = $this->img->SetAngle($aa);
0 ignored issues
show
Unused Code introduced by
The assignment to $aa is dead and can be removed.
Loading history...
2186
        }
2187 3
    }
2188
2189 5
    public function StrokeFrameBackground()
2190
    {
2191 5
        if ($this->background_image != '' && $this->background_cflag != '') {
2192
            Util\JpGraphError::RaiseL(25040); //('It is not possible to specify both a background image and a background country flag.');
2193
        }
2194 5
        if ($this->background_image != '') {
2195 4
            $bkgimg = $this->LoadBkgImage($this->background_image_format, $this->background_image);
2196 1
        } elseif ($this->background_cflag != '') {
2197 1
            $fobj                        = new Image\FlagImages(FLAGSIZE4);
2198 1
            $dummy                       = '';
2199 1
            $bkgimg                      = $fobj->GetImgByName($this->background_cflag, $dummy);
2200 1
            $this->background_image_mix  = $this->background_cflag_mix;
2201 1
            $this->background_image_type = $this->background_cflag_type;
2202
        } else {
2203
            return;
2204
        }
2205
2206 5
        $bw = imagesx($bkgimg);
2207 5
        $bh = imagesy($bkgimg);
2208
2209
        // No matter what the angle is we always stroke the image and frame
2210
        // assuming it is 0 degree
2211 5
        $aa = $this->img->SetAngle(0);
2212
2213 5
        switch ($this->background_image_type) {
2214 5
            case BGIMG_FILLPLOT: // Resize to just fill the plotarea
2215 3
                $this->FillMarginArea();
2216 3
                $this->StrokeFrame();
2217
                // Special case to hande 90 degree rotated graph corectly
2218 3
                if ($aa == 90) {
2219
                    $this->img->SetAngle(90);
2220
                    $this->FillPlotArea();
2221
                    $aa  = $this->img->SetAngle(0);
2222
                    $adj = ($this->img->height - $this->img->width) / 2;
2223
                    $this->img->CopyMerge(
2224
                        $bkgimg,
2225
                        $this->img->bottom_margin - $adj,
2226
                        $this->img->left_margin + $adj,
2227
                        0,
2228
                        0,
2229
                        $this->img->plotheight + 1,
2230
                        $this->img->plotwidth,
2231
                        $bw,
2232
                        $bh,
2233
                        $this->background_image_mix
2234
                    );
2235
                } else {
2236 3
                    $this->FillPlotArea();
2237 3
                    $this->img->CopyMerge(
2238 3
                        $bkgimg,
2239 3
                        $this->img->left_margin,
2240 3
                        $this->img->top_margin + 1,
2241 3
                        0,
2242 3
                        0,
2243 3
                        $this->img->plotwidth + 1,
2244 3
                        $this->img->plotheight,
2245 3
                        $bw,
2246 3
                        $bh,
2247 3
                        $this->background_image_mix
2248
                    );
2249
                }
2250
2251 3
                break;
2252 4
            case BGIMG_FILLFRAME: // Fill the whole area from upper left corner, resize to just fit
2253 3
                $hadj = 0;
2254 3
                $vadj = 0;
2255 3
                if ($this->doshadow) {
2256 2
                    $hadj = $this->shadow_width;
2257 2
                    $vadj = $this->shadow_width;
2258
                }
2259 3
                $this->FillMarginArea();
2260 3
                $this->FillPlotArea();
2261 3
                $this->img->CopyMerge(
2262 3
                    $bkgimg,
2263 3
                    0,
2264 3
                    0,
2265 3
                    0,
2266 3
                    0,
2267 3
                    $this->img->width - $hadj,
2268 3
                    $this->img->height - $vadj,
2269 3
                    $bw,
2270 3
                    $bh,
2271 3
                    $this->background_image_mix
2272
                );
2273 3
                $this->StrokeFrame();
2274
2275 3
                break;
2276 3
            case BGIMG_COPY: // Just copy the image from left corner, no resizing
2277 3
                $this->FillMarginArea();
2278 3
                $this->FillPlotArea();
2279 3
                $this->img->CopyMerge(
2280 3
                    $bkgimg,
2281 3
                    0,
2282 3
                    0,
2283 3
                    0,
2284 3
                    0,
2285 3
                    $bw,
2286 3
                    $bh,
2287 3
                    $bw,
2288 3
                    $bh,
2289 3
                    $this->background_image_mix
2290
                );
2291 3
                $this->StrokeFrame();
2292
2293 3
                break;
2294 1
            case BGIMG_CENTER: // Center original image in the plot area
2295 1
                $this->FillMarginArea();
2296 1
                $this->FillPlotArea();
2297 1
                $centerx = round($this->img->plotwidth / 2 + $this->img->left_margin - $bw / 2);
2298 1
                $centery = round($this->img->plotheight / 2 + $this->img->top_margin - $bh / 2);
2299 1
                $this->img->CopyMerge(
2300 1
                    $bkgimg,
2301 1
                    $centerx,
2302 1
                    $centery,
2303 1
                    0,
2304 1
                    0,
2305 1
                    $bw,
2306 1
                    $bh,
2307 1
                    $bw,
2308 1
                    $bh,
2309 1
                    $this->background_image_mix
2310
                );
2311 1
                $this->StrokeFrame();
2312
2313 1
                break;
2314 1
            case BGIMG_FREE: // Just copy the image to the specified location
2315 1
                $this->img->CopyMerge(
2316 1
                    $bkgimg,
2317 1
                    $this->background_image_xpos,
2318 1
                    $this->background_image_ypos,
2319 1
                    0,
2320 1
                    0,
2321 1
                    $bw,
2322 1
                    $bh,
2323 1
                    $bw,
2324 1
                    $bh,
2325 1
                    $this->background_image_mix
2326
                );
2327 1
                $this->StrokeFrame(); // New
2328 1
                break;
2329
            default:
2330
                Util\JpGraphError::RaiseL(25042); //(" Unknown background image layout");
2331
        }
2332 5
        $this->img->SetAngle($aa);
2333 5
    }
2334
2335
    // Private
2336
    // Draw a frame around the image
2337 21
    public function StrokeFrame()
2338
    {
2339 21
        if (!$this->doframe) {
2340 20
            return;
2341
        }
2342
2343 2
        if ($this->background_image_type <= 1 && ($this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle == BGRAD_PLOT))) {
2344 2
            $c = $this->margin_color;
2345
        } else {
2346
            $c = false;
2347
        }
2348
2349 2
        if ($this->doshadow) {
2350
            $this->img->SetColor($this->frame_color);
2351
            $this->img->ShadowRectangle(
2352
                0,
2353
                0,
2354
                $this->img->width,
2355
                $this->img->height,
2356
                $c,
2357
                $this->shadow_width,
2358
                $this->shadow_color
2359
            );
2360 2
        } elseif ($this->framebevel) {
2361
            if ($c) {
2362
                $this->img->SetColor($this->margin_color);
2363
                $this->img->FilledRectangle(0, 0, $this->img->width - 1, $this->img->height - 1);
2364
            }
2365
            $this->img->Bevel(
2366
                1,
2367
                1,
2368
                $this->img->width - 2,
2369
                $this->img->height - 2,
2370
                $this->framebeveldepth,
2371
                $this->framebevelcolor1,
2372
                $this->framebevelcolor2
2373
            );
2374
            if ($this->framebevelborder) {
2375
                $this->img->SetColor($this->framebevelbordercolor);
2376
                $this->img->Rectangle(0, 0, $this->img->width - 1, $this->img->height - 1);
2377
            }
2378
        } else {
2379 2
            $this->img->SetLineWeight($this->frame_weight);
2380 2
            if ($c) {
2381 2
                $this->img->SetColor($this->margin_color);
2382 2
                $this->img->FilledRectangle(0, 0, $this->img->width - 1, $this->img->height - 1);
2383
            }
2384 2
            $this->img->SetColor($this->frame_color);
2385 2
            $this->img->Rectangle(0, 0, $this->img->width - 1, $this->img->height - 1);
2386
        }
2387 2
    }
2388
2389 5
    public function FillMarginArea()
2390
    {
2391 5
        $hadj = 0;
2392 5
        $vadj = 0;
2393 5
        if ($this->doshadow) {
2394 3
            $hadj = $this->shadow_width;
2395 3
            $vadj = $this->shadow_width;
2396
        }
2397
2398 5
        $this->img->SetColor($this->margin_color);
2399 5
        $this->img->FilledRectangle(0, 0, $this->img->width - 1 - $hadj, $this->img->height - 1 - $vadj);
2400
2401 5
        $this->img->FilledRectangle(0, 0, $this->img->width - 1 - $hadj, $this->img->top_margin);
2402 5
        $this->img->FilledRectangle(0, $this->img->top_margin, $this->img->left_margin, $this->img->height - 1 - $hadj);
2403 5
        $this->img->FilledRectangle(
2404 5
            $this->img->left_margin + 1,
2405 5
            $this->img->height - $this->img->bottom_margin,
2406 5
            $this->img->width - 1 - $hadj,
2407 5
            $this->img->height - 1 - $hadj
2408
        );
2409 5
        $this->img->FilledRectangle(
2410 5
            $this->img->width - $this->img->right_margin,
2411 5
            $this->img->top_margin + 1,
2412 5
            $this->img->width - 1 - $hadj,
2413 5
            $this->img->height - $this->img->bottom_margin - 1
2414
        );
2415 5
    }
2416
2417 17
    public function FillPlotArea()
2418
    {
2419 17
        $this->img->PushColor($this->plotarea_color);
2420 17
        $this->img->FilledRectangle(
2421 17
            $this->img->left_margin,
2422 17
            $this->img->top_margin,
2423 17
            $this->img->width - $this->img->right_margin,
2424 17
            $this->img->height - $this->img->bottom_margin
2425
        );
2426 17
        $this->img->PopColor();
2427 17
    }
2428
2429
    // Stroke the plot area with either a solid color or a background image
2430 19
    public function StrokePlotArea()
2431
    {
2432
        // Note: To be consistent we really should take a possible shadow
2433
        // into account. However, that causes some problem for the LinearScale class
2434
        // since in the current design it does not have any links to class Graph which
2435
        // means it has no way of compensating for the adjusted plotarea in case of a
2436
        // shadow. So, until I redesign LinearScale we can't compensate for this.
2437
        // So just set the two adjustment parameters to zero for now.
2438 19
        $boxadj = 0; //$this->doframe ? $this->frame_weight : 0 ;
0 ignored issues
show
Unused Code introduced by
The assignment to $boxadj is dead and can be removed.
Loading history...
2439 19
        $adj    = 0; //$this->doshadow ? $this->shadow_width : 0 ;
0 ignored issues
show
Unused Code introduced by
The assignment to $adj is dead and can be removed.
Loading history...
2440
2441 19
        if ($this->background_image != '' || $this->background_cflag != '') {
2442 5
            $this->StrokeFrameBackground();
2443
        } else {
2444 15
            $aa = $this->img->SetAngle(0);
2445 15
            $this->StrokeFrame();
2446 15
            $aa = $this->img->SetAngle($aa);
0 ignored issues
show
Unused Code introduced by
The assignment to $aa is dead and can be removed.
Loading history...
2447 15
            $this->StrokeBackgroundGrad();
2448 15
            if ($this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle == BGRAD_MARGIN)) {
2449 13
                $this->FillPlotArea();
2450
            }
2451 15
            $this->StrokePlotGrad();
2452
        }
2453 19
    }
2454
2455 21
    public function StrokeIcons()
2456
    {
2457 21
        $n = safe_count($this->iIcons);
2458 21
        for ($i = 0; $i < $n; ++$i) {
2459
            $this->iIcons[$i]->StrokeWithScale($this->img, $this->xscale, $this->yscale);
2460
        }
2461 21
    }
2462
2463 19
    public function StrokePlotBox()
2464
    {
2465
        // Should we draw a box around the plot area?
2466 19
        if ($this->boxed) {
2467 19
            $this->img->SetLineWeight(1);
2468 19
            $this->img->SetLineStyle('solid');
2469 19
            $this->img->SetColor($this->box_color);
2470 19
            for ($i = 0; $i < $this->box_weight; ++$i) {
2471 19
                $this->img->Rectangle(
2472 19
                    $this->img->left_margin - $i,
2473 19
                    $this->img->top_margin - $i,
2474 19
                    $this->img->width - $this->img->right_margin + $i,
2475 19
                    $this->img->height - $this->img->bottom_margin + $i
2476
                );
2477
            }
2478
        }
2479 19
    }
2480
2481 1
    public function SetTitleBackgroundFillStyle($aStyle, $aColor1 = 'black', $aColor2 = 'white')
2482
    {
2483 1
        $this->titlebkg_fillstyle = $aStyle;
2484 1
        $this->titlebkg_scolor1   = $aColor1;
2485 1
        $this->titlebkg_scolor2   = $aColor2;
2486 1
    }
2487
2488 1
    public function SetTitleBackground($aBackColor = 'gray', $aStyle = TITLEBKG_STYLE1, $aFrameStyle = TITLEBKG_FRAME_NONE, $aFrameColor = 'black', $aFrameWeight = 1, $aBevelHeight = 3, $aEnable = true)
2489
    {
2490 1
        $this->titlebackground             = $aEnable;
2491 1
        $this->titlebackground_color       = $aBackColor;
2492 1
        $this->titlebackground_style       = $aStyle;
2493 1
        $this->titlebackground_framecolor  = $aFrameColor;
2494 1
        $this->titlebackground_framestyle  = $aFrameStyle;
2495 1
        $this->titlebackground_frameweight = $aFrameWeight;
2496 1
        $this->titlebackground_bevelheight = $aBevelHeight;
2497 1
    }
2498
2499 21
    public function StrokeTitles()
2500
    {
2501 21
        $margin = 3;
2502
2503 21
        if ($this->titlebackground) {
2504
            // Find out height
2505 1
            $this->title->margin += 2;
2506 1
            $h = $this->title->GetTextHeight($this->img) + $this->title->margin + $margin;
2507 1
            if ($this->subtitle->t != '' && !$this->subtitle->hide) {
2508
                $h += $this->subtitle->GetTextHeight($this->img) + $margin +
2509
                $this->subtitle->margin;
2510
                $h += 2;
2511
            }
2512 1
            if ($this->subsubtitle->t != '' && !$this->subsubtitle->hide) {
2513
                $h += $this->subsubtitle->GetTextHeight($this->img) + $margin +
2514
                $this->subsubtitle->margin;
2515
                $h += 2;
2516
            }
2517 1
            $this->img->PushColor($this->titlebackground_color);
2518 1
            if ($this->titlebackground_style === TITLEBKG_STYLE1) {
2519
                // Inside the frame
2520 1
                if ($this->framebevel) {
2521
                    $x1 = $y1 = $this->framebeveldepth + 1;
2522
                    $x2 = $this->img->width - $this->framebeveldepth - 2;
2523
                    $this->title->margin += $this->framebeveldepth + 1;
2524
                    $h += $y1;
2525
                    $h += 2;
2526
                } else {
2527 1
                    $x1 = $y1 = $this->frame_weight;
2528 1
                    $x2 = $this->img->width - $this->frame_weight - 1;
2529
                }
2530
            } elseif ($this->titlebackground_style === TITLEBKG_STYLE2) {
2531
                // Cover the frame as well
2532
                $x1 = $y1 = 0;
2533
                $x2 = $this->img->width - 1;
2534
            } elseif ($this->titlebackground_style === TITLEBKG_STYLE3) {
2535
                // Cover the frame as well (the difference is that
2536
                // for style==3 a bevel frame border is on top
2537
                // of the title background)
2538
                $x1 = $y1 = 0;
2539
                $x2 = $this->img->width - 1;
2540
                $h += $this->framebeveldepth;
2541
                $this->title->margin += $this->framebeveldepth;
2542
            } else {
2543
                Util\JpGraphError::RaiseL(25043); //('Unknown title background style.');
2544
            }
2545
2546 1
            if ($this->titlebackground_framestyle === 3) {
2547 1
                $h += $this->titlebackground_bevelheight * 2 + 1;
2548 1
                $this->title->margin += $this->titlebackground_bevelheight;
2549
            }
2550
2551 1
            if ($this->doshadow) {
2552
                $x2 -= $this->shadow_width;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $x2 does not seem to be defined for all execution paths leading up to this point.
Loading history...
2553
            }
2554
2555 1
            $indent = 0;
2556 1
            if ($this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL) {
2557 1
                $indent = $this->titlebackground_bevelheight;
2558
            }
2559
2560 1
            if ($this->titlebkg_fillstyle == TITLEBKG_FILLSTYLE_HSTRIPED) {
2561 1
                $this->img->FilledRectangle2(
2562 1
                    $x1 + $indent,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $x1 does not seem to be defined for all execution paths leading up to this point.
Loading history...
2563 1
                    $y1 + $indent,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $y1 does not seem to be defined for all execution paths leading up to this point.
Loading history...
2564 1
                    $x2 - $indent,
2565 1
                    $h - $indent,
2566 1
                    $this->titlebkg_scolor1,
2567 1
                    $this->titlebkg_scolor2
2568
                );
2569
            } elseif ($this->titlebkg_fillstyle == TITLEBKG_FILLSTYLE_VSTRIPED) {
2570
                $this->img->FilledRectangle2(
2571
                    $x1 + $indent,
2572
                    $y1 + $indent,
2573
                    $x2 - $indent,
2574
                    $h - $indent,
2575
                    $this->titlebkg_scolor1,
2576
                    $this->titlebkg_scolor2,
2577
                    2
2578
                );
2579
            } else {
2580
                // Solid fill
2581
                $this->img->FilledRectangle($x1, $y1, $x2, $h);
2582
            }
2583 1
            $this->img->PopColor();
2584
2585 1
            $this->img->PushColor($this->titlebackground_framecolor);
2586 1
            $this->img->SetLineWeight($this->titlebackground_frameweight);
2587 1
            if ($this->titlebackground_framestyle == TITLEBKG_FRAME_FULL) {
2588
                // Frame background
2589
                $this->img->Rectangle($x1, $y1, $x2, $h);
2590 1
            } elseif ($this->titlebackground_framestyle == TITLEBKG_FRAME_BOTTOM) {
2591
                // Bottom line only
2592
                $this->img->Line($x1, $h, $x2, $h);
2593 1
            } elseif ($this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL) {
2594 1
                $this->img->Bevel($x1, $y1, $x2, $h, $this->titlebackground_bevelheight);
2595
            }
2596 1
            $this->img->PopColor();
2597
2598
            // This is clumsy. But we neeed to stroke the whole graph frame if it is
2599
            // set to bevel to get the bevel shading on top of the text background
2600 1
            if ($this->framebevel && $this->doframe && $this->titlebackground_style === 3) {
2601
                $this->img->Bevel(
2602
                    1,
2603
                    1,
2604
                    $this->img->width - 2,
2605
                    $this->img->height - 2,
2606
                    $this->framebeveldepth,
2607
                    $this->framebevelcolor1,
2608
                    $this->framebevelcolor2
2609
                );
2610
                if ($this->framebevelborder) {
2611
                    $this->img->SetColor($this->framebevelbordercolor);
2612
                    $this->img->Rectangle(0, 0, $this->img->width - 1, $this->img->height - 1);
2613
                }
2614
            }
2615
        }
2616
2617
        // Stroke title
2618 21
        $y = $this->title->margin;
2619 21
        if ($this->title->halign == 'center') {
2620 21
            $this->title->Center(0, $this->img->width, $y);
2621
        } elseif ($this->title->halign == 'left') {
2622
            $this->title->SetPos($this->title->margin + 2, $y);
2623
        } elseif ($this->title->halign == 'right') {
2624
            $indent = 0;
2625
            if ($this->doshadow) {
2626
                $indent = $this->shadow_width + 2;
2627
            }
2628
            $this->title->SetPos($this->img->width - $this->title->margin - $indent, $y, 'right');
2629
        }
2630 21
        $this->title->Stroke($this->img);
2631
2632
        // ... and subtitle
2633 21
        $y += $this->title->GetTextHeight($this->img) + $margin + $this->subtitle->margin;
2634 21
        if ($this->subtitle->halign == 'center') {
2635 21
            $this->subtitle->Center(0, $this->img->width, $y);
2636
        } elseif ($this->subtitle->halign == 'left') {
2637
            $this->subtitle->SetPos($this->subtitle->margin + 2, $y);
2638
        } elseif ($this->subtitle->halign == 'right') {
2639
            $indent = 0;
2640
            if ($this->doshadow) {
2641
                $indent = $this->shadow_width + 2;
2642
            }
2643
2644
            $this->subtitle->SetPos($this->img->width - $this->subtitle->margin - $indent, $y, 'right');
2645
        }
2646 21
        $this->subtitle->Stroke($this->img);
2647
2648
        // ... and subsubtitle
2649 21
        $y += $this->subtitle->GetTextHeight($this->img) + $margin + $this->subsubtitle->margin;
2650 21
        if ($this->subsubtitle->halign == 'center') {
2651 21
            $this->subsubtitle->Center(0, $this->img->width, $y);
2652
        } elseif ($this->subsubtitle->halign == 'left') {
2653
            $this->subsubtitle->SetPos($this->subsubtitle->margin + 2, $y);
2654
        } elseif ($this->subsubtitle->halign == 'right') {
2655
            $indent = 0;
2656
            if ($this->doshadow) {
2657
                $indent = $this->shadow_width + 2;
2658
            }
2659
2660
            $this->subsubtitle->SetPos($this->img->width - $this->subsubtitle->margin - $indent, $y, 'right');
2661
        }
2662 21
        $this->subsubtitle->Stroke($this->img);
2663
2664
        // ... and fancy title
2665 21
        $this->tabtitle->Stroke($this->img);
2666 21
    }
2667
2668 19
    public function StrokeTexts()
2669
    {
2670
        // Stroke any user added text objects
2671 19
        if ($this->texts != null) {
2672 1
            for ($i = 0; $i < safe_count($this->texts); ++$i) {
2673 1
                $this->texts[$i]->StrokeWithScale($this->img, $this->xscale, $this->yscale);
2674
            }
2675
        }
2676
2677 19
        if ($this->y2texts != null && $this->y2scale != null) {
2678
            for ($i = 0; $i < safe_count($this->y2texts); ++$i) {
2679
                $this->y2texts[$i]->StrokeWithScale($this->img, $this->xscale, $this->y2scale);
2680
            }
2681
        }
2682 19
    }
2683
2684 19
    public function StrokeTables()
2685
    {
2686 19
        if ($this->iTables != null) {
2687
            $n = safe_count($this->iTables);
2688
            for ($i = 0; $i < $n; ++$i) {
2689
                $this->iTables[$i]->StrokeWithScale($this->img, $this->xscale, $this->yscale);
2690
            }
2691
        }
2692 19
    }
2693
2694
    public function DisplayClientSideaImageMapAreas()
2695
    {
2696
        // Debug stuff - display the outline of the image map areas
2697
        $csim = '';
2698
        foreach ($this->plots as $p) {
2699
            $csim .= $p->GetCSIMareas();
2700
        }
2701
        $csim .= $this->legend->GetCSIMareas();
2702
        if (preg_match_all('/area shape="(\\w+)" coords="([0-9\\, ]+)"/', $csim, $coords)) {
2703
            $this->img->SetColor($this->csimcolor);
2704
            $n = safe_count($coords[0]);
2705
            for ($i = 0; $i < $n; ++$i) {
2706
                if ($coords[1][$i] == 'poly') {
2707
                    preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/', $coords[2][$i], $pts);
2708
                    $this->img->SetStartPoint($pts[1][count($pts[0]) - 1], $pts[2][count($pts[0]) - 1]);
2709
                    $m = safe_count($pts[0]);
2710
                    for ($j = 0; $j < $m; ++$j) {
2711
                        $this->img->LineTo($pts[1][$j], $pts[2][$j]);
2712
                    }
2713
                } elseif ($coords[1][$i] == 'rect') {
2714
                    $pts = preg_split('/,/', $coords[2][$i]);
2715
                    $this->img->SetStartPoint($pts[0], $pts[1]);
2716
                    $this->img->LineTo($pts[2], $pts[1]);
2717
                    $this->img->LineTo($pts[2], $pts[3]);
2718
                    $this->img->LineTo($pts[0], $pts[3]);
2719
                    $this->img->LineTo($pts[0], $pts[1]);
2720
                }
2721
            }
2722
        }
2723
    }
2724
2725
    // Text scale offset in world coordinates
2726 18
    public function SetTextScaleOff($aOff)
2727
    {
2728 18
        $this->text_scale_off         = $aOff;
2729 18
        $this->xscale->text_scale_off = $aOff;
2730 18
    }
2731
2732
    // Text width of bar to be centered in absolute pixels
2733 1
    public function SetTextScaleAbsCenterOff($aOff)
2734
    {
2735 1
        $this->text_scale_abscenteroff = $aOff;
2736 1
    }
2737
2738
    // Get Y min and max values for added lines
2739 17
    public function GetLinesYMinMax($aLines)
2740
    {
2741 17
        if (is_null($aLines)) {
2742 17
            return false;
2743
        }
2744
2745
        $n = safe_count($aLines);
2746
        if ($n == 0) {
2747
            return false;
2748
        }
2749
2750
        $min = $aLines[0]->scaleposition;
2751
        $max = $min;
2752
        $flg = false;
2753
        for ($i = 0; $i < $n; ++$i) {
2754
            if ($aLines[$i]->direction == HORIZONTAL) {
2755
                $flg = true;
2756
                $v   = $aLines[$i]->scaleposition;
2757
                if ($min > $v) {
2758
                    $min = $v;
2759
                }
2760
2761
                if ($max < $v) {
2762
                    $max = $v;
2763
                }
2764
            }
2765
        }
2766
2767
        return $flg ? [$min, $max] : false;
0 ignored issues
show
introduced by
The condition $flg is always false.
Loading history...
2768
    }
2769
2770
    // Get X min and max values for added lines
2771 7
    public function GetLinesXMinMax($aLines)
2772
    {
2773 7
        $n = safe_count($aLines);
2774 7
        if ($n == 0) {
2775 7
            return false;
2776
        }
2777
2778
        $min = $aLines[0]->scaleposition;
2779
        $max = $min;
2780
        $flg = false;
2781
        for ($i = 0; $i < $n; ++$i) {
2782
            if ($aLines[$i]->direction == VERTICAL) {
2783
                $flg = true;
2784
                $v   = $aLines[$i]->scaleposition;
2785
                if ($min > $v) {
2786
                    $min = $v;
2787
                }
2788
2789
                if ($max < $v) {
2790
                    $max = $v;
2791
                }
2792
            }
2793
        }
2794
2795
        return $flg ? [$min, $max] : false;
0 ignored issues
show
introduced by
The condition $flg is always false.
Loading history...
2796
    }
2797
2798
    // Get min and max values for all included plots
2799 17
    public function GetPlotsYMinMax($bPlots)
2800
    {
2801
        $aPlots = array_filter($bPlots, function ($plot) {
2802
            //\Kint::dump($plot, $plot instanceof Plot\Plot);
2803 17
            return $plot instanceof Plot\Plot;
2804 17
        });
2805 17
        reset($aPlots);
2806 17
        $n = safe_count($aPlots);
2807 17
        $i = 0;
2808
        //\Kint::dump($n, $aPlots);
2809
        do {
2810
            //\Kint::dump($i, $aPlots[$i]);
2811 17
            list($xmax, $max) = isset($aPlots[$i]) ? $aPlots[$i]->Max() : [null, null];
2812 17
        } while (++$i < $n && !is_numeric($max));
2813
2814 17
        $i = 0;
2815
        do {
2816 17
            list($xmin, $min) = isset($aPlots[$i]) ? $aPlots[$i]->Min() : [null, null];
2817 17
        } while (++$i < $n && !is_numeric($min));
2818
2819 17
        if (!is_numeric($min) || !is_numeric($max)) {
2820
            Util\JpGraphError::RaiseL(25044); //('Cannot use autoscaling since it is impossible to determine a valid min/max value  of the Y-axis (only null values).');
2821
        }
2822
2823 17
        for ($i = 0; $i < $n; ++$i) {
2824 17
            list($xmax, $ymax) = isset($aPlots[$i]) ? $aPlots[$i]->Max() : [null, null];
2825 17
            list($xmin, $ymin) = isset($aPlots[$i]) ? $aPlots[$i]->Min() : [null, null];
2826 17
            if (is_numeric($ymax)) {
2827 17
                $max = max($max, $ymax);
2828
            }
2829
2830 17
            if (is_numeric($ymin)) {
2831 17
                $min = min($min, $ymin);
2832
            }
2833
        }
2834 17
        if ($min == '') {
2835 3
            $min = 0;
2836
        }
2837
2838 17
        if ($max == '') {
2839
            $max = 0;
2840
        }
2841
2842 17
        if ($min == 0 && $max == 0) {
2843
            // Special case if all values are 0
2844
            $min = 0;
2845
            $max = 1;
2846
        }
2847
2848 17
        return [$min, $max];
2849
    }
2850
2851
    public function hasLinePlotAndBarPlot()
2852
    {
2853
        $has_line = false;
2854
        $has_bar  = false;
2855
2856
        foreach ($this->plots as $plot) {
2857
            if ($plot instanceof Plot\LinePlot) {
2858
                $has_line = true;
2859
            }
2860
            if ($plot instanceof Plot\BarPlot) {
2861
                $has_bar = true;
2862
            }
2863
        }
2864
2865
        if ($has_line && $has_bar) {
2866
            return true;
2867
        }
2868
2869
        return false;
2870
    }
2871
2872 1
    public function SetTheme($graph_theme)
2873
    {
2874 1
        if (!($this instanceof PieGraph)) {
2875 1
            if (!$this->isAfterSetScale) {
2876
                Util\JpGraphError::RaiseL(25133); //('Use Graph::SetTheme() after Graph::SetScale().');
2877
            }
2878
        }
2879
2880 1
        if ($this->graph_theme) {
2881 1
            $this->ClearTheme();
2882
        }
2883 1
        $this->graph_theme = $graph_theme;
2884 1
        $this->graph_theme->ApplyGraph($this);
2885 1
    }
2886
2887 2
    public function ClearTheme()
2888
    {
2889 2
        $this->graph_theme = null;
2890
2891 2
        $this->isRunningClear = true;
2892
2893 2
        $this->__construct(
2894 2
            $this->inputValues['aWidth'],
2895 2
            $this->inputValues['aHeight'],
2896 2
            $this->inputValues['aCachedName'],
2897 2
            $this->inputValues['aTimeout'],
2898 2
            $this->inputValues['aInline']
2899
        );
2900
2901 2
        if (!($this instanceof PieGraph)) {
2902 2
            if ($this->isAfterSetScale) {
2903 1
                $this->SetScale(
2904 1
                    $this->inputValues['aAxisType'],
2905 1
                    $this->inputValues['aYMin'],
2906 1
                    $this->inputValues['aYMax'],
2907 1
                    $this->inputValues['aXMin'],
2908 1
                    $this->inputValues['aXMax']
2909
                );
2910
            }
2911
        }
2912
2913 2
        $this->isRunningClear = false;
2914 2
    }
2915
2916
    public function SetSupersampling($do = false, $scale = 2)
2917
    {
2918
        if ($do) {
2919
            define('SUPERSAMPLING_SCALE', $scale);
2920
        // $this->img->scale = $scale;
2921
        } else {
2922
            define('SUPERSAMPLING_SCALE', 1);
2923
            //$this->img->scale = 0;
2924
        }
2925
    }
2926
} // @class
2927