Issues (459)

src/graph/MGraph.php (7 issues)

1
<?php
2
3
/**
4
 * JPGraph v4.0.3
5
 */
6
7
namespace Amenadiel\JpGraph\Graph;
8
9
use Amenadiel\JpGraph\Image;
10
use Amenadiel\JpGraph\Text;
11
use Amenadiel\JpGraph\Util;
12
13
/**
14
 * File:        JPGRAPH_MGRAPH.PHP
15
 * // Description: Class to handle multiple graphs in the same image
16
 * // Created:     2006-01-15
17
 * // Ver:         $Id: jpgraph_mgraph.php 1770 2009-08-17 06:10:22Z ljp $
18
 * //
19
 * // Copyright (c) Asial Corporation. All rights reserved.
20
 */
21
22
/**
23
 * @class MGraph
24
 * // Description: Create a container image that can hold several graph
25
 */
26
class MGraph
27
{
28
    public $title;
29
    public $subtitle;
30
    public $subsubtitle;
31
32
    protected $img;
33
    protected $iCnt          = 0;
34
    protected $iGraphs       = []; // image_handle, x, y, fx, fy, sizex, sizey
35
    protected $iFillColor    = 'white';
36
    protected $iCurrentColor = 0;
37
    protected $lm            = 4;
38
    protected $rm            = 4;
39
    protected $tm            = 4;
40
    protected $bm            = 4;
41
    protected $iDoFrame      = false;
42
    protected $iFrameColor   = 'black';
43
    protected $iFrameWeight  = 1;
44
    protected $iLineWeight   = 1;
45
    protected $expired       = false;
46
    protected $cache;
47
    protected $cache_name    = '';
48
    protected $inline        = true;
49
    protected $image_format  = 'png';
50
    protected $image_quality = 75;
51
    protected $iWidth;
52
    protected $iHeight;
53
    protected $background_image        = '';
54
    protected $background_image_center = true;
55
    protected $backround_image_format  = '';
56
    protected $background_image_mix    = 100;
57
    protected $background_image_y;
58
    protected $background_image_x;
59
    private $doshadow     = false;
60
    private $shadow_width = 4;
61
    private $shadow_color = '[email protected]';
62
    public $footer;
63
64
    // Create a new instane of the combined graph
65
    public function __construct($aWidth = null, $aHeight = null, $aCachedName = '', $aTimeOut = 0, $aInline = true)
66
    {
67
        $this->iWidth  = $aWidth;
68
        $this->iHeight = $aHeight;
69
70
        // If the cached version exist just read it directly from the
71
        // cache, stream it back to browser and exit
72
        if ($aCachedName != '' && READ_CACHE && $aInline) {
73
            $this->cache = new Image\ImgStreamCache();
74
            $this->cache->SetTimeOut($aTimeOut);
75
            $image = new Image\Image();
76
            if ($this->cache->GetAndStream($image, $aCachedName)) {
77
                exit();
0 ignored issues
show
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...
78
            }
79
        }
80
        $this->inline     = $aInline;
81
        $this->cache_name = $aCachedName;
82
83
        $this->title = new Text\Text();
84
        $this->title->ParagraphAlign('center');
85
        $this->title->SetFont(FF_FONT2, FS_BOLD);
86
        $this->title->SetMargin(3);
87
        $this->title->SetAlign('center');
88
89
        $this->subtitle = new Text\Text();
90
        $this->subtitle->ParagraphAlign('center');
91
        $this->subtitle->SetFont(FF_FONT1, FS_BOLD);
92
        $this->subtitle->SetMargin(3);
93
        $this->subtitle->SetAlign('center');
94
95
        $this->subsubtitle = new Text\Text();
96
        $this->subsubtitle->ParagraphAlign('center');
97
        $this->subsubtitle->SetFont(FF_FONT1, FS_NORMAL);
98
        $this->subsubtitle->SetMargin(3);
99
        $this->subsubtitle->SetAlign('center');
100
101
        $this->footer = new Image\Footer();
102
    }
103
104
    // Specify background fill color for the combined graph
105
    public function SetFillColor($aColor)
106
    {
107
        $this->iFillColor = $aColor;
108
    }
109
110
    // Add a frame around the combined graph
111
    public function SetFrame($aFlg, $aColor = 'black', $aWeight = 1)
112
    {
113
        $this->iDoFrame     = $aFlg;
114
        $this->iFrameColor  = $aColor;
115
        $this->iFrameWeight = $aWeight;
116
    }
117
118
    // Specify a background image blend
119
    public function SetBackgroundImageMix($aMix)
120
    {
121
        $this->background_image_mix = $aMix;
122
    }
123
124
    // Specify a background image
125
    public function SetBackgroundImage($aFileName, $aCenter_aX = null, $aY = null)
126
    {
127
        // Second argument can be either a boolean value or
128
        // a numeric
129
        $aCenter = true;
130
        $aX      = null;
131
132
        if (is_numeric($aCenter_aX)) {
133
            $aX = $aCenter_aX;
134
        }
135
136
        // Get extension to determine image type
137
        $e = explode('.', $aFileName);
138
        if (!$e) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $e of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
139
            Util\JpGraphError::RaiseL(12002, $aFileName);
140
            //('Incorrect file name for MGraph::SetBackgroundImage() : '.$aFileName.' Must have a valid image extension (jpg,gif,png) when using autodetection of image type');
141
        }
142
143
        $valid_formats = ['png', 'jpg', 'gif'];
144
        $aImgFormat    = strtolower($e[count($e) - 1]);
145
        if ($aImgFormat == 'jpeg') {
146
            $aImgFormat = 'jpg';
147
        } elseif (!in_array($aImgFormat, $valid_formats, true)) {
148
            Util\JpGraphError::RaiseL(12003, $aImgFormat, $aFileName);
149
            //('Unknown file extension ($aImgFormat) in MGraph::SetBackgroundImage() for filename: '.$aFileName);
150
        }
151
152
        $this->background_image        = $aFileName;
153
        $this->background_image_center = $aCenter;
154
        $this->background_image_format = $aImgFormat;
155
        $this->background_image_x      = $aX;
156
        $this->background_image_y      = $aY;
157
    }
