In mail.php, we don't want to double encode fields so in send() create local variable...
[isso.git] / graph_pie.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Blue Static ISSO Framework
5 || # Copyright ©2002-[#]year[#] Blue Static
6 || #
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
10 || #
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 || # more details.
15 || #
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
21
22 /**
23 * Graphing system: pie chart
24 * graph_pie.php
25 *
26 * @package ISSO
27 */
28
29 /**
30 * Graphing System: Pie Chart
31 *
32 * This framework creates pie charts as PNG image strings. Simply add to
33 * the data set and graph to get the byte stream returned.
34 *
35 * @author Blue Static
36 * @copyright Copyright ©2002 - [#]year[#], Blue Static
37 * @version $Revision$
38 * @package ISSO
39 *
40 */
41 class Graph_Pie
42 {
43 /**
44 * Framework registry object
45 * @var object
46 * @access private
47 */
48 var $registry = null;
49
50 /**
51 * Graphing data set; 2D array of
52 * array(NAME, PERCENT, COLOR)
53 * @var array
54 * @access private
55 */
56 var $dataset = array();
57
58 /**
59 * Image resource
60 * @var resource
61 * @access private
62 */
63 var $image = null;
64
65 /**
66 * The dimensions of the image
67 * @var array
68 * @access private
69 */
70 var $dimensions = array('width' => 550, 'height' => 350);
71
72 /**
73 * Add a legend to the graph
74 * @var bool
75 * @access private
76 */
77 var $legend = true;
78
79 /**
80 * Title of the graph
81 * @var string
82 * @access private
83 */
84 var $title = 'ISSO Pie Chart';
85
86 // ###################################################################
87 /**
88 * Constructor
89 */
90 function __construct(&$registry)
91 {
92 $this->registry =& $registry;
93
94 $this->set_scale(0);
95 }
96
97 // ###################################################################
98 /**
99 * (PHP 4) Constructor
100 */
101 function Graph_Pie(&$registry)
102 {
103 $this->__construct($registry);
104 }
105
106 // ###################################################################
107 /**
108 * Graphs the actual graph and returns a byte stream
109 *
110 * @access public
111 *
112 * @return string Byte stream
113 */
114 function graph()
115 {
116 $colours['black'] = imagecolorallocate($this->image, 0, 0, 0);
117 $colours['white'] = imagecolorallocate($this->image, 255, 255, 255);
118 $colours['grey'] = imagecolorallocate($this->image, 121, 121, 123);
119
120 $graphpadding = 10;
121 $graphspacing = 4;
122 $diameter = $this->dimensions['height'] - (5 * $graphpadding);
123 $radius = $diameter / 2;
124 $graphstart = $graphpadding + imagefontheight(5) + $graphpadding;
125 $legendbox = 10;
126
127 // fill background
128 imagefill($this->image, 0, 0, $colours['white']);
129
130 // title the chart
131 imagestring($this->image, 5, ($this->dimensions['width'] - (imagefontwidth(5) * strlen($this->title))) / 2, $graphpadding, $this->title, $colours['black']);
132
133 $center = array(
134 'x' => ($this->legend ? ($radius + $graphpadding) : ($this->dimensions['width'] / 2)),
135 'y' => ($this->dimensions['height'] / 2) + $graphpadding
136 );
137
138 // draw a border
139 imageline($this->image, 0, 0, 0, $this->dimensions['height'], $colours['black']); // left
140 imageline($this->image, 0, $this->dimensions['height'] - 1, $this->dimensions['width'], $this->dimensions['height'] - 1, $colours['black']); // bottom
141 imageline($this->image, $this->dimensions['width'] - 1, 0, $this->dimensions['width'] - 1, $this->dimensions['height'], $colours['black']); // right
142 imageline($this->image, 0, 0, $this->dimensions['width'], 0, $colours['black']); // top
143
144 $legx = (2 * $graphpadding) + $diameter;
145
146 $lastdeg = 0;
147 $boxoffset = 0;
148 foreach ($this->dataset AS $plot)
149 {
150 $deg = (360 / 100) * $plot[1];
151 imagefilledarc($this->image, $center['x'], $center['y'], $diameter, $diameter, $lastdeg, $deg + $lastdeg, $plot[2], IMG_ARC_PIE);
152 imagefilledarc($this->image, $center['x'], $center['y'], $diameter, $diameter, $lastdeg, $deg + $lastdeg, $colours['grey'], IMG_ARC_EDGED | IMG_ARC_NOFILL);
153 $lastdeg += $deg;
154
155 if ($this->legend)
156 {
157 $box = array(
158 $legx + 1 + $graphspacing, $graphstart + 1 + $graphspacing + $boxoffset, // top left
159 $legx + 1 + $graphspacing, $graphstart + 1 + $graphspacing + $boxoffset + $legendbox, // bottom left
160 $legx + 1 + $graphspacing + $legendbox, $graphstart + 1 + $graphspacing + $boxoffset + $legendbox, // bottom right
161 $legx + 1 + $graphspacing + $legendbox, $graphstart + 1 + $graphspacing + $boxoffset // top right
162 );
163 imagefilledpolygon($this->image, $box, 4, $plot[2]);
164
165 imagestring($this->image, 2, ($legx + 1 + $graphspacing + $legendbox + $graphspacing), ($graphstart + $graphspacing + $boxoffset), $plot[0] . " ($plot[1]%)", $colours['black']);
166
167 $boxoffset += $graphspacing + $legendbox;
168 }
169 }
170
171 // draw the ellipse (do here so it cleans up the arc edges)
172 imageellipse($this->image, $center['x'], $center['y'], $diameter, $diameter, $colours['grey']);
173
174 // do the legend
175 if ($this->legend)
176 {
177 imageline($this->image, $legx, $graphstart, $this->dimensions['width'] - $graphpadding, $graphstart, $colours['black']); // top
178 imageline($this->image, $legx, $graphstart, $legx, $legy = ($graphstart + $graphspacing + $boxoffset + 1), $colours['black']); // left
179 imageline($this->image, $legx, $legy, $this->dimensions['width'] - $graphpadding, $legy, $colours['black']); // bottom
180 imageline($this->image, $this->dimensions['width'] - $graphpadding, $graphstart, $this->dimensions['width'] - $graphpadding, $legy, $colours['black']); // right
181 }
182
183 ob_start();
184 imagepng($this->image);
185 $data = ob_get_contents();
186 if ($data === false)
187 {
188 $data = ob_get_clean();
189 }
190 ob_clean();
191 ob_end_clean();
192
193 return $data;
194 }
195
196 // ###################################################################
197 /**
198 * Sets the width and height by using scale factors of 550x350; you
199 * can specify a positive value to multiply by that many times or a
200 * negative one to divide
201 *
202 * @access public
203 *
204 * @param float Scale factor
205 */
206 function set_scale($scale)
207 {
208 $this->dimensions['width'] = 550;
209 $this->dimensions['height'] = 350;
210
211 if ($scale > 0)
212 {
213 $this->dimensions['width'] *= $scale;
214 $this->dimensions['height'] *= $scale;
215 }
216 else if ($scale < 0)
217 {
218 $scale = abs($scale);
219 $this->dimensions['width'] /= $scale;
220 $this->dimensions['height'] /= $scale;
221 }
222
223 if (!is_null($this->image))
224 {
225 imagedestroy($this->image);
226 }
227
228 $this->image = imagecreate($this->dimensions['width'], $this->dimensions['height']);
229 }
230
231 // ###################################################################
232 /**
233 * Sets whether or not a legend is created for the graph
234 *
235 * @access public
236 *
237 * @param bool Draw a legend?
238 */
239 function set_legend($yesno)
240 {
241 $this->legend = (bool)$yesno;
242 }
243
244 // ###################################################################
245 /**
246 * Sets the title of the chart to be drawn above the graph
247 *
248 * @access public
249 *
250 * @param string Title of the chart
251 */
252 function set_title($title)
253 {
254 $this->title = $title;
255 }
256
257 // ###################################################################
258 /**
259 * Adds an entry to the data set without specifying a colour to add.
260 * This is the standard method as the colour should only be overridden
261 * if necessary.
262 *
263 * @access public
264 *
265 * @param string Data column name
266 * @param integer Percentage of 100
267 */
268 function add_data_set($name, $percent)
269 {
270 $this->dataset[] = array($name, intval($percent), $this->fetch_colour());
271 }
272
273 // ###################################################################
274 /**
275 * Adds an entry ot the data set with specifying a colour. This works
276 * the same as add_data_st() but requires an array() as the 3rd parameter
277 * of R,G,B values
278 *
279 * @access public
280 *
281 * @param string Data column name
282 * @param integer Percent of 100
283 * @param array Array of R,G,B values
284 */
285 function add_data_set_colour($name, $percent, $colour)
286 {
287 $this->dataset[] = array($name, intval($percent), imagecolorallocate($this->image, $colour[0], $colour[1], $colour[2]));
288 }
289
290 // ###################################################################
291 /**
292 * Fetches a colour from the allocated colour list and returns the value
293 *
294 * @access private
295 *
296 * @return integer Allocated colour resource
297 */
298 function fetch_colour()
299 {
300 static $colourlist = array(
301 array(100, 60, 175),
302 array(221, 110, 21),
303 array(179, 34, 31),
304 array(69, 196, 243),
305 array(128, 186, 33),
306 array(28, 101, 155),
307 array(246, 204, 95),
308 array(6, 43, 147),
309 array(204, 61, 7),
310 array(170, 169, 174),
311 array(90, 15, 24),
312 array(45, 130, 195)
313 );
314 static $allocated = 0;
315
316 $colour = $colourlist["$allocated"];
317 $allocated++;
318
319 return imagecolorallocate($this->image, $colour[0], $colour[1], $colour[2]);
320 }
321 }
322
323 /*=====================================================================*\
324 || ###################################################################
325 || # $HeadURL$
326 || # $Id$
327 || ###################################################################
328 \*=====================================================================*/
329 ?>