2 /*=======================================================================
3 // File: JPGRAPH_GRADIENT.PHP
4 // Description: Create a color gradient
6 // Author: Johan Persson (johanp@aditus.nu)
7 // Ver: $Id: jpgraph_gradient.php,v 1.1.2.5 2003/08/23 23:15:06 aditus Exp $
9 // License: This code is released under QPL
10 // Copyright (C) 2003 Johan Persson
11 //========================================================================
15 //===================================================
17 // Description: Handles gradient fills. This is to be
18 // considered a "friend" class of Class Image.
19 //===================================================
25 function Gradient(&$img) {
30 function SetNumColors($aNum) {
31 $this->numcolors=$aNum;
35 // Produce a gradient filled rectangle with a smooth transition between
37 // ($xl,$yt) Top left corner
38 // ($xr,$yb) Bottom right
39 // $from_color Starting color in gradient
40 // $to_color End color in the gradient
41 // $style Which way is the gradient oriented?
42 function FilledRectangle($xl,$yt,$xr,$yb,$from_color,$to_color,$style=1) {
45 $steps = abs($xr-$xl);
46 $delta = $xr>=$xl ? 1 : -1;
47 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
48 for( $i=0, $x=$xl; $i < $steps; ++$i ) {
49 $this->img->current_color = $colors[$i];
50 $this->img->Line($x,$yt,$x,$yb);
56 $steps = abs($yb-$yt);
57 $delta = $yb>=$yt ? 1 : -1;
58 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
59 for($i=0,$y=$yt; $i < $steps; ++$i) {
60 $this->img->current_color = $colors[$i];
61 $this->img->Line($xl,$y,$xr,$y);
66 case 3: // VERTICAL FROM MIDDLE
67 $steps = abs($yb-$yt)/2;
68 $delta = $yb >= $yt ? 1 : -1;
69 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
70 for($y=$yt, $i=0; $i < $steps; ++$i) {
71 $this->img->current_color = $colors[$i];
72 $this->img->Line($xl,$y,$xr,$y);
76 for($j=0; $j < $steps; ++$j, --$i) {
77 $this->img->current_color = $colors[$i];
78 $this->img->Line($xl,$y,$xr,$y);
81 $this->img->Line($xl,$y,$xr,$y);
84 case 4: // HORIZONTAL FROM MIDDLE
85 $steps = abs($xr-$xl)/2;
86 $delta = $xr>=$xl ? 1 : -1;
87 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
88 for($x=$xl, $i=0; $i < $steps; ++$i) {
89 $this->img->current_color = $colors[$i];
90 $this->img->Line($x,$yb,$x,$yt);
94 for($j=0; $j < $steps; ++$j, --$i) {
95 $this->img->current_color = $colors[$i];
96 $this->img->Line($x,$yb,$x,$yt);
99 $this->img->Line($x,$yb,$x,$yt);
102 case 6: // HORIZONTAL WIDER MIDDLE
103 $diff = round(abs($xr-$xl));
104 $steps = floor(abs($diff)/3);
105 $firststep = $diff - 2*$steps ;
106 // $steps = abs($xr-$xl)/3;
107 $delta = $xr >= $xl ? 1 : -1;
108 $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
109 for($x=$xl, $i=0; $i < $firststep; ++$i) {
110 $this->img->current_color = $colors[$i];
111 $this->img->Line($x,$yb,$x,$yt);
115 $this->img->current_color = $colors[$i];
116 for($j=0; $j< $steps; ++$j) {
117 $this->img->Line($x,$yb,$x,$yt);
121 for($j=0; $j < $steps; ++$j, --$i) {
122 $this->img->current_color = $colors[$i];
123 $this->img->Line($x,$yb,$x,$yt);
128 case 7: // VERTICAL WIDER MIDDLE
129 $diff = round(abs($yb-$yt));
130 $steps = floor(abs($diff)/3);
131 $firststep = $diff - 2*$steps ;
132 $delta = $yb >= $yt? 1 : -1;
133 $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
134 for($y=$yt, $i=0; $i < $firststep; ++$i) {
135 $this->img->current_color = $colors[$i];
136 $this->img->Line($xl,$y,$xr,$y);
140 $this->img->current_color = $colors[$i];
141 for($j=0; $j < $steps; ++$j) {
142 $this->img->Line($xl,$y,$xr,$y);
145 for($j=0; $j < $steps; ++$j, --$i) {
146 $this->img->current_color = $colors[$i];
147 $this->img->Line($xl,$y,$xr,$y);
152 case 8: // LEFT REFLECTION
153 $steps1 = round(0.3*abs($xr-$xl));
154 $delta = $xr>=$xl ? 1 : -1;
156 $this->GetColArray($from_color.':1.3',$to_color,$steps1,$colors,$this->numcolors);
157 for($x=$xl, $i=0; $i < $steps1; ++$i) {
158 $this->img->current_color = $colors[$i];
159 $this->img->Line($x,$yb,$x,$yt);
162 $steps2 = max(1,round(0.08*abs($xr-$xl)));
163 $this->img->SetColor($to_color);
164 for($j=0; $j< $steps2; ++$j) {
165 $this->img->Line($x,$yb,$x,$yt);
168 $steps = abs($xr-$xl)-$steps1-$steps2;
169 $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors);
170 for($i=0; $i < $steps; ++$i) {
171 $this->img->current_color = $colors[$i];
172 $this->img->Line($x,$yb,$x,$yt);
177 case 9: // RIGHT REFLECTION
178 $steps1 = round(0.7*abs($xr-$xl));
179 $delta = $xr>=$xl ? 1 : -1;
181 $this->GetColArray($from_color,$to_color,$steps1,$colors,$this->numcolors);
182 for($x=$xl, $i=0; $i < $steps1; ++$i) {
183 $this->img->current_color = $colors[$i];
184 $this->img->Line($x,$yb,$x,$yt);
187 $steps2 = max(1,round(0.08*abs($xr-$xl)));
188 $this->img->SetColor($to_color);
189 for($j=0; $j< $steps2; ++$j) {
190 $this->img->Line($x,$yb,$x,$yt);
193 $steps = abs($xr-$xl)-$steps1-$steps2;
194 $this->GetColArray($to_color,$from_color.':1.3',$steps,$colors,$this->numcolors);
195 for($i=0; $i < $steps; ++$i) {
196 $this->img->current_color = $colors[$i];
197 $this->img->Line($x,$yb,$x,$yt);
204 $steps = floor(min(($yb-$yt)+1,($xr-$xl)+1)/2);
205 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
208 $x=$xl;$y=$yt;$x2=$xr;$y2=$yb;
209 for($x=$xl, $i=0; $x < $xl+$dx && $y < $yt+$dy ; ++$x, ++$y, --$x2, --$y2, ++$i) {
210 assert( $i < count($colors));
211 $this->img->current_color = $colors[$i];
212 $this->img->Rectangle($x,$y,$x2,$y2);
214 $this->img->Line($x,$y,$x2,$y2);
218 die("JpGraph Error: Unknown gradient style (=$style).");
223 // Fill a special case of a polygon with a flat bottom
224 // with a gradient. Can be used for filled line plots.
225 // Please note that this is NOT a generic gradient polygon fill
226 // routine. It assumes that the bottom is flat (like a drawing
228 function FilledFlatPolygon($pts,$from_color,$to_color) {
229 if( count($pts) == 0 ) return;
234 for( $i=0, $idx=0; $i < $n; $i += 2) {
235 $x = round($pts[$i]);
236 $y = round($pts[$i+1]);
237 $miny = min($miny,$y);
238 $maxy = max($maxy,$y);
242 $this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors);
243 for($i=$miny, $idx=0; $i <= $maxy; ++$i ) {
244 $colmap[$i] = $colors[$idx++];
249 while( $idx < $n-1 ) {
250 $p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1]));
251 $p2 = array(round($pts[++$idx*2]),round($pts[$idx*2+1]));
253 // Find the largest rectangle we can fill
254 $y = max($p1[1],$p2[1]) ;
255 for($yy=$maxy; $yy >= $y; --$yy) {
256 $this->img->current_color = $colmap[$yy];
257 $this->img->Line($p1[0],$yy,$p2[0],$yy);
260 if( $p1[1] == $p2[1] ) continue;
262 // Fill the rest using lines (slow...)
263 $slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]);
267 if( $p1[1] > $p2[1] ) {
268 while( $y >= $p2[1] ) {
269 $x1=$slope*($start-$y)+$p1[0];
270 $this->img->current_color = $colmap[$y];
271 $this->img->Line($x1,$y,$x2,$y);
276 while( $y >= $p1[1] ) {
277 $x2=$p2[0]+$slope*($start-$y);
278 $this->img->current_color = $colmap[$y];
279 $this->img->Line($x1,$y,$x2,$y);
288 // Add to the image color map the necessary colors to do the transition
289 // between the two colors using $numcolors intermediate colors
290 function GetColArray($from_color,$to_color,$arr_size,&$colors,$numcols=100) {
291 if( $arr_size==0 ) return;
292 // If color is given as text get it's corresponding r,g,b values
293 $from_color = $this->img->rgb->Color($from_color);
294 $to_color = $this->img->rgb->Color($to_color);
296 $rdelta=($to_color[0]-$from_color[0])/$numcols;
297 $gdelta=($to_color[1]-$from_color[1])/$numcols;
298 $bdelta=($to_color[2]-$from_color[2])/$numcols;
299 $colorsperstep = $numcols/$arr_size;
301 for ($i=0; $i < $arr_size; ++$i) {
302 $colnum = floor($colorsperstep*$i);
303 if ( $colnum == $prevcolnum )
304 $colors[$i] = $colidx;
306 $r = floor($from_color[0] + $colnum*$rdelta);
307 $g = floor($from_color[1] + $colnum*$gdelta);
308 $b = floor($from_color[2] + $colnum*$bdelta);
309 $colidx = $this->img->rgb->Allocate(sprintf("#%02x%02x%02x",$r,$g,$b));
310 $colors[$i] = $colidx;
312 $prevcolnum = $colnum;