source: trunk/client/modules/Elezioni/grafici/jpgraph_gradient.php@ 265

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