158
159
    public function _strokeBackgroundImage()
160
    {
161
        if ($this->background_image == '') {
162
            return;
163
        }
164
165
        $bkgimg = Graph::LoadBkgImage('', $this->background_image);
166
167
        // Background width & Heoght
168
        $bw = imagesx($bkgimg);
169
        $bh = imagesy($bkgimg);
170
171
        // Canvas width and height
172
        $cw = imagesx($this->img);
173
        $ch = imagesy($this->img);
174
175
        if ($this->doshadow) {
176
            $cw -= $this->shadow_width;
177
            $ch -= $this->shadow_width;
178
        }
179
180
        if ($this->background_image_x === null || $this->background_image_y === null) {
181
            if ($this->background_image_center) {
182
                // Center original image in the plot area
183
                $x = round($cw / 2 - $bw / 2);
184
                $y = round($ch / 2 - $bh / 2);
185
            } else {
186
                // Just copy the image from left corner, no resizing
187
                $x = 0;
188
                $y = 0;
189
            }
190
        } else {
191
            $x = $this->background_image_x;
192
            $y = $this->background_image_y;
193
        }
194
        imagecopymerge($this->img, $bkgimg, $x, $y, 0, 0, $bw, $bh, $this->background_image_mix);
195
    }
196
197
    public function AddMix($aGraph, $x = 0, $y = 0, $mix = 100, $fx = 0, $fy = 0, $w = 0, $h = 0)
0 ignored issues
show
The parameter $fy 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

