Gradient::GetColArray()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 33
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 4.0011

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 24
c 1
b 0
f 0
nc 4
nop 5
dl 0
loc 33
ccs 23
cts 24
cp 0.9583
crap 4.0011
rs 9.536
1
<?php
2
3
/**
4
 * JPGraph v4.0.3
5
 */
6
7
namespace Amenadiel\JpGraph\Plot;
8
9
/*
10
 * File:        JPGRAPH_GRADIENT.PHP
11
 * // Description: Create a color gradient
12
 * // Created:     2003-02-01
13
 * // Ver:         $Id: jpgraph_gradient.php 1761 2009-08-01 08:31:28Z ljp $
14
 * //
15
 * // Copyright (c) Asial Corporation. All rights reserved.
16
 */
17
use Amenadiel\JpGraph\Util;
18
19
/**
20
 * @class Gradient
21
 * // Description: Handles gradient fills. This is to be
22
 * // considered a "friend" class of Class Image.
23
 */
24
class Gradient
25
{
26
    private $img;
27
    private $numcolors = 100;
28
29
    /**
30
     * CONSTRUCTOR.
31
     *
32
     * @param mixed $img
33
     */
34 15
    public function __construct(&$img)
35
    {
36 15
        $this->img = $img;
37 15
    }
38
39
    public function SetNumColors($aNum)
40
    {
41
        $this->numcolors = $aNum;
42
    }
43
44
    /**
45
     * PUBLIC METHODS.
46
     *
47
     * @param mixed $xl
48
     * @param mixed $yt
49
     * @param mixed $xr
50
     * @param mixed $yb
51
     * @param mixed $from_color
52
     * @param mixed $to_color
53
     * @param mixed $style
54
     */
55
    // Produce a gradient filled rectangle with a smooth transition between
56
    // two colors.
57
    // ($xl,$yt)  Top left corner
58
    // ($xr,$yb) Bottom right
59
    // $from_color Starting color in gradient
60
    // $to_color End color in the gradient
61
    // $style  Which way is the gradient oriented?
62 3
    public function FilledRectangle($xl, $yt, $xr, $yb, $from_color, $to_color, $style = 1)
63
    {
64 3
        $this->img->SetLineWeight(1);
65
        switch ($style) {
66 3
            case GRAD_VER:
67
                $steps = ceil(abs($xr - $xl) + 1);
68
                $delta = $xr >= $xl ? 1 : -1;
69
                $this->GetColArray($from_color, $to_color, $steps, $colors, $this->numcolors);
70
                for ($i = 0, $x = $xl; $i < $steps; ++$i) {
71
                    $this->img->current_color = $colors[$i];
72
                    $this->img->Line($x, $yt, $x, $yb);
73
                    $x += $delta;
74
                }
75
76
                break;
77 3
            case GRAD_HOR:
78 3
                $steps = ceil(abs($yb - $yt) + 1);
79 3
                $delta = $yb >= $yt ? 1 : -1;
80 3
                $this->GetColArray($from_color, $to_color, $steps, $colors, $this->numcolors);
81 3
                for ($i = 0, $y = $yt; $i < $steps; ++$i) {
82 3
                    $this->img->current_color = $colors[$i];
83 3
                    $this->img->Line($xl, $y, $xr, $y);
84 3
                    $y += $delta;
85
                }
86
87 3
                break;
88
            case GRAD_MIDHOR:
89
                $steps = ceil(abs($yb - $yt) / 2);
90
                $delta = $yb >= $yt ? 1 : -1;
91
                $this->GetColArray($from_color, $to_color, $steps, $colors, $this->numcolors);
92
                for ($y = $yt, $i = 0; $i < $steps; ++$i) {
93
                    $this->img->current_color = $colors[$i];
94
                    $this->img->Line($xl, $y, $xr, $y);
95
                    $y += $delta;
96
                }
97
                --$i;
98
                if (abs($yb - $yt) % 2 == 1) {
99
                    --$steps;
100
                }
101
                for ($j = 0; $j < $steps; ++$j, --$i) {
102
                    $this->img->current_color = $colors[$i];
103
                    $this->img->Line($xl, $y, $xr, $y);
104
                    $y += $delta;
105
                }
106
                $this->img->Line($xl, $y, $xr, $y);
107
108
                break;
109
            case GRAD_MIDVER:
110
                $steps = ceil(abs($xr - $xl) / 2);
111
                $delta = $xr >= $xl ? 1 : -1;
112
                $this->GetColArray($from_color, $to_color, $steps, $colors, $this->numcolors);
113
                for ($x = $xl, $i = 0; $i < $steps; ++$i) {
114
                    $this->img->current_color = $colors[$i];
115
                    $this->img->Line($x, $yb, $x, $yt);
116
                    $x += $delta;
117
                }
118
                --$i;
119
                if (abs($xr - $xl) % 2 == 1) {
120
                    --$steps;
121
                }
122
                for ($j = 0; $j < $steps; ++$j, --$i) {
123
                    $this->img->current_color = $colors[$i];
124
                    $this->img->Line($x, $yb, $x, $yt);
125
                    $x += $delta;
126
                }
127
                $this->img->Line($x, $yb, $x, $yt);
128
129
                break;
130
            case GRAD_WIDE_MIDVER:
131
                $diff      = ceil(abs($xr - $xl));
132
                $steps     = floor(abs($diff) / 3);
133
                $firststep = $diff - 2 * $steps;
134
                $delta     = $xr >= $xl ? 1 : -1;
135
                $this->GetColArray($from_color, $to_color, $firststep, $colors, $this->numcolors);
136
                for ($x = $xl, $i = 0; $i < $firststep; ++$i) {
137
                    $this->img->current_color = $colors[$i];
138
                    $this->img->Line($x, $yb, $x, $yt);
139
                    $x += $delta;
140
                }
141
                --$i;
142
                $this->img->current_color = $colors[$i];
143
                for ($j = 0; $j < $steps; ++$j) {
144
                    $this->img->Line($x, $yb, $x, $yt);
145
                    $x += $delta;
146
                }
147
148
                for ($j = 0; $j < $steps; ++$j, --$i) {
149
                    $this->img->current_color = $colors[$i];
150
                    $this->img->Line($x, $yb, $x, $yt);
151
                    $x += $delta;
152
                }
153
154
                break;
155
            case GRAD_WIDE_MIDHOR:
156
                $diff      = ceil(abs($yb - $yt));
157
                $steps     = floor(abs($diff) / 3);
158
                $firststep = $diff - 2 * $steps;
159
                $delta     = $yb >= $yt ? 1 : -1;
160
                $this->GetColArray($from_color, $to_color, $firststep, $colors, $this->numcolors);
161
                for ($y = $yt, $i = 0; $i < $firststep; ++$i) {
162
                    $this->img->current_color = $colors[$i];
163
                    $this->img->Line($xl, $y, $xr, $y);
164
                    $y += $delta;
165
                }
166
                --$i;
167
                $this->img->current_color = $colors[$i];
168
                for ($j = 0; $j < $steps; ++$j) {
169
                    $this->img->Line($xl, $y, $xr, $y);
170
                    $y += $delta;
171
                }
172
                for ($j = 0; $j < $steps; ++$j, --$i) {
173
                    $this->img->current_color = $colors[$i];
174
                    $this->img->Line($xl, $y, $xr, $y);
175
                    $y += $delta;
176
                }
177
178
                break;
179
            case GRAD_LEFT_REFLECTION:
180
                $steps1 = ceil(0.3 * abs($xr - $xl));
181
                $delta  = $xr >= $xl ? 1 : -1;
182
183
                $from_color  = $this->img->rgb->Color($from_color);
184
                $adj         = 1.4;
185
                $m           = ($adj - 1.0) * (255 - min(255, min($from_color[0], min($from_color[1], $from_color[2]))));
186
                $from_color2 = [min(255, $from_color[0] + $m),
187
                    min(255, $from_color[1] + $m), min(255, $from_color[2] + $m), ];
188
189
                $this->GetColArray($from_color2, $to_color, $steps1, $colors, $this->numcolors);
190
                $n = safe_count($colors);
191
                for ($x = $xl, $i = 0; $i < $steps1 && $i < $n; ++$i) {
192
                    $this->img->current_color = $colors[$i];
193
                    $this->img->Line($x, $yb, $x, $yt);
194
                    $x += $delta;
195
                }
196
                $steps2 = max(1, ceil(0.08 * abs($xr - $xl)));
197
                $this->img->SetColor($to_color);
198
                for ($j = 0; $j < $steps2; ++$j) {
199
                    $this->img->Line($x, $yb, $x, $yt);
200
                    $x += $delta;
201
                }
202
                $steps = abs($xr - $xl) - $steps1 - $steps2;
203
                $this->GetColArray($to_color, $from_color, $steps, $colors, $this->numcolors);
204
                $n = safe_count($colors);
205
                for ($i = 0; $i < $steps && $i < $n; ++$i) {
206
                    $this->img->current_color = $colors[$i];
207
                    $this->img->Line($x, $yb, $x, $yt);
208
                    $x += $delta;
209
                }
210
211
                break;
212
            case GRAD_RIGHT_REFLECTION:
213
                $steps1 = ceil(0.7 * abs($xr - $xl));
214
                $delta  = $xr >= $xl ? 1 : -1;
215
216
                $this->GetColArray($from_color, $to_color, $steps1, $colors, $this->numcolors);
217
                $n = safe_count($colors);
218
                for ($x = $xl, $i = 0; $i < $steps1 && $i < $n; ++$i) {
219
                    $this->img->current_color = $colors[$i];
220
                    $this->img->Line($x, $yb, $x, $yt);
221
                    $x += $delta;
222
                }
223
                $steps2 = max(1, ceil(0.08 * abs($xr - $xl)));
224
                $this->img->SetColor($to_color);
225
                for ($j = 0; $j < $steps2; ++$j) {
226
                    $this->img->Line($x, $yb, $x, $yt);
227
                    $x += $delta;
228
                }
229
230
                $from_color = $this->img->rgb->Color($from_color);
231
                $adj        = 1.4;
232
                $m          = ($adj - 1.0) * (255 - min(255, min($from_color[0], min($from_color[1], $from_color[2]))));
233
                $from_color = [min(255, $from_color[0] + $m),
234
                    min(255, $from_color[1] + $m), min(255, $from_color[2] + $m), ];
235
236
                $steps = abs($xr - $xl) - $steps1 - $steps2;
237
                $this->GetColArray($to_color, $from_color, $steps, $colors, $this->numcolors);
238
                $n = safe_count($colors);
239
                for ($i = 0; $i < $steps && $i < $n; ++$i) {
240
                    $this->img->current_color = $colors[$i];
241
                    $this->img->Line($x, $yb, $x, $yt);
242
                    $x += $delta;
243
                }
244
245
                break;
246
            case GRAD_CENTER:
247
                $steps = ceil(min(($yb - $yt) + 1, ($xr - $xl) + 1) / 2);
248
                $this->GetColArray($from_color, $to_color, $steps, $colors, $this->numcolors);
249
                $dx = ($xr - $xl) / 2;
250
                $dy = ($yb - $yt) / 2;
251
                $x  = $xl;
0 ignored issues
show
Unused Code introduced by
The assignment to $x is dead and can be removed.
Loading history...
252
                $y  = $yt;
253
                $x2 = $xr;
254
                $y2 = $yb;
255
                $n  = safe_count($colors);
256
                for ($x = $xl, $i = 0; $x < $xl + $dx && $y < $yt + $dy && $i < $n; ++$x, ++$y, --$x2, --$y2, ++$i) {
257
                    $this->img->current_color = $colors[$i];
258
                    $this->img->Rectangle($x, $y, $x2, $y2);
259
                }
260
                $this->img->Line($x, $y, $x2, $y2);
261
262
                break;
263
            case GRAD_RAISED_PANEL:
264
                // right to left
265
                $steps1 = $xr - $xl;
266
                $delta  = $xr >= $xl ? 1 : -1;
267
                $this->GetColArray($to_color, $from_color, $steps1, $colors, $this->numcolors);
268
                $n = safe_count($colors);
269
                for ($x = $xl, $i = 0; $i < $steps1 && $i < $n; ++$i) {
270
                    $this->img->current_color = $colors[$i];
271
                    $this->img->Line($x, $yb, $x, $yt);
272
                    $x += $delta;
273
                }
274
275
                // left to right
276
                $xr -= 3;
277
                $xl += 3;
278
                $yb -= 3;
279
                $yt += 3;
280
                $steps2 = $xr - $xl;
281
                $delta  = $xr >= $xl ? 1 : -1;
282
                for ($x = $xl, $j = $steps2; $j >= 0; --$j) {
283
                    $this->img->current_color = $colors[$j];
284
                    $this->img->Line($x, $yb, $x, $yt);
285
                    $x += $delta;
286
                }
287
288
                break;
289
            case GRAD_DIAGONAL:
290
                // use the longer dimension to determine the required number of steps.
291
                // first loop draws from one corner to the mid-diagonal and the second
292
                // loop draws from the mid-diagonal to the opposing corner.
293
                if ($xr - $xl > $yb - $yt) {
294
                    // width is greater than height -> use x-dimension for steps
295
                    $steps = $xr - $xl;
296
                    $delta = $xr >= $xl ? 1 : -1;
297
                    $this->GetColArray($from_color, $to_color, $steps * 2, $colors, $this->numcolors);
298
                    $n = safe_count($colors);
299
300
                    for ($x = $xl, $i = 0; $i < $steps && $i < $n; ++$i) {
301
                        $this->img->current_color = $colors[$i];
302
                        $y                        = $yt + ($i / $steps) * ($yb - $yt) * $delta;
303
                        $this->img->Line($x, $yt, $xl, $y);
304
                        $x += $delta;
305
                    }
306
307
                    for ($x = $xl, $i = 0; $i < $steps && $i < $n; ++$i) {
308
                        $this->img->current_color = $colors[$steps + $i];
309
                        $y                        = $yt + ($i / $steps) * ($yb - $yt) * $delta;
310
                        $this->img->Line($x, $yb, $xr, $y);
311
                        $x += $delta;
312
                    }
313
                } else {
314
                    // height is greater than width -> use y-dimension for steps
315
                    $steps = $yb - $yt;
316
                    $delta = $yb >= $yt ? 1 : -1;
317
                    $this->GetColArray($from_color, $to_color, $steps * 2, $colors, $this->numcolors);
318
                    $n = safe_count($colors);
319
320
                    for ($y = $yt, $i = 0; $i < $steps && $i < $n; ++$i) {
321
                        $this->img->current_color = $colors[$i];
322
                        $x                        = $xl + ($i / $steps) * ($xr - $xl) * $delta;
323
                        $this->img->Line($x, $yt, $xl, $y);
324
                        $y += $delta;
325
                    }
326
327
                    for ($y = $yt, $i = 0; $i < $steps && $i < $n; ++$i) {
328
                        $this->img->current_color = $colors[$steps + $i];
329
                        $x                        = $xl + ($i / $steps) * ($xr - $xl) * $delta;
330
                        $this->img->Line($x, $yb, $xr, $y);
331
                        $x += $delta;
332
                    }
333
                }
334
335
                break;
336
            default:
337
                Util\JpGraphError::RaiseL(7001, $style);
338
                //("Unknown gradient style (=$style).");
339
                break;
340
        }
341 3
    }
342
343
    // Fill a special case of a polygon with a flat bottom
344
    // with a gradient. Can be used for filled line plots.
345
    // Please note that this is NOT a generic gradient polygon fill
346
    // routine. It assumes that the bottom is flat (like a drawing
347
    // of a mountain)
348
    public function FilledFlatPolygon($pts, $from_color, $to_color)
349
    {
350
        if (safe_count($pts) == 0) {
351
            return;
352
        }
353
354
        $maxy = $pts[1];
355
        $miny = $pts[1];
356
        $n    = safe_count($pts);
357
        for ($i = 0, $idx = 0; $i < $n; $i += 2) {
0 ignored issues
show
Unused Code introduced by
The assignment to $idx is dead and can be removed.
Loading history...
358
            $x    = round($pts[$i]);
0 ignored issues
show
Unused Code introduced by
The assignment to $x is dead and can be removed.
Loading history...
359
            $y    = round($pts[$i + 1]);
360
            $miny = min($miny, $y);
361
            $maxy = max($maxy, $y);
362
        }
363
364
        $colors = [];
365
        $this->GetColArray($from_color, $to_color, abs($maxy - $miny) + 1, $colors, $this->numcolors);
366
        for ($i = $miny, $idx = 0; $i <= $maxy; ++$i) {
367
            $colmap[$i] = $colors[$idx++];
368
        }
369
370
        $n   = safe_count($pts) / 2;
371
        $idx = 0;
372
        while ($idx < $n - 1) {
373
            $p1 = [round($pts[$idx * 2]), round($pts[$idx * 2 + 1])];
374
            $p2 = [round($pts[++$idx * 2]), round($pts[$idx * 2 + 1])];
375
376
            // Find the largest rectangle we can fill
377
            $y = max($p1[1], $p2[1]);
378
            for ($yy = $maxy; $yy > $y; --$yy) {
379
                $this->img->current_color = $colmap[$yy];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $colmap does not seem to be defined for all execution paths leading up to this point.
Loading history...
380
                $this->img->Line($p1[0], $yy, $p2[0] - 1, $yy);
381
            }
382
383
            if ($p1[1] == $p2[1]) {
384
                continue;
385
            }
386
387
            // Fill the rest using lines (slow...)
388
            $slope = ($p2[0] - $p1[0]) / ($p1[1] - $p2[1]);
389
            $x1    = $p1[0];
390
            $x2    = $p2[0] - 1;
391
            $start = $y;
392
            if ($p1[1] > $p2[1]) {
393
                while ($y >= $p2[1]) {
394
                    $x1                       = $slope * ($start - $y) + $p1[0];
395
                    $this->img->current_color = $colmap[$y];
396
                    $this->img->Line($x1, $y, $x2, $y);
397
                    --$y;
398
                }
399
            } else {
400
                while ($y >= $p1[1]) {
401
                    $x2                       = $p2[0] + $slope * ($start - $y);
402
                    $this->img->current_color = $colmap[$y];
403
                    $this->img->Line($x1, $y, $x2, $y);
404
                    --$y;
405
                }
406
            }
407
        }
408
    }
409
410
    /**
411
     * PRIVATE METHODS.
412
     *
413
     * @param mixed $from_color
414
     * @param mixed $to_color
415
     * @param mixed $arr_size
416
     * @param mixed $numcols
417
     * @param mixed $colors
418
     */
419
    // Add to the image color map the necessary colors to do the transition
420
    // between the two colors using $numcolors intermediate colors
421 3
    public function GetColArray($from_color, $to_color, $arr_size, &$colors, $numcols = 100)
422
    {
423 3
        if ($arr_size == 0) {
424
            return;
425
        }
426
427
        // If color is given as text get it's corresponding r,g,b values
428 3
        $from_color = $this->img->rgb->Color($from_color);
429 3
        $to_color   = $this->img->rgb->Color($to_color);
430
431 3
        $rdelta        = ($to_color[0] - $from_color[0]) / $numcols;
432 3
        $gdelta        = ($to_color[1] - $from_color[1]) / $numcols;
433 3
        $bdelta        = ($to_color[2] - $from_color[2]) / $numcols;
434 3
        $colorsperstep = $numcols / $arr_size;
435 3
        $prevcolnum    = -1;
436 3
        $from_alpha    = $from_color[3];
437 3
        $to_alpha      = $to_color[3];
438 3
        $adelta        = ($to_alpha - $from_alpha) / $numcols;
439
440 3
        for ($i = 0; $i < $arr_size; ++$i) {
441 3
            $colnum = floor($colorsperstep * $i);
442 3
            if ($colnum == $prevcolnum) {
443 3
                $colors[$i] = $colidx;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $colidx does not seem to be defined for all execution paths leading up to this point.
Loading history...
444
            } else {
445 3
                $r     = floor($from_color[0] + $colnum * $rdelta);
446 3
                $g     = floor($from_color[1] + $colnum * $gdelta);
447 3
                $b     = floor($from_color[2] + $colnum * $bdelta);
448 3
                $alpha = $from_alpha + $colnum * $adelta;
449
450 3
                $colidx     = $this->img->rgb->Allocate(sprintf('#%02x%02x%02x', $r, $g, $b), $alpha);
451 3
                $colors[$i] = $colidx;
452
            }
453 3
            $prevcolnum = $colnum;
454
        }
455 3
    }
456
} // @class
457