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
![]() |
|||
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
|
|||
358 | $x = round($pts[$i]); |
||
0 ignored issues
–
show
|
|||
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
|
|||
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
|
|||
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 |