197
    public function AddMix($aGraph, $x = 0, $y = 0, $mix = 100, $fx = 0, /** @scrutinizer ignore-unused */ $fy = 0, $w = 0, $h = 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...
The parameter $fx 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

197
    public function AddMix($aGraph, $x = 0, $y = 0, $mix = 100, /** @scrutinizer ignore-unused */ $fx = 0, $fy = 0, $w = 0, $h = 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...
198
    {
199
        $this->_gdImgHandle($aGraph->Stroke(_IMG_HANDLER), $x, $y, $fx = 0, $fy = 0, $w, $h, $mix);
200
    }
201
202
    public function Add($aGraph, $x = 0, $y = 0, $fx = 0, $fy = 0, $w = 0, $h = 0)
0 ignored issues
show
The parameter $fx 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

202
    public function Add($aGraph, $x = 0, $y = 0, /** @scrutinizer ignore-unused */ $fx = 0, $fy = 0, $w = 0, $h = 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...
The parameter $fy 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

202
    public function Add($aGraph, $x = 0, $y = 0, $fx = 0, /** @scrutinizer ignore-unused */ $fy = 0, $w = 0, $h = 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...
203
    {
204
        $this->_gdImgHandle($aGraph->Stroke(_IMG_HANDLER), $x, $y, $fx = 0, $fy = 0, $w, $h);
205
    }
206
207
    public function _gdImgHandle($agdCanvas, $x, $y, $fx = 0, $fy = 0, $w = 0, $h = 0, $mix = 100)
208
    {
209
        if ($w == 0) {
210
            $w = @imagesx($agdCanvas);
211
        }
212
        if ($w === null) {
213
            Util\JpGraphError::RaiseL(12007);
214
            //('Argument to MGraph::Add() is not a valid GD image handle.');
215
            return;
216
        }
217
        if ($h == 0) {
218
            $h = @imagesy($agdCanvas);
219
        }
220
        $this->iGraphs[$this->iCnt++] = [$agdCanvas, $x, $y, $fx, $fy, $w, $h, $mix];
221
    }
222
223
    public function SetMargin($lm, $rm, $tm, $bm)
224
    {
225
        $this->lm = $lm;
226
        $this->rm = $rm;
227
        $this->tm = $tm;
228
        $this->bm = $bm;
229
    }
230
231
    public function SetExpired($aFlg = true)
232
    {
233
        $this->expired = $aFlg;
234
    }
235
236
    public function SetImgFormat($aFormat, $aQuality = 75)
237
    {
238
        $this->image_format  = $aFormat;
239
        $this->image_quality = $aQuality;
240
    }
241
242
    // Set the shadow around the whole image
243
    public function SetShadow($aShowShadow = true, $aShadowWidth = 4, $aShadowColor = '[email protected]')
244
    {
245
        $this->doshadow     = $aShowShadow;
246
        $this->shadow_color = $aShadowColor;
247
        $this->shadow_width = $aShadowWidth;
248
        $this->footer->iBottomMargin += $aShadowWidth;
249
        $this->footer->iRightMargin += $aShadowWidth;
250
    }
251
252
    public function StrokeTitle($image, $w, $h)
0 ignored issues
show
The parameter $h 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

252
    public function StrokeTitle($image, $w, /** @scrutinizer ignore-unused */ $h)

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...
253
    {
254
        // Stroke title
255
        if ($this->title->t !== '') {
256
            $margin = 3;
257
258
            $y = $this->title->margin;
259
            if ($this->title->halign == 'center') {
260
                $this->title->Center(0, $w, $y);
261
            } elseif ($this->title->halign == 'left') {
262
                $this->title->SetPos($this->title->margin + 2, $y);
263
            } elseif ($this->title->halign == 'right') {
264
                $indent = 0;
265
                if ($this->doshadow) {
266
                    $indent = $this->shadow_width + 2;
267
                }
268
                $this->title->SetPos($w - $this->title->margin - $indent, $y, 'right');
269
            }
270
            $this->title->Stroke($image);
271
272
            // ... and subtitle
273
            $y += $this->title->GetTextHeight($image) + $margin + $this->subtitle->margin;
274
            if ($this->subtitle->halign == 'center') {
275
                $this->subtitle->Center(0, $w, $y);
276
            } elseif ($this->subtitle->halign == 'left') {
277
                $this->subtitle->SetPos($this->subtitle->margin + 2, $y);
278
            } elseif ($this->subtitle->halign == 'right') {
279
                $indent = 0;
280
                if ($this->doshadow) {
281
                    $indent = $this->shadow_width + 2;
282
                }
283
                $this->subtitle->SetPos($this->img->width - $this->subtitle->margin - $indent, $y, 'right');
284
            }
285
            $this->subtitle->Stroke($image);
286
287
            // ... and subsubtitle
288
            $y += $this->subtitle->GetTextHeight($image) + $margin + $this->subsubtitle->margin;
289
            if ($this->subsubtitle->halign == 'center') {
290
                $this->subsubtitle->Center(0, $w, $y);
291
            } elseif ($this->subsubtitle->halign == 'left') {
292
                $this->subsubtitle->SetPos($this->subsubtitle->margin + 2, $y);
293
            } elseif ($this->subsubtitle->halign == 'right') {
294
                $indent = 0;
295
                if ($this->doshadow) {
296
                    $indent = $this->shadow_width + 2;
297
                }
298
                $this->subsubtitle->SetPos($w - $this->subsubtitle->margin - $indent, $y, 'right');
299
            }
300
            $this->subsubtitle->Stroke($image);
301
        }
302
    }
303
304
    public function Stroke($aFileName = '')
305
    {
306
        // Find out the necessary size for the container image
307
        $w = 0;
308
        $h = 0;
309
        for ($i = 0; $i < $this->iCnt; ++$i) {
310
            $maxw = $this->iGraphs[$i][1] + $this->iGraphs[$i][5];
311
            $maxh = $this->iGraphs[$i][2] + $this->iGraphs[$i][6];
312
            $w    = max($w, $maxw);
313
            $h    = max($h, $maxh);
314
        }
315
        $w += $this->lm + $this->rm;
316
        $h += $this->tm + $this->bm;
317
318
        // User specified width,height overrides
319
        if ($this->iWidth !== null && $this->iWidth !== 0) {
320
            $w = $this->iWidth;
321
        }
322
323
        if ($this->iHeight !== null && $this->iHeight !== 0) {
324
            $h = $this->iHeight;
325
        }
326
327
        if ($this->doshadow) {
328
            $w += $this->shadow_width;
329
            $h += $this->shadow_width;
330
        }
331
332
        $image = new Image\Image($w, $h);
333
        $image->SetImgFormat($this->image_format, $this->image_quality);
334
335
        if ($this->doshadow) {
336
            $image->SetColor($this->iFrameColor);
337
            $image->ShadowRectangle(0, 0, $w - 1, $h - 1, $this->iFillColor, $this->shadow_width, $this->shadow_color);
338
            $w -= $this->shadow_width;
339
            $h -= $this->shadow_width;
340
        } else {
341
            $image->SetColor($this->iFillColor);
342
            $image->FilledRectangle(0, 0, $w - 1, $h - 1);
343
        }
344
        $image->SetExpired($this->expired);
345
346
        $this->img = $image->img;
347
        $this->_strokeBackgroundImage();
348
349
        if ($this->iDoFrame && !$this->doshadow) {
350
            $image->SetColor($this->iFrameColor);
351
            $image->SetLineWeight($this->iFrameWeight);
352
            $image->Rectangle(0, 0, $w - 1, $h - 1);
353
        }
354
355
        // Copy all sub graphs to the container
356
        for ($i = 0; $i < $this->iCnt; ++$i) {
357
            $image->CopyMerge(
358
                $this->iGraphs[$i][0],
359
                $this->iGraphs[$i][1] + $this->lm,
360
                $this->iGraphs[$i][2] + $this->tm,
361
                $this->iGraphs[$i][3],
362
                $this->iGraphs[$i][4],
363
                $this->iGraphs[$i][5],
364
                $this->iGraphs[$i][6],
365
                -1,
366
                -1, /* Full from width and height */
367
                $this->iGraphs[$i][7]
368
            );
369
        }
370
371
        $this->StrokeTitle($image, $w, $h);
372
        $this->footer->Stroke($image);
373
374
        // Output image
375
        if ($aFileName == _IMG_HANDLER) {
376
            return $image->img;
377
        }
378
        //Finally stream the generated picture
379
        $this->cache = new Image\ImgStreamCache();
380
        $this->cache->PutAndStream($image, $this->cache_name, $this->inline, $aFileName);
381
    }
382
}
383
384
// EOF
385