PageRenderTime 64ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/include/jpgraph/jpgraph_gradient.php

https://github.com/Rambutan/hamsterpaj
PHP | 376 lines | 303 code | 32 blank | 41 comment | 46 complexity | 9100c51841164f654c046bf5a95a6b3f MD5 | raw file
  1. <?php
  2. /*=======================================================================
  3. // File: JPGRAPH_GRADIENT.PHP
  4. // Description: Create a color gradient
  5. // Created: 2003-02-01
  6. // Author: Johan Persson (johanp@aditus.nu)
  7. // Ver: $Id: jpgraph_gradient.php 21 2005-05-30 20:35:34Z ljp $
  8. //
  9. // Copyright (c) Aditus Consulting. All rights reserved.
  10. //========================================================================
  11. */
  12. // Styles for gradient color fill
  13. DEFINE("GRAD_VER",1);
  14. DEFINE("GRAD_VERT",1);
  15. DEFINE("GRAD_HOR",2);
  16. DEFINE("GRAD_MIDHOR",3);
  17. DEFINE("GRAD_MIDVER",4);
  18. DEFINE("GRAD_CENTER",5);
  19. DEFINE("GRAD_WIDE_MIDVER",6);
  20. DEFINE("GRAD_WIDE_MIDHOR",7);
  21. DEFINE("GRAD_LEFT_REFLECTION",8);
  22. DEFINE("GRAD_RIGHT_REFLECTION",9);
  23. DEFINE("GRAD_RAISED_PANEL",10);
  24. //===================================================
  25. // CLASS Gradient
  26. // Description: Handles gradient fills. This is to be
  27. // considered a "friend" class of Class Image.
  28. //===================================================
  29. class Gradient {
  30. var $img=null;
  31. var $numcolors=100;
  32. //---------------
  33. // CONSTRUCTOR
  34. function Gradient(&$img) {
  35. $this->img = $img;
  36. }
  37. function SetNumColors($aNum) {
  38. $this->numcolors=$aNum;
  39. }
  40. //---------------
  41. // PUBLIC METHODS
  42. // Produce a gradient filled rectangle with a smooth transition between
  43. // two colors.
  44. // ($xl,$yt) Top left corner
  45. // ($xr,$yb) Bottom right
  46. // $from_color Starting color in gradient
  47. // $to_color End color in the gradient
  48. // $style Which way is the gradient oriented?
  49. function FilledRectangle($xl,$yt,$xr,$yb,$from_color,$to_color,$style=1) {
  50. switch( $style ) {
  51. case GRAD_VER:
  52. $steps = round(abs($xr-$xl));
  53. $delta = $xr>=$xl ? 1 : -1;
  54. $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
  55. for( $i=0, $x=$xl; $i < $steps; ++$i ) {
  56. $this->img->current_color = $colors[$i];
  57. $this->img->Line($x,$yt,$x,$yb);
  58. $x += $delta;
  59. }
  60. break;
  61. case GRAD_HOR:
  62. $steps = round(abs($yb-$yt));
  63. $delta = $yb>=$yt ? 1 : -1;
  64. $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
  65. for($i=0,$y=$yt; $i < $steps; ++$i) {
  66. $this->img->current_color = $colors[$i];
  67. $this->img->Line($xl,$y,$xr,$y);
  68. $y += $delta;
  69. }
  70. break;
  71. case GRAD_MIDHOR:
  72. $steps = round(abs($yb-$yt)/2);
  73. $delta = $yb >= $yt ? 1 : -1;
  74. $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
  75. for($y=$yt, $i=0; $i < $steps; ++$i) {
  76. $this->img->current_color = $colors[$i];
  77. $this->img->Line($xl,$y,$xr,$y);
  78. $y += $delta;
  79. }
  80. --$i;
  81. if( abs($yb-$yt) % 2 == 1 ) --$steps;
  82. for($j=0; $j < $steps; ++$j, --$i) {
  83. $this->img->current_color = $colors[$i];
  84. $this->img->Line($xl,$y,$xr,$y);
  85. $y += $delta;
  86. }
  87. $this->img->Line($xl,$y,$xr,$y);
  88. break;
  89. case GRAD_MIDVER:
  90. $steps = round(abs($xr-$xl)/2);
  91. $delta = $xr>=$xl ? 1 : -1;
  92. $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
  93. for($x=$xl, $i=0; $i < $steps; ++$i) {
  94. $this->img->current_color = $colors[$i];
  95. $this->img->Line($x,$yb,$x,$yt);
  96. $x += $delta;
  97. }
  98. --$i;
  99. if( abs($xr-$xl) % 2 == 1 ) --$steps;
  100. for($j=0; $j < $steps; ++$j, --$i) {
  101. $this->img->current_color = $colors[$i];
  102. $this->img->Line($x,$yb,$x,$yt);
  103. $x += $delta;
  104. }
  105. $this->img->Line($x,$yb,$x,$yt);
  106. break;
  107. case GRAD_WIDE_MIDVER:
  108. $diff = round(abs($xr-$xl));
  109. $steps = floor(abs($diff)/3);
  110. $firststep = $diff - 2*$steps ;
  111. $delta = $xr >= $xl ? 1 : -1;
  112. $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
  113. for($x=$xl, $i=0; $i < $firststep; ++$i) {
  114. $this->img->current_color = $colors[$i];
  115. $this->img->Line($x,$yb,$x,$yt);
  116. $x += $delta;
  117. }
  118. --$i;
  119. $this->img->current_color = $colors[$i];
  120. for($j=0; $j< $steps; ++$j) {
  121. $this->img->Line($x,$yb,$x,$yt);
  122. $x += $delta;
  123. }
  124. for($j=0; $j < $steps; ++$j, --$i) {
  125. $this->img->current_color = $colors[$i];
  126. $this->img->Line($x,$yb,$x,$yt);
  127. $x += $delta;
  128. }
  129. break;
  130. case GRAD_WIDE_MIDHOR:
  131. $diff = round(abs($yb-$yt));
  132. $steps = floor(abs($diff)/3);
  133. $firststep = $diff - 2*$steps ;
  134. $delta = $yb >= $yt? 1 : -1;
  135. $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
  136. for($y=$yt, $i=0; $i < $firststep; ++$i) {
  137. $this->img->current_color = $colors[$i];
  138. $this->img->Line($xl,$y,$xr,$y);
  139. $y += $delta;
  140. }
  141. --$i;
  142. $this->img->current_color = $colors[$i];
  143. for($j=0; $j < $steps; ++$j) {
  144. $this->img->Line($xl,$y,$xr,$y);
  145. $y += $delta;
  146. }
  147. for($j=0; $j < $steps; ++$j, --$i) {
  148. $this->img->current_color = $colors[$i];
  149. $this->img->Line($xl,$y,$xr,$y);
  150. $y += $delta;
  151. }
  152. break;
  153. case GRAD_LEFT_REFLECTION:
  154. $steps1 = round(0.3*abs($xr-$xl));
  155. $delta = $xr>=$xl ? 1 : -1;
  156. $from_color = $this->img->rgb->Color($from_color);
  157. $adj = 1.4;
  158. $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2]))));
  159. $from_color2 = array(min(255,$from_color[0]+$m),
  160. min(255,$from_color[1]+$m), min(255,$from_color[2]+$m));
  161. $this->GetColArray($from_color2,$to_color,$steps1,$colors,$this->numcolors);
  162. $n = count($colors);
  163. for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
  164. $this->img->current_color = $colors[$i];
  165. $this->img->Line($x,$yb,$x,$yt);
  166. $x += $delta;
  167. }
  168. $steps2 = max(1,round(0.08*abs($xr-$xl)));
  169. $this->img->SetColor($to_color);
  170. for($j=0; $j< $steps2; ++$j) {
  171. $this->img->Line($x,$yb,$x,$yt);
  172. $x += $delta;
  173. }
  174. $steps = abs($xr-$xl)-$steps1-$steps2;
  175. $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors);
  176. $n = count($colors);
  177. for($i=0; $i < $steps && $i < $n; ++$i) {
  178. $this->img->current_color = $colors[$i];
  179. $this->img->Line($x,$yb,$x,$yt);
  180. $x += $delta;
  181. }
  182. break;
  183. case GRAD_RIGHT_REFLECTION:
  184. $steps1 = round(0.7*abs($xr-$xl));
  185. $delta = $xr>=$xl ? 1 : -1;
  186. $this->GetColArray($from_color,$to_color,$steps1,$colors,$this->numcolors);
  187. $n = count($colors);
  188. for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
  189. $this->img->current_color = $colors[$i];
  190. $this->img->Line($x,$yb,$x,$yt);
  191. $x += $delta;
  192. }
  193. $steps2 = max(1,round(0.08*abs($xr-$xl)));
  194. $this->img->SetColor($to_color);
  195. for($j=0; $j< $steps2; ++$j) {
  196. $this->img->Line($x,$yb,$x,$yt);
  197. $x += $delta;
  198. }
  199. $from_color = $this->img->rgb->Color($from_color);
  200. $adj = 1.4;
  201. $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2]))));
  202. $from_color = array(min(255,$from_color[0]+$m),
  203. min(255,$from_color[1]+$m), min(255,$from_color[2]+$m));
  204. $steps = abs($xr-$xl)-$steps1-$steps2;
  205. $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors);
  206. $n = count($colors);
  207. for($i=0; $i < $steps && $i < $n; ++$i) {
  208. $this->img->current_color = $colors[$i];
  209. $this->img->Line($x,$yb,$x,$yt);
  210. $x += $delta;
  211. }
  212. break;
  213. case GRAD_CENTER:
  214. $steps = ceil(min(($yb-$yt)+1,($xr-$xl)+1)/2);
  215. $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
  216. $dx = ($xr-$xl)/2;
  217. $dy = ($yb-$yt)/2;
  218. $x=$xl;$y=$yt;$x2=$xr;$y2=$yb;
  219. $n = count($colors);
  220. for($x=$xl, $i=0; $x < $xl+$dx && $y < $yt+$dy && $i < $n; ++$x, ++$y, --$x2, --$y2, ++$i) {
  221. $this->img->current_color = $colors[$i];
  222. $this->img->Rectangle($x,$y,$x2,$y2);
  223. }
  224. $this->img->Line($x,$y,$x2,$y2);
  225. break;
  226. case GRAD_RAISED_PANEL:
  227. // right to left
  228. $steps1 = $xr-$xl;
  229. $delta = $xr>=$xl ? 1 : -1;
  230. $this->GetColArray($to_color,$from_color,$steps1,$colors,$this->numcolors);
  231. $n = count($colors);
  232. for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
  233. $this->img->current_color = $colors[$i];
  234. $this->img->Line($x,$yb,$x,$yt);
  235. $x += $delta;
  236. }
  237. // left to right
  238. $xr -= 3;
  239. $xl += 3;
  240. $yb -= 3;
  241. $yt += 3;
  242. $steps2 = $xr-$xl;
  243. $delta = $xr>=$xl ? 1 : -1;
  244. for($x=$xl, $j=$steps2; $j >= 0; --$j) {
  245. $this->img->current_color = $colors[$j];
  246. $this->img->Line($x,$yb,$x,$yt);
  247. $x += $delta;
  248. }
  249. break;
  250. default:
  251. JpGraphError::Raise("Unknown gradient style (=$style).");
  252. break;
  253. }
  254. }
  255. // Fill a special case of a polygon with a flat bottom
  256. // with a gradient. Can be used for filled line plots.
  257. // Please note that this is NOT a generic gradient polygon fill
  258. // routine. It assumes that the bottom is flat (like a drawing
  259. // of a mountain)
  260. function FilledFlatPolygon($pts,$from_color,$to_color) {
  261. if( count($pts) == 0 ) return;
  262. $maxy=$pts[1];
  263. $miny=$pts[1];
  264. $n = count($pts) ;
  265. for( $i=0, $idx=0; $i < $n; $i += 2) {
  266. $x = round($pts[$i]);
  267. $y = round($pts[$i+1]);
  268. $miny = min($miny,$y);
  269. $maxy = max($maxy,$y);
  270. }
  271. $colors = array();
  272. $this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors);
  273. for($i=$miny, $idx=0; $i <= $maxy; ++$i ) {
  274. $colmap[$i] = $colors[$idx++];
  275. }
  276. $n = count($pts)/2 ;
  277. $idx = 0 ;
  278. while( $idx < $n-1 ) {
  279. $p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1]));
  280. $p2 = array(round($pts[++$idx*2]),round($pts[$idx*2+1]));
  281. // Find the largest rectangle we can fill
  282. $y = max($p1[1],$p2[1]) ;
  283. for($yy=$maxy; $yy > $y; --$yy) {
  284. $this->img->current_color = $colmap[$yy];
  285. $this->img->Line($p1[0],$yy,$p2[0]-1,$yy);
  286. }
  287. if( $p1[1] == $p2[1] ) continue;
  288. // Fill the rest using lines (slow...)
  289. $slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]);
  290. $x1 = $p1[0];
  291. $x2 = $p2[0]; //-1;
  292. $start = $y;
  293. if( $p1[1] > $p2[1] ) {
  294. while( $y >= $p2[1] ) {
  295. $x1=$slope*($start-$y)+$p1[0];
  296. $this->img->current_color = $colmap[$y];
  297. $this->img->Line($x1,$y,$x2,$y);
  298. --$y;
  299. }
  300. }
  301. else {
  302. while( $y >= $p1[1] ) {
  303. $x2=$p2[0]+$slope*($start-$y);
  304. $this->img->current_color = $colmap[$y];
  305. $this->img->Line($x1,$y,$x2,$y);
  306. --$y;
  307. }
  308. }
  309. }
  310. }
  311. //---------------
  312. // PRIVATE METHODS
  313. // Add to the image color map the necessary colors to do the transition
  314. // between the two colors using $numcolors intermediate colors
  315. function GetColArray($from_color,$to_color,$arr_size,&$colors,$numcols=100) {
  316. if( $arr_size==0 ) return;
  317. // If color is given as text get it's corresponding r,g,b values
  318. $from_color = $this->img->rgb->Color($from_color);
  319. $to_color = $this->img->rgb->Color($to_color);
  320. $rdelta=($to_color[0]-$from_color[0])/$numcols;
  321. $gdelta=($to_color[1]-$from_color[1])/$numcols;
  322. $bdelta=($to_color[2]-$from_color[2])/$numcols;
  323. $colorsperstep = $numcols/$arr_size;
  324. $prevcolnum = -1;
  325. $from_alpha = $from_color[3];
  326. $to_alpha = $to_color[3];
  327. $adelta = ( $to_alpha - $from_alpha ) / $numcols ;
  328. for ($i=0; $i < $arr_size; ++$i) {
  329. $colnum = floor($colorsperstep*$i);
  330. if ( $colnum == $prevcolnum )
  331. $colors[$i] = $colidx;
  332. else {
  333. $r = floor($from_color[0] + $colnum*$rdelta);
  334. $g = floor($from_color[1] + $colnum*$gdelta);
  335. $b = floor($from_color[2] + $colnum*$bdelta);
  336. $alpha = $from_alpha + $colnum*$adelta;
  337. $colidx = $this->img->rgb->Allocate(sprintf("#%02x%02x%02x",$r,$g,$b),$alpha);
  338. $colors[$i] = $colidx;
  339. }
  340. $prevcolnum = $colnum;
  341. }
  342. }
  343. } // Class
  344. ?>