Enabled RTL text in Graphics Engine. Due to bug in imagettftext.
[fa-stable.git] / reporting / includes / class.graphic.inc
1 <?php
2 /**
3 *
4 *   graph
5 *   version 1.0
6 *
7 *
8 *
9 * Author: Carlos Reche/Joe Hunt
10 * E-mail: carlosreche@yahoo.com/joe.hunt.consulting@gmail.com
11 * Sorocaba, SP - Brazil/Wellington, New Zealand
12 *
13 * Created: Sep 20, 2004
14 * Last Modification: Sep 20, 2004/Apr 01, 2007
15 *
16 *
17 *
18 *  Authors' comments:
19 *
20 *  graph creates 6 different types of graphics with how many parameters you want. You can
21 *  change the appearance of the graphics in 3 different skins, and you can still cross data from 2 
22 *  graphics in only 1! It's a powerful script, and I recommend you read all the instructions 
23 *  to learn how to use all of this features. Don't worry, it's very simple to use it.
24 *
25 *  This script is free. Please keep the credits.
26 *
27 */
28
29 /**
30
31    INSTRUNCTIONS OF HOW TO USE THIS SCRIPT  (Please, take a minute to read it. It's important!)
32
33
34    NOTE: make sure that your PHP is compiled to work with GD Lib.
35
36 ///// START OF EXAMPLE.PHP /////
37
38 <?php
39
40 require "class.graphics.inc";
41 $pg = new graph;
42
43 $pg->title = "Sex";
44 $pg->type  = "5";
45 $pg->x[0]  = "male";
46 $pg->y[0]  = "50";
47 $pg->x[1]  = "female";
48 $pg->y[1]  = "55";
49 $pg->display();
50 ?>
51
52 In your html file you set it up as:
53 .....
54 <img src="example.php" border="1" />
55 .....
56
57 You can supply extra parameters to display(). Ex. $pg->display("test.png") will save the image to a file.
58 Ex. $pg->display("", true) will paint a border around the image. It might be suitable if you choose to save to
59 file for later presentation.
60
61 ///// END OF EXAMPLE.PHP /////
62
63
64
65    Here is a list of all parameters you may set:
66
67    title      =>  Title of the graphic
68    axis_x     =>  Name of values from Axis X
69    axis_y     =>  Name of values from Axis Y
70    graphic_1  =>  Name of Graphic_1 (only shown if you are gonna cross data from 2 different graphics)
71    graphic_2  =>  Name of Graphic_2 (same comment of above)
72
73    type  =>  Type of graphic (values 1 to 6)
74                 1 => Vertical bars (default)
75                 2 => Horizontal bars
76                 3 => Dots
77                 4 => Lines
78                 5 => Pie
79                 6 => Donut
80
81    skin   => Skin of the graphic (values 1 to 3)
82                 1 => Office (default)
83                 2 => Matrix
84                 3 => Spring
85
86    credits => Only if you want to show my credits in the image. :)
87                 0 => doesn't show (default)
88                 1 => shows
89
90    x[0]  =>  Name of the first parameter in Axis X
91    x[1]  =>  Name of the second parameter in Axis X
92    ... (etc)
93
94    y[0]  =>  Value from "graphic_1" relative for "x[0]"
95    y[1]  =>  Value from "graphic_1" relative for "x[1]"
96    ... (etc)
97
98    z[0]  =>  Value from "graphic_2" relative for "x[0]"
99    z[1]  =>  Value from "graphic_2" relative for "x[1]"
100    ... (etc)
101
102
103    NOTE: You can't cross data between graphics if you use "pie" or "donut" graphic. Values for "z"
104    won't be considerated.
105
106    That's all! Hope you make a good use of it!
107    It would be nice to receive feedback from others users. All comments are welcome!
108
109    Regards,
110
111    Carlos Reche
112
113 */
114
115 class graph 
116 {
117
118     var $x;
119     var $y;
120     var $z;
121
122     var $title;
123     var $axis_x;
124     var $axis_y;
125     var $graphic_1;
126     var $graphic_2;
127     var $type = 1;
128     var $skin = 1;
129     var $credits = 0;
130     var $latin_notation;
131
132     var $width;
133     var $height;
134     var $height_title;
135     var $alternate_x;
136
137         var $size = 2;
138         var $tsize = 5;
139
140     var $total_parameters;
141     var $sum_total;
142     var $biggest_value;
143     var $biggest_parameter;
144     var $available_types;
145     var $dec1 = 0;
146     var $dec2 = 0;
147     var $h3d = 15; // 3D height
148         var $built_in = false;
149         var $fontfile = "";
150         var $encoding;
151         
152     function graph()
153     {
154         global $UTF8_fontfile;
155                 $this->encoding = strtoupper($_SESSION['language']->encoding);
156                 $path = dirname(__FILE__).'/../fonts/';
157
158                 // If you use UTF-8 encoding you have to download and install FreeSans.ttf font.
159                 // It is not bundled with application due to its size.
160                 // You can also use another UTF-8 font and put it in config.php with the name in $UTF8_fontfile 
161                 $this->fontfile = $this->encoding == 'UTF-8' ? (isset($UTF8_fontfile) && $UTF8_fontfile != "" ? $path.$UTF8_fontfile : $path.'FreeSans.ttf') : 
162                         $path.'LiberationSans-Regular.ttf';
163                 
164         $this->x = $this->y = $this->z = array();
165         $this->biggest_x        = NULL;
166         $this->biggest_y        = NULL;
167         $this->alternate_x      = false;
168         $this->graphic_2_exists = false;
169         $this->total_parameters = 0;
170         $this->sum_total        = 1;
171                 $this->latin_notation   = false;
172     }
173
174
175     function display($save="", $border=false)
176     {
177         $this->legend_exists        = (preg_match("/(5|6)/", $this->type)) ? true : false;
178         $this->biggest_graphic_name = (strlen($this->graphic_1) > strlen($this->graphic_2)) ? $this->graphic_1 : $this->graphic_2;
179         $this->height_title         = (!empty($this->title)) ? ($this->string_height($this->tsize) + 15) : 0;
180         $this->space_between_bars   = ($this->type == 1) ? 40 : 30;
181         $this->space_between_dots   = 40;
182         $this->higher_value         = 0;
183         $this->higher_value_str     = 0;
184
185         $this->width               = 0;
186         $this->height              = 0;
187         $this->graphic_area_width  = 0;
188         $this->graphic_area_height = 0;
189         $this->graphic_area_x1     = 30;
190         $this->graphic_area_y1     = 20 + $this->height_title;
191         $this->graphic_area_x2     = $this->graphic_area_x1 + $this->graphic_area_width;
192         $this->graphic_area_y2     = $this->graphic_area_y1 + $this->graphic_area_height;
193
194                 if (count($this->z) && (preg_match("/(1|2|3|4)/", $this->type)))
195             $this->graphic_2_exists = true;
196         $this->total_parameters    = count($this->x);
197                 for ($i = 0; $i < $this->total_parameters; $i++)
198                 {
199                         if (strlen($this->x[$i]) > strlen($this->biggest_x))
200                 $this->biggest_x = $this->x[$i];
201                         if ($this->y[$i] > $this->biggest_y)
202                 $this->biggest_y = number_format(round($this->y[$i], 1), 1, ".", "");
203             if ($this->graphic_2_exists)    
204             {
205                 if (isset($this->z[$i]) && $this->z[$i] > $this->biggest_y)
206                         $this->biggest_y = number_format(round($this->z[$i], 1), 1, ".", "");
207             }           
208         }
209
210         if (($this->graphic_2_exists == true)  &&  ((!empty($this->graphic_1)) || (!empty($this->graphic_2))))
211         {
212             $this->legend_exists = true;
213         }
214
215         $this->sum_total           = array_sum($this->y);
216         if ($this->sum_total == 0)
217                 $this->sum_total = 1;
218         $this->space_between_bars += ($this->graphic_2_exists == true) ? 10 : 0;
219
220         $this->calculate_higher_value();
221         $this->calculate_width();
222         $this->calculate_height();
223
224         $this->create_graphic($save, $border);
225     }
226
227     function create_graphic($save="", $border=false)
228     {
229         $size = 3;
230         $this->img = imagecreatetruecolor($this->width, $this->height);
231
232         $this->load_color_palette();
233
234         // Fill background
235         imagefill($this->img, 0, 0, $this->color['background']);
236         //imagefilledrectangle($this->img, 0, 0, $this->width, $this->height, $this->color['background']);
237         //if ($border)
238         //      imagerectangle($this->img, 0, 0, $this->width-1, $this->height-1, imagecolorallocate($this->img, 100, 150, 200));
239
240         // Draw title
241         if (!empty($this->title))
242         {
243             $center = ($this->width / 2) - ($this->string_width($this->title, $this->tsize) / 2);
244             $this->_imagestring($this->img, $this->tsize, $center, 10, $this->title, $this->color['title']);
245         }
246
247
248         // Draw axis and background lines for "vertical bars", "dots" and "lines"
249         if (preg_match("/^(1|3|4)$/", $this->type))
250         {
251             if ($this->legend_exists == true)
252             {
253                 $this->draw_legend();
254             }
255
256             $higher_value_y    = $this->graphic_area_y1 + (0.1 * $this->graphic_area_height);
257             $higher_value_size = 0.9 * $this->graphic_area_height;
258
259             $less  = 7 * strlen($this->higher_value_str);
260
261             imageline($this->img, $this->graphic_area_x1, $higher_value_y, $this->graphic_area_x2, $higher_value_y, $this->color['bg_lines']);
262             $this->_imagestring($this->img, $this->size, ($this->graphic_area_x1-$less-7), ($higher_value_y-7), $this->higher_value_str, $this->color['axis_values']);
263
264             for ($i = 1; $i < 10; $i++)
265             {
266                 $dec_y = $i * ($higher_value_size / 10);
267                 $x1 = $this->graphic_area_x1;
268                 $y1 = $this->graphic_area_y2 - $dec_y;
269                 $x2 = $this->graphic_area_x2;
270                 $y2 = $this->graphic_area_y2 - $dec_y;
271
272                 imageline($this->img, $x1, $y1, $x2, $y2, $this->color['bg_lines']);
273                 if ($i % 2 == 0) 
274                 {
275                     $value = $this->number_formated($this->higher_value * $i / 10, $this->dec1);
276                     $len1 = strlen($this->higher_value_str);
277                     $len2 = strlen($value);
278                     if ($len2 < $len1)
279                         $len2 += ($len1-$len2-1);
280                     $less = 7 * $len2;
281                     //$this->_imagestring($this->img, $this->size, ($x1-$less-7), ($y2-7), $value, $this->color['axis_values']);
282                     $this->_imagestring($this->img, $this->size, ($x1-$less-7), ($y2-7), $value, $this->color['axis_values']);
283                 }
284             }
285
286             // Axis X
287             $this->_imagestring($this->img, $this->size, $this->graphic_area_x2+10, $this->graphic_area_y2+3, $this->axis_x, $this->color['title']);
288             imageline($this->img, $this->graphic_area_x1, $this->graphic_area_y2, $this->graphic_area_x2, $this->graphic_area_y2, $this->color['axis_line']);
289             // Axis Y
290             $this->_imagestring($this->img, $this->size, 20, $this->graphic_area_y1-20, $this->axis_y, $this->color['title']);
291             imageline($this->img, $this->graphic_area_x1, $this->graphic_area_y1, $this->graphic_area_x1, $this->graphic_area_y2, $this->color['axis_line']);
292         }
293
294
295         // Draw axis and background lines for "horizontal bars"
296         else if ($this->type == 2)
297         {
298             if ($this->legend_exists == true)
299             {
300                 $this->draw_legend();
301             }
302
303             $higher_value_x    = $this->graphic_area_x2 - (0.2 * $this->graphic_area_width);
304             $higher_value_size = 0.8 * $this->graphic_area_width;
305
306             imageline($this->img, ($this->graphic_area_x1+$higher_value_size), $this->graphic_area_y1, ($this->graphic_area_x1+$higher_value_size), $this->graphic_area_y2, $this->color['bg_lines']);
307             $this->_imagestring($this->img, $this->size, (($this->graphic_area_x1+$higher_value_size) - ($this->string_width($this->higher_value, $this->size)/2)), ($this->graphic_area_y2+2), $this->higher_value_str, $this->color['axis_values']);
308
309             for ($i = 1, $alt = 15; $i < 10; $i++)
310             {
311                 $dec_x = number_format(round($i * ($higher_value_size  / 10), 1), 1, ".", "");
312
313                 imageline($this->img, ($this->graphic_area_x1+$dec_x), $this->graphic_area_y1, ($this->graphic_area_x1+$dec_x), $this->graphic_area_y2, $this->color['bg_lines']);
314                 if ($i % 2 == 0) 
315                 {
316                     $alt   = (strlen($this->biggest_y) > 4 && $alt != 15) ? 15 : 2;
317                     $value = $this->number_formated($this->higher_value * $i / 10, $this->dec1);
318                     $this->_imagestring($this->img, $this->size, (($this->graphic_area_x1+$dec_x) - ($this->string_width($this->higher_value, $this->size)/2)), ($this->graphic_area_y2), $value, $this->color['axis_values'], $alt);
319                 }
320             }
321
322             // Axis X
323             $this->_imagestring($this->img, $this->size, ($this->graphic_area_x2+10), ($this->graphic_area_y2+3), $this->axis_y, $this->color['title']);
324             imageline($this->img, $this->graphic_area_x1, $this->graphic_area_y2, $this->graphic_area_x2, $this->graphic_area_y2, $this->color['axis_line']);
325             // Axis Y
326             $this->_imagestring($this->img, $this->size, 20, ($this->graphic_area_y1-20), $this->axis_x, $this->color['title']);
327             imageline($this->img, $this->graphic_area_x1, $this->graphic_area_y1, $this->graphic_area_x1, $this->graphic_area_y2, $this->color['axis_line']);
328         }
329
330
331         // Draw legend box for "pie" or "donut"
332         else if (preg_match("/^(5|6)$/", $this->type))
333         {
334             $this->draw_legend();
335         }
336
337
338
339         /**
340         * Draw graphic: VERTICAL BARS
341         */
342         if ($this->type == 1)
343         {
344             $num = 1;
345             $x   = $this->graphic_area_x1 + 20;
346
347             foreach ($this->x as $i => $parameter)
348             {
349                 if (isset($this->z[$i])) 
350                 {
351                     $size = round($this->z[$i] * $higher_value_size / $this->higher_value);
352                     $x1   = $x + 10;
353                     $y1   = ($this->graphic_area_y2 - $size) + 1;
354                     $x2   = $x1 + 20;
355                     $y2   = $this->graphic_area_y2 - 1;
356                     imageline($this->img, ($x1+1), ($y1-1), $x2, ($y1-1), $this->color['bars_2_shadow']);
357                     imageline($this->img, ($x2+1), ($y1-1), ($x2+1), $y2, $this->color['bars_2_shadow']);
358                     imageline($this->img, ($x2+2), ($y1-1), ($x2+2), $y2, $this->color['bars_2_shadow']);
359                     imagefilledrectangle($this->img, $x1, $y1, $x2, $y2, $this->color['bars_2']);
360                 }
361
362                 $size = round($this->y[$i] * $higher_value_size / $this->higher_value);
363                 $alt  = (($num % 2 == 0) && (strlen($this->biggest_x) > 5)) ? 15 : 2;
364                 $x1   = $x;
365                 $y1   = ($this->graphic_area_y2 - $size) + 1;
366                 $x2   = $x1 + 20;
367                 $y2   = $this->graphic_area_y2 - 1;
368                 $x   += $this->space_between_bars;
369                 $num++;
370
371                 imageline($this->img, ($x1+1), ($y1-1), $x2, ($y1-1), $this->color['bars_shadow']);
372                 imageline($this->img, ($x2+1), ($y1-1), ($x2+1), $y2, $this->color['bars_shadow']);
373                 imageline($this->img, ($x2+2), ($y1-1), ($x2+2), $y2, $this->color['bars_shadow']);
374                 imagefilledrectangle($this->img, $x1, $y1, $x2, $y2, $this->color['bars']);
375                 $this->_imagestring($this->img, $this->size, ((($x1+$x2)/2) - (strlen($parameter)*7/2)), ($y2+2), $parameter, $this->color['axis_values'], $alt);
376             }
377         }
378
379
380         /**
381         * Draw graphic: HORIZONTAL BARS
382         */
383         else if ($this->type == 2)
384         {
385             $y = 10;
386
387             foreach ($this->x as $i => $parameter)
388             {
389                 if (isset($this->z[$i])) 
390                 {
391                     $size = round($this->z[$i] * $higher_value_size / $this->higher_value);
392                     $x1   = $this->graphic_area_x1 + 1;
393                     $y1   = $this->graphic_area_y1 + $y + 10;
394                     $x2   = $x1 + $size;
395                     $y2   = $y1 + 15;
396                     imageline($this->img, ($x1), ($y2+1), $x2, ($y2+1), $this->color['bars_2_shadow']);
397                     imageline($this->img, ($x1), ($y2+2), $x2, ($y2+2), $this->color['bars_2_shadow']);
398                     imageline($this->img, ($x2+1), ($y1+1), ($x2+1), ($y2+2), $this->color['bars_2_shadow']);
399                     imagefilledrectangle($this->img, $x1, $y1, $x2, $y2, $this->color['bars_2']);
400                     $this->_imagestring($this->img, $this->size, ($x2+7), ($y1+7), $this->number_formated($this->z[$i], $this->dec2), $this->color['bars_2_shadow']);
401                 }
402
403                 $size = round(($this->y[$i] / $this->higher_value) * $higher_value_size);
404                 $x1   = $this->graphic_area_x1 + 1;
405                 $y1   = $this->graphic_area_y1 + $y;
406                 $x2   = $x1 + $size;
407                 $y2   = $y1 + 15;
408                 $y   += $this->space_between_bars;
409
410                 imageline($this->img, ($x1), ($y2+1), $x2, ($y2+1), $this->color['bars_shadow']);
411                 imageline($this->img, ($x1), ($y2+2), $x2, ($y2+2), $this->color['bars_shadow']);
412                 imageline($this->img, ($x2+1), ($y1+1), ($x2+1), ($y2+2), $this->color['bars_shadow']);
413                 imagefilledrectangle($this->img, $x1, $y1, $x2, $y2, $this->color['bars']);
414                 $this->_imagestring($this->img, $this->size, ($x2+7), ($y1+2), $this->number_formated($this->y[$i], $this->dec2), $this->color['bars_shadow']);
415
416                 //$this->_imagestring($this->img, $this->size, ($x1 - ((strlen($parameter)*7)+7)), ($y1+2), $parameter, $this->color['axis_values']);
417                 $this->_imagestring($this->img, $this->size, 30, ($y1+2), $parameter, $this->color['axis_values']);
418             }
419         }
420
421
422         /**
423         * Draw graphic: DOTS or LINE
424         */
425         else if (preg_match("/^(3|4)$/", $this->type))
426         {
427
428             $x[0] = $this->graphic_area_x1+1;
429
430             foreach ($this->x as $i => $parameter)
431             {
432                 if ($this->graphic_2_exists == true) 
433                 {
434                     $size  = round($this->z[$i] * $higher_value_size / $this->higher_value);
435                     $z[$i] = $this->graphic_area_y2 - $size;
436                 }
437
438                 $alt   = (($i % 2 == 0) && (strlen($this->biggest_x) > 5)) ? 15 : 2;
439                 $size  = round($this->y[$i] * $higher_value_size / $this->higher_value);
440                 $y[$i] = $this->graphic_area_y2 - $size;
441
442                 if ($i != 0) 
443                 {
444                     imageline($this->img, $x[$i], ($this->graphic_area_y1+10), $x[$i], ($this->graphic_area_y2-1), $this->color['bg_lines']);
445                 }
446                 $this->_imagestring($this->img, $this->size, ($x[$i] - (strlen($parameter)*7/2 )), ($this->graphic_area_y2+2), $parameter, $this->color['axis_values'], $alt);
447
448                 $x[$i+1] = $x[$i] + 40;
449             }
450
451             foreach ($x as $i => $value_x)
452             {
453                 if ($this->graphic_2_exists == true)
454                 {
455                     if (isset($z[$i+1])) 
456                     {
457                         // Draw lines
458                         if ($this->type == 4)
459                         {
460                             imageline($this->img, $x[$i], $z[$i], $x[$i+1], $z[$i+1], $this->color['line_2']);
461                             imageline($this->img, $x[$i], ($z[$i]+1), $x[$i+1], ($z[$i+1]+1), $this->color['line_2']);
462                         }
463                         imagefilledrectangle($this->img, $x[$i]-1, $z[$i]-1, $x[$i]+2, $z[$i]+2, $this->color['line_2']);
464                     }
465                     else 
466                     { // Draw last dot
467                         imagefilledrectangle($this->img, $x[$i-1]-1, $z[$i-1]-1, $x[$i-1]+2, $z[$i-1]+2, $this->color['line_2']);
468                     }
469                 }
470
471                 if (count($y) > 1)
472                 {
473                     if (isset($y[$i+1])) 
474                     {
475                         // Draw lines
476                         if ($this->type == 4)
477                         {
478                             imageline($this->img, $x[$i], $y[$i], $x[$i+1], $y[$i+1], $this->color['line']);
479                             imageline($this->img, $x[$i], ($y[$i]+1), $x[$i+1], ($y[$i+1]+1), $this->color['line']);
480                         }
481                         imagefilledrectangle($this->img, $x[$i]-1, $y[$i]-1, $x[$i]+2, $y[$i]+2, $this->color['line']);
482                     }
483                     else 
484                     { // Draw last dot
485                         imagefilledrectangle($this->img, $x[$i-1]-1, $y[$i-1]-1, $x[$i-1]+2, $y[$i-1]+2, $this->color['line']);
486                     }
487                 }
488
489             }
490         }
491
492
493         /**
494         * Draw graphic: PIE or DONUT
495         */
496         else if (preg_match("/^(5|6)$/", $this->type))
497         {
498             $center_x = ($this->graphic_area_x1 + $this->graphic_area_x2) / 2;
499             $center_y = ($this->graphic_area_y1 + $this->graphic_area_y2) / 2;
500             $width    = $this->graphic_area_width;
501             $height   = $this->graphic_area_height;
502             $start    = 0;
503             $sizes    = array();
504
505             foreach ($this->x as $i => $parameter)
506             {
507                 $size    = $this->y[$i] * 360 / $this->sum_total;
508                                 $size = round2($size, 0);
509                 $sizes[] = $size;
510                 $start  += $size;
511             }
512             $start = 270;
513
514             // Draw PIE
515             if ($this->type == 5)
516             {
517                 // Draw shadow
518                 foreach ($sizes as $i => $size)
519                 {
520                     $num_color = $i + 1;
521                     while ($num_color > 7) 
522                     {
523                         $num_color -= 5;
524                     }
525                     $color = 'arc_' . $num_color . '_shadow';
526
527                     for ($i = $this->h3d; $i >= 0; $i--)
528                     {
529                         //imagearc($this->img, $center_x, ($center_y+$i), $width, $height, $start, ($start+$size), $this->color[$color]);
530                         if ($size >= 1)
531                                 imagefilledarc($this->img, $center_x, ($center_y+$i), $width, $height, $start, ($start+$size), $this->color[$color], IMG_ARC_NOFILL);
532                     }
533                     $start += $size;
534                 }
535
536                 $start = 270;
537
538                 // Draw pieces
539                 foreach ($sizes as $i => $size)
540                 {
541                     $num_color = $i + 1;
542                     while ($num_color > 7) 
543                     {
544                         $num_color -= 5;
545                     }
546                     $color = 'arc_' . $num_color;
547                     if ($size >= 1)
548                         imagefilledarc($this->img, $center_x, $center_y, ($width+2), ($height+2), $start, ($start+$size), $this->color[$color], IMG_ARC_EDGED);
549                     $start += $size;
550                 }
551             }
552
553             // Draw DONUT
554             else if ($this->type == 6)
555             {
556                 foreach ($sizes as $i => $size)
557                 {
558                     $num_color = $i + 1;
559                     while ($num_color > 7) 
560                     {
561                         $num_color -= 5;
562                     }
563                     $color        = 'arc_' . $num_color;
564                     $color_shadow = 'arc_' . $num_color . '_shadow';
565                     if ($size >= 1)
566                         imagefilledarc($this->img, $center_x, $center_y, $width, $height, $start, ($start+$size), $this->color[$color], IMG_ARC_PIE);
567                     $start += $size;
568                 }
569                 imagefilledarc($this->img, $center_x, $center_y, 100, 100, 0, 360, $this->color['background'], IMG_ARC_PIE);
570                 imagearc($this->img, $center_x, $center_y, 100, 100, 0, 360, $this->color['bg_legend']);
571                 imagearc($this->img, $center_x, $center_y, ($width+1), ($height+1), 0, 360, $this->color['bg_legend']);
572             }
573         }
574
575
576         if ($this->credits == true) 
577         {
578             $this->draw_credits();
579         }
580                 if ($save != "")
581                         imagepng($this->img, $save);
582                 else
583                 {
584                 header('Content-type: image/png');
585                 imagepng($this->img);
586         }       
587         imagedestroy($this->img);
588     }
589
590     function calculate_width()
591     {
592         switch ($this->type)
593         {
594             // Vertical bars
595             case 1:
596                 $this->legend_box_width   = ($this->legend_exists == true) ? ($this->string_width($this->biggest_graphic_name, $this->tsize) + 25) : 0;
597                 $this->graphic_area_width = ($this->space_between_bars * $this->total_parameters) + 30;
598                 $this->graphic_area_x1   += $this->string_width(($this->higher_value_str), $this->size);
599                 $this->width += $this->graphic_area_x1 + 20;
600                 $this->width += ($this->legend_exists == true) ? 50 : ((7 * strlen($this->axis_x)) + 10);
601                 break;
602
603             // Horizontal bars
604             case 2:
605                 $this->legend_box_width   = ($this->legend_exists == true) ? ($this->string_width($this->biggest_graphic_name, $this->size) + 25) : 0;
606                 $this->graphic_area_width = ($this->string_width($this->higher_value_str, $this->size) > 50) ? (5 * ($this->string_width($this->higher_value_str, $this->size)) * 0.85) : 200;
607                 $this->graphic_area_x1 += 7 * strlen($this->biggest_x);
608                 $this->width += ($this->legend_exists == true) ? 60 : ((7 * strlen($this->axis_y)) + 30);
609                 $this->width += $this->graphic_area_x1;
610                 break;
611
612             // Dots
613             case 3:
614                 $this->legend_box_width   = ($this->legend_exists == true) ? ($this->string_width($this->biggest_graphic_name, $this->size) + 25) : 0;
615                 $this->graphic_area_width = ($this->space_between_dots * $this->total_parameters) - 10;
616                 $this->graphic_area_x1   += $this->string_width(($this->higher_value_str), $this->size);
617                 $this->width += $this->graphic_area_x1 + 20;
618                 $this->width += ($this->legend_exists == true) ? 40 : ((7 * strlen($this->axis_x)) + 30);
619                 break;
620
621             // Lines
622             case 4:
623                 $this->legend_box_width   = ($this->legend_exists == true) ? ($this->string_width($this->biggest_graphic_name, $this->size) + 25) : 0;
624                 $this->graphic_area_width = ($this->space_between_dots * $this->total_parameters) - 10;
625                 $this->graphic_area_x1   += $this->string_width(($this->higher_value_str), $this->size);
626                 $this->width += $this->graphic_area_x1 + 20;
627                 $this->width += ($this->legend_exists == true) ? 40 : ((7 * strlen($this->axis_x)) + 30);
628                 break;
629
630             // Pie
631             case 5:
632                 $this->legend_box_width   = $this->string_width($this->biggest_x, $this->size) + 85;
633                 $this->graphic_area_width = 200;
634                 $this->width += 90;
635                 break;
636
637             // Donut
638             case 6:
639                 $this->legend_box_width   = $this->string_width($this->biggest_x, $this->size) + 85;
640                 $this->graphic_area_width = 180;
641                 $this->width += 90;
642                 break;
643         }
644
645         $this->graphic_area_width = max($this->graphic_area_width, $this->string_width($this->title, $this->size));
646         $this->width += $this->graphic_area_width;
647         $this->width += $this->legend_box_width;
648
649
650         $this->graphic_area_x2 = $this->graphic_area_x1 + $this->graphic_area_width;
651         $this->legend_box_x1   = $this->graphic_area_x2 + 40;
652         $this->legend_box_x2   = $this->legend_box_x1 + $this->legend_box_width;
653     }
654
655     function calculate_height()
656     {
657         switch ($this->type)
658         {
659             // Vertical bars
660             case 1:
661                 $this->legend_box_height   = ($this->graphic_2_exists == true) ? 40 : 0;
662                 $this->graphic_area_height = 150;
663                 $this->height += 65;
664                 break;
665
666             // Horizontal bars
667             case 2:
668                 $this->legend_box_height   = ($this->graphic_2_exists == true) ? 40 : 0;
669                 $this->graphic_area_height = ($this->space_between_bars * $this->total_parameters) + 10;
670                 $this->height += 65;
671                 break;
672
673             // Dots
674             case 3:
675                 $this->legend_box_height   = ($this->graphic_2_exists == true) ? 40 : 0;
676                 $this->graphic_area_height = 150;
677                 $this->height += 65;
678                 break;
679
680             // Lines
681             case 4:
682                 $this->legend_box_height   = ($this->graphic_2_exists == true) ? 40 : 0;
683                 $this->graphic_area_height = 150;
684                 $this->height += 65;
685                 break;
686
687             // Pie
688             case 5:
689                 $this->legend_box_height   = (!empty($this->axis_x)) ? 30 : 5;
690                 $this->legend_box_height  += (14 * $this->total_parameters);
691                 $this->graphic_area_height = 150;
692                 $this->height += 50;
693                 break;
694
695             // Donut
696             case 6:
697                 $this->legend_box_height   = (!empty($this->axis_x)) ? 30 : 5;
698                 $this->legend_box_height  += (14 * $this->total_parameters);
699                 $this->graphic_area_height = 180;
700                 $this->height += 50;
701                 break;
702         }
703
704         $this->height += $this->height_title;
705         $this->height += ($this->legend_box_height > $this->graphic_area_height) ? ($this->legend_box_height - $this->graphic_area_height) : 0;
706         $this->height += $this->graphic_area_height;
707
708         $this->graphic_area_y2 = $this->graphic_area_y1 + $this->graphic_area_height;
709         $this->legend_box_y1   = $this->graphic_area_y1 + 10;
710         $this->legend_box_y2   = $this->legend_box_y1 + $this->legend_box_height;
711     }
712
713     function draw_legend()
714     {
715         $x1 = $this->legend_box_x1;
716         $y1 = $this->legend_box_y1;
717         $x2 = $this->legend_box_x2;
718         $y2 = $this->legend_box_y2;
719
720         imagefilledrectangle($this->img, $x1, $y1, $x2, $y2, $this->color['bg_legend']);
721
722         $x = $x1 + 5;
723         $y = $y1 + 5;
724
725
726         // Draw legend values for VERTICAL BARS, HORIZONTAL BARS, DOTS and LINES
727         if (preg_match("/^(1|2|3|4)$/", $this->type))
728         {
729             $color_1 = (preg_match("/^(1|2)$/", $this->type)) ? $this->color['bars']   : $this->color['line'];
730             $color_2 = (preg_match("/^(1|2)$/", $this->type)) ? $this->color['bars_2'] : $this->color['line_2'];
731
732             imagefilledrectangle($this->img, $x, $y, ($x+10), ($y+10), $color_1);
733             imagerectangle($this->img, $x, $y, ($x+10), ($y+10), $this->color['title']);
734             $this->_imagestring($this->img, $this->size, ($x+15), ($y-2), $this->graphic_1, $this->color['axis_values']);
735             $y += 20;
736             imagefilledrectangle($this->img, $x, $y, ($x+10), ($y+10), $color_2);
737             imagerectangle($this->img, $x, $y, ($x+10), ($y+10), $this->color['title']);
738             $this->_imagestring($this->img, $this->size, ($x+15), ($y-2), $this->graphic_2, $this->color['axis_values']);
739         }
740
741         // Draw legend values for PIE or DONUT
742         else if (preg_match("/^(5|6)$/", $this->type))
743         {
744             if (!empty($this->axis_x))
745             {
746                 $this->_imagestring($this->img, $this->size, ((($x1+$x2)/2) - (strlen($this->axis_x)*7/2)), $y, 
747                         $this->axis_x." (".$this->graphic_1.")", $this->color['title']);
748                 $y += 25;
749             }
750
751             $num = 1;
752
753             foreach ($this->x as $i => $parameter)
754             {
755                 while ($num > 7) 
756                 {
757                     $num -= 5;
758                 }
759                 $color = 'arc_' . $num;
760
761                 $percent = number_format(round(($this->y[$i] * 100 / $this->sum_total), 2), 2, ".", "") . ' %';
762                 $less    = (strlen($percent) * 7);
763
764                 if ($num != 1) 
765                 {
766                     imageline($this->img, ($x1+15), ($y-2), ($x2-5), ($y-2), $this->color['bg_lines']);
767                 }
768                 imagefilledrectangle($this->img, $x, $y, ($x+10), ($y+10), $this->color[$color]);
769                 imagerectangle($this->img, $x, $y, ($x+10), ($y+10), $this->color['title']);
770                 $this->_imagestring($this->img, $this->size, ($x+15), ($y-2), $parameter, $this->color['axis_values']);
771                 $this->_imagestring($this->img, $this->size, ($x2-$less), ($y-2), $percent, $this->color['axis_values']);
772                 $y += 14;
773                 $num++;
774             }
775         }
776     }
777
778
779     function string_width($string, $size) 
780     {
781         $single_width = $size + 4;
782         if ($this->encoding == "UTF-8")
783                 $width = mb_strlen($string, "UTF-8");
784         else    
785                 $width = strlen($string);
786         return $single_width * $width;
787     }
788
789     function string_height($size) 
790     {
791         if ($size <= 1) 
792         {
793             $height = 8;
794         } 
795         else if ($size <= 3) 
796         {
797             $height = 12;
798         } 
799         else if ($size >= 4) 
800         {
801             $height = 14;
802         }
803         return $height;
804     }
805
806     function calculate_higher_value() 
807     {
808         $digits   = strlen(round($this->biggest_y));
809         $interval = pow(10, ($digits-1));
810         $this->higher_value     = round(($this->biggest_y - ($this->biggest_y % $interval) + $interval), 1);
811         $this->higher_value_str = $this->number_formated($this->higher_value, $this->dec1);
812     }
813
814     function number_formated($number, $dec_size = 1)
815     {
816         if ($this->latin_notation == true) 
817             return number_format(round($number, $dec_size), $dec_size, ",", ".");
818         return number_format(round($number, $dec_size), $dec_size, ".", ",");
819     }
820
821     function number_float($number)
822     {
823         if ($this->latin_notation == true) 
824             $number = str_replace(".", "", $number);
825         return (float)str_replace(",", "", $number);
826     }
827
828
829     function draw_credits() 
830     {
831         $this->_imagestring($this->img, $this->size - 2, ($this->width-120), ($this->height-10), "Powered by Carlos Reche", $this->color['title']);
832     }
833
834
835     function load_color_palette()
836     {
837         switch ($this->skin)
838         {
839             // Office
840             case 1:
841                 //$this->color['title']       = imagecolorallocate($this->img,  50,  50,  50);
842                 $this->color['title']       = imagecolorallocate($this->img,  40,  70,  130);
843                 //$this->color['background']  = imagecolorallocate($this->img, 238, 255, 238);
844                 $this->color['background']  = imagecolorallocate($this->img, 255, 255, 255);
845                 $this->color['axis_values'] = imagecolorallocate($this->img,  50,  50,  50);
846                 $this->color['axis_line']   = imagecolorallocate($this->img, 100, 100, 100);
847                 $this->color['bg_lines']    = imagecolorallocate($this->img, 220, 220, 220);
848                 $this->color['bg_legend']   = imagecolorallocate($this->img, 255, 255, 255);
849
850                 if (preg_match("/^(1|2)$/", $this->type))
851                 {
852                     $this->color['bars']          = imagecolorallocate($this->img, 100, 150, 200);
853                     $this->color['bars_shadow']   = imagecolorallocate($this->img,  50, 100, 150);
854                     $this->color['bars_2']        = imagecolorallocate($this->img, 200, 250, 150);
855                     $this->color['bars_2_shadow'] = imagecolorallocate($this->img, 120, 170,  70);
856                 }
857                 else if (preg_match("/^(3|4)$/", $this->type))
858                 {
859                     $this->color['line']   = imagecolorallocate($this->img, 100, 150, 200);
860                     $this->color['line_2'] = imagecolorallocate($this->img, 230, 100, 100);
861                 }
862                 else if (preg_match("/^(5|6)$/", $this->type))
863                 {
864                     $this->color['arc_1']        = imagecolorallocate($this->img, 255, 150,   0);
865                     $this->color['arc_2']        = imagecolorallocate($this->img, 150,   0, 255);
866                     $this->color['arc_3']        = imagecolorallocate($this->img,   0, 255, 255);
867                     $this->color['arc_4']        = imagecolorallocate($this->img, 255,   0,   0);
868                     $this->color['arc_5']        = imagecolorallocate($this->img,   0, 255,   0);
869                     $this->color['arc_6']        = imagecolorallocate($this->img,   0,   0, 255);
870                     $this->color['arc_7']        = imagecolorallocate($this->img, 255, 255,   0);
871                     $this->color['arc_1_shadow'] = imagecolorallocate($this->img, 127,  75,   0);
872                     $this->color['arc_2_shadow'] = imagecolorallocate($this->img,  75,   0, 127);
873                     $this->color['arc_3_shadow'] = imagecolorallocate($this->img,   0, 127, 127);
874                     $this->color['arc_4_shadow'] = imagecolorallocate($this->img, 127,   0,   0);
875                     $this->color['arc_5_shadow'] = imagecolorallocate($this->img,   0, 127,   0);
876                     $this->color['arc_6_shadow'] = imagecolorallocate($this->img,   0,   0, 127);
877                     $this->color['arc_7_shadow'] = imagecolorallocate($this->img, 127, 127,   0);
878                 }
879                 break;
880
881             // Matrix
882             case 2:
883                 $this->color['title']       = imagecolorallocate($this->img, 255, 255, 255);
884                 $this->color['background']  = imagecolorallocate($this->img,   0,   0,   0);
885                 $this->color['axis_values'] = imagecolorallocate($this->img,   0, 230,   0);
886                 $this->color['axis_line']   = imagecolorallocate($this->img,   0, 200,   0);
887                 $this->color['bg_lines']    = imagecolorallocate($this->img, 100, 100, 100);
888                 $this->color['bg_legend']   = imagecolorallocate($this->img,  70,  70,  70);
889
890                 if (preg_match("/^(1|2)$/", $this->type))
891                 {
892                     $this->color['bars']          = imagecolorallocate($this->img,  50, 200,  50);
893                     $this->color['bars_shadow']   = imagecolorallocate($this->img,   0, 150,   0);
894                     $this->color['bars_2']        = imagecolorallocate($this->img, 255, 255, 255);
895                     $this->color['bars_2_shadow'] = imagecolorallocate($this->img, 220, 220, 220);
896                 }
897                 else if (preg_match("/^(3|4)$/", $this->type))
898                 {
899                     $this->color['line']   = imagecolorallocate($this->img, 220, 220, 220);
900                     $this->color['line_2'] = imagecolorallocate($this->img,   0, 180,   0);
901                 }
902                 else if (preg_match("/^(5|6)$/", $this->type))
903                 {
904                     $this->color['arc_1']        = imagecolorallocate($this->img, 255, 255, 255);
905                     $this->color['arc_2']        = imagecolorallocate($this->img, 200, 220, 200);
906                     $this->color['arc_3']        = imagecolorallocate($this->img, 160, 200, 160);
907                     $this->color['arc_4']        = imagecolorallocate($this->img, 135, 180, 135);
908                     $this->color['arc_5']        = imagecolorallocate($this->img, 115, 160, 115);
909                     $this->color['arc_6']        = imagecolorallocate($this->img, 100, 140, 100);
910                     $this->color['arc_7']        = imagecolorallocate($this->img,  90, 120,  90);
911                     $this->color['arc_1_shadow'] = imagecolorallocate($this->img, 127, 127, 127);
912                     $this->color['arc_2_shadow'] = imagecolorallocate($this->img, 100, 110, 100);
913                     $this->color['arc_3_shadow'] = imagecolorallocate($this->img,  80, 100,  80);
914                     $this->color['arc_4_shadow'] = imagecolorallocate($this->img,  67,  90,  67);
915                     $this->color['arc_5_shadow'] = imagecolorallocate($this->img,  57,  80,  57);
916                     $this->color['arc_6_shadow'] = imagecolorallocate($this->img,  50,  70,  50);
917                     $this->color['arc_7_shadow'] = imagecolorallocate($this->img,  45,  60,  45);
918                 }
919                 break;
920
921
922             // Spring
923             case 3:
924                 $this->color['title']       = imagecolorallocate($this->img, 250,  50,  50);
925                 //$this->color['background']  = imagecolorallocate($this->img, 250, 250, 220);
926                 $this->color['background']  = imagecolorallocate($this->img, 255, 255, 255);
927                 $this->color['axis_values'] = imagecolorallocate($this->img,  50, 150,  50);
928                 $this->color['axis_line']   = imagecolorallocate($this->img,  50, 100,  50);
929                 $this->color['bg_lines']    = imagecolorallocate($this->img, 200, 224, 180);
930                 //$this->color['bg_legend']   = imagecolorallocate($this->img, 230, 230, 200);
931                 $this->color['bg_legend']   = imagecolorallocate($this->img, 255, 255, 255);
932
933                 if (preg_match("/^(1|2)$/", $this->type))
934                 {
935                     $this->color['bars']          = imagecolorallocate($this->img, 255, 170,  80);
936                     $this->color['bars_shadow']   = imagecolorallocate($this->img, 200, 120,  30);
937                     $this->color['bars_2']        = imagecolorallocate($this->img, 250, 230,  80);
938                     $this->color['bars_2_shadow'] = imagecolorallocate($this->img, 180, 150,   0);
939                 }
940                 else if (preg_match("/^(3|4)$/", $this->type))
941                 {
942                     $this->color['line']   = imagecolorallocate($this->img, 230, 100,   0);
943                     $this->color['line_2'] = imagecolorallocate($this->img, 220, 200,  50);
944                 }
945                 else if (preg_match("/^(5|6)$/", $this->type))
946                 {
947                     $this->color['arc_1']        = imagecolorallocate($this->img, 100, 150, 200);
948                     $this->color['arc_2']        = imagecolorallocate($this->img, 200, 250, 150);
949                     $this->color['arc_3']        = imagecolorallocate($this->img, 250, 200, 150);
950                     $this->color['arc_4']        = imagecolorallocate($this->img, 250, 150, 150);
951                     $this->color['arc_5']        = imagecolorallocate($this->img, 250, 250, 150);
952                     $this->color['arc_6']        = imagecolorallocate($this->img, 230, 180, 250);
953                     $this->color['arc_7']        = imagecolorallocate($this->img, 200, 200, 150);
954                     $this->color['arc_1_shadow'] = imagecolorallocate($this->img,  50,  75, 100);
955                     $this->color['arc_2_shadow'] = imagecolorallocate($this->img, 100, 125,  75);
956                     $this->color['arc_3_shadow'] = imagecolorallocate($this->img, 125, 100,  75);
957                     $this->color['arc_4_shadow'] = imagecolorallocate($this->img, 125,  75,  75);
958                     $this->color['arc_5_shadow'] = imagecolorallocate($this->img, 125, 125,  75);
959                     $this->color['arc_6_shadow'] = imagecolorallocate($this->img, 115,  90, 125);
960                     $this->color['arc_7_shadow'] = imagecolorallocate($this->img, 100, 100,  75);
961                 }
962                 break;
963
964         }
965     }
966
967     function _imagestring($img, $size, $x, $y, $string, $col, $alt=0)
968     {
969         if ($alt && mb_strlen($string) > 12)
970                         $string = mb_substr($string, 0, 12);
971
972                 if ($this->encoding != 'UTF-8') {
973                         if (function_exists('iconv'))
974                                 $string = iconv($this->encoding, 'UTF-8', $string);
975                         else
976                                 $string = mb_convert_encoding($string, 'UTF-8', $this->encoding);
977                 }
978                 
979                 // New 2014-06-26 Joe Hunt for handling ev. RTL languages
980                 if ($this->encoding == 'UTF-8')
981                 {
982                         if (is_arabic($string))
983                                 $string = arabic($string, "we");
984                         elseif (is_hebrew($string))
985                                 $string = hebrew($string);
986                 }
987
988         if ($this->built_in)
989         {
990                 imagestring($img, $size, $x, $y + $alt, $string, $col);
991         }       
992         else    
993         {
994                 if ($size == 1)
995                         $size = 7;
996                 elseif ($size == 2)
997                         $size = 8;
998                 elseif ($size == 3)
999                         $size = 9;
1000                 elseif ($size == 4)
1001                         $size = 11;
1002                 else
1003                         $size = 12;
1004                 $y += $size + 3;        
1005                 //if ($alt)
1006                 //      $angle = -15;
1007                 //else
1008                                 $angle = 0;
1009                         
1010                         imagettftext($img, $size, $angle, $x, $y + $alt, $col, $this->fontfile, $string);
1011         }
1012     }   
1013 }
1014
1015 // The following is for handling RTL texts. GD does not handle RTL at all.
1016 // The function, arabic, has been taken from Milad Rastian and
1017 // modified by Bagram Siadat.
1018 // The function has been further modified and several bugs are fixed.
1019
1020 function is_arabic($text)
1021 {
1022         return preg_match('/\p{Arabic}/u', $text);
1023
1024
1025 function is_hebrew($text)
1026 {
1027         return preg_match('/\p{Hebrew}/u', $text);
1028
1029
1030 function utf8_strlen($str) 
1031 {
1032         return preg_match_all('/[\x00-\x7F\xC0-\xFD]/', $str, $dummy);
1033 }
1034
1035 function utf8_chr($uni) 
1036 {
1037         $r = "";
1038     # ASCII range (including control chars)
1039     if ( ($uni >= 0) && ($uni <= 0x007f) ) 
1040             $r .= chr($uni);
1041         elseif ($uni <= 0x07ff) // 2 byte sequence
1042         {
1043                 $r .= chr(0xc0 | ($uni >> 6));
1044                 $r .= chr(0x80 | ($uni & 0x003f));
1045         } 
1046         elseif($uni == 0xFEFF) // Byte order mark (skip)
1047                 return chr(0); // nop -- zap the BOM
1048         elseif ($uni >= 0xD800 && $uni <= 0xDFFF) // Test for illegal surrogates 
1049                 return chr(0); // found a surrogate
1050         elseif ($uni <= 0xffff) // 3 byte sequence 
1051         {
1052                 $r .= chr(0xe0 | ($uni >> 12));
1053                 $r .= chr(0x80 | (($uni >> 6) & 0x003f));
1054                 $r .= chr(0x80 | ($uni & 0x003f));
1055         } 
1056         elseif ($uni <= 0x10ffff) // 4 byte sequence 
1057         {
1058                 $r .= chr(0xf0 | ($uni >> 18));
1059                 $r .= chr(0x80 | (($uni >> 12) & 0x3f));
1060                 $r .= chr(0x80 | (($uni >> 6) & 0x3f));
1061                 $r .= chr(0x80 | ($uni & 0x3f));
1062         } 
1063         else 
1064                 return chr(0);
1065         return $r;
1066 }
1067
1068 global $p_chars;
1069 $p_chars = array (
1070     utf8_chr(0x0622) => array (utf8_chr(0xfe82), utf8_chr(0xfe82), utf8_chr(0x0622)),
1071     utf8_chr(0x0627) => array (utf8_chr(0xfe8e), utf8_chr(0xfe8e), utf8_chr(0x0627)),
1072     utf8_chr(0x0628) => array (utf8_chr(0xfe90), utf8_chr(0xfe92), utf8_chr(0xfe91)),
1073     utf8_chr(0x067e) => array (utf8_chr(0xfb57), utf8_chr(0xfb59), utf8_chr(0xfb58)),
1074     utf8_chr(0x062a) => array (utf8_chr(0xfe96), utf8_chr(0xfe98), utf8_chr(0xfe97)),
1075     utf8_chr(0x062b) => array (utf8_chr(0xfe9a), utf8_chr(0xfe9c), utf8_chr(0xfe9b)),
1076     utf8_chr(0x062c) => array (utf8_chr(0xfe9e), utf8_chr(0xfea0), utf8_chr(0xfe9f)),
1077     utf8_chr(0x0686) => array (utf8_chr(0xfb7b), utf8_chr(0xfb7d), utf8_chr(0xfb7c)),
1078     utf8_chr(0x062d) => array (utf8_chr(0xfea2), utf8_chr(0xfea4), utf8_chr(0xfea3)),
1079     utf8_chr(0x062e) => array (utf8_chr(0xfea6), utf8_chr(0xfea8), utf8_chr(0xfea7)),
1080     utf8_chr(0x062f) => array (utf8_chr(0xfeaa), utf8_chr(0xfeaa), utf8_chr(0xfea9)),
1081     utf8_chr(0x0630) => array (utf8_chr(0xfeac), utf8_chr(0xfeac), utf8_chr(0xfeab)),
1082     utf8_chr(0x0631) => array (utf8_chr(0xfeae), utf8_chr(0xfeae), utf8_chr(0xfead)),
1083     utf8_chr(0x0632) => array (utf8_chr(0xfeb0), utf8_chr(0xfeb0), utf8_chr(0xfeaf)),
1084     utf8_chr(0x0698) => array (utf8_chr(0xfb8b), utf8_chr(0xfb8b), utf8_chr(0xfb8a)),
1085     utf8_chr(0x0633) => array (utf8_chr(0xfeb2), utf8_chr(0xfeb4), utf8_chr(0xfeb3)),
1086     utf8_chr(0x0634) => array (utf8_chr(0xfeb6), utf8_chr(0xfeb8), utf8_chr(0xfeb7)),
1087     utf8_chr(0x0635) => array (utf8_chr(0xfeba), utf8_chr(0xfebc), utf8_chr(0xfebb)),
1088     utf8_chr(0x0636) => array (utf8_chr(0xfebe), utf8_chr(0xfec0), utf8_chr(0xfebf)),
1089     utf8_chr(0x0637) => array (utf8_chr(0xfec2), utf8_chr(0xfec4), utf8_chr(0xfec3)),
1090     utf8_chr(0x0638) => array (utf8_chr(0xfec6), utf8_chr(0xfec8), utf8_chr(0xfec7)),
1091     utf8_chr(0x0639) => array (utf8_chr(0xfeca), utf8_chr(0xfecc), utf8_chr(0xfecb)),
1092     utf8_chr(0x063a) => array (utf8_chr(0xfece), utf8_chr(0xfed0), utf8_chr(0xfecf)),
1093     utf8_chr(0x0641) => array (utf8_chr(0xfed2), utf8_chr(0xfed4), utf8_chr(0xfed3)),
1094     utf8_chr(0x0642) => array (utf8_chr(0xfed6), utf8_chr(0xfed8), utf8_chr(0xfed7)),
1095     utf8_chr(0x06a9) => array (utf8_chr(0xfeda), utf8_chr(0xfedc), utf8_chr(0xfedb)),
1096     utf8_chr(0x06af) => array (utf8_chr(0xfb93), utf8_chr(0xfb95), utf8_chr(0xfb94)),
1097     utf8_chr(0x0644) => array (utf8_chr(0xfede), utf8_chr(0xfee0), utf8_chr(0xfedf)),
1098     utf8_chr(0x0645) => array (utf8_chr(0xfee2), utf8_chr(0xfee4), utf8_chr(0xfee3)),
1099     utf8_chr(0x0646) => array (utf8_chr(0xfee6), utf8_chr(0xfee8), utf8_chr(0xfee7)),
1100     utf8_chr(0x0648) => array (utf8_chr(0xfeee), utf8_chr(0xfeee), utf8_chr(0xfeed)),
1101     utf8_chr(0x06cc) => array (utf8_chr(0xfbfd), utf8_chr(0xfbff), utf8_chr(0xfbfe)),
1102     utf8_chr(0x0643) => array (utf8_chr(0xfeda), utf8_chr(0xfedc), utf8_chr(0xfedb)),
1103     utf8_chr(0x064a) => array (utf8_chr(0xfef2), utf8_chr(0xfef4), utf8_chr(0xfef3)),
1104     utf8_chr(0x0623) => array (utf8_chr(0xfe84), utf8_chr(0xfe84), utf8_chr(0xfe83)),
1105     utf8_chr(0x0624) => array (utf8_chr(0xfe86), utf8_chr(0xfe86), utf8_chr(0xfe85)),
1106     utf8_chr(0x0625) => array (utf8_chr(0xfe88), utf8_chr(0xfe88), utf8_chr(0xfe87)),
1107     utf8_chr(0x0626) => array (utf8_chr(0xfe8a), utf8_chr(0xfe8c), utf8_chr(0xfe8b)),
1108     utf8_chr(0x0629) => array (utf8_chr(0xfe94), utf8_chr(0xfe98), utf8_chr(0xfe97))
1109 );
1110
1111 global $nastaligh;
1112 $nastaligh = array (
1113     utf8_chr(0x0647) => array (utf8_chr(0xfbab), utf8_chr(0xfbad), utf8_chr(0xfbac))
1114 );
1115 global $normal;
1116 $normal = array (
1117     utf8_chr(0x0647) => array (utf8_chr(0xfeea), utf8_chr(0xfeec), utf8_chr(0xfeeb))
1118 );
1119
1120 global $mp_chars;
1121 $mp_chars = array (utf8_chr(0x0622), utf8_chr(0x0627), utf8_chr(0x062f), utf8_chr(0x0630), utf8_chr(0x0631), utf8_chr(0x0632), 
1122         utf8_chr(0x0698), utf8_chr(0x0648), utf8_chr(0x0623), utf8_chr(0x0625), utf8_chr(0x0624));
1123
1124 global $ignorelist;
1125 $ignorelist = array (utf8_chr(0x0000), utf8_chr(0x064c), utf8_chr(0x064d), utf8_chr(0x064b), utf8_chr(0x064f), utf8_chr(0x0650), 
1126         utf8_chr(0x064e), utf8_chr(0x0651), utf8_chr(0x0653), utf8_chr(0x0670), utf8_chr(0x0654), utf8_chr(0xfe76), utf8_chr(0xfe7a), 
1127         utf8_chr(0xfe78), utf8_chr(0xfe7c), utf8_chr(0xfe7e), utf8_chr(0xfe74), utf8_chr(0xfe70), utf8_chr(0xfc5e), utf8_chr(0xfc5f), 
1128         utf8_chr(0xfc60), utf8_chr(0xfc61), utf8_chr(0xfc62), utf8_chr(0xfc63));
1129
1130 ///
1131 function arabic($str,$z="",$method='normal')
1132 {
1133         global $p_chars,$mp_chars, $ignorelist,$nastaligh,$normal;
1134         $str_back = $output = $e_output = $str_next = $str1 = $num = "";
1135         if ($method == 'nastaligh')
1136                 $p_chars = array_merge($p_chars, $nastaligh);
1137         else
1138                 $p_chars = array_merge($p_chars, $normal);
1139         $str_len = utf8_strlen($str);
1140         preg_match_all("/./u", $str, $ar);
1141         for ($i = 0; $i < $str_len; $i++)
1142         {
1143                 if (isset($ar[0][$i]))
1144                         $str1 = $ar[0][$i];
1145                 if(isset($ar[0][$i+1]) && in_array($ar[0][$i+1], $ignorelist))
1146                 {
1147                         if (isset($ar[0][$i+2]))
1148                                 $str_next = $ar[0][$i+2];
1149                         if ($i == 2) 
1150                                 $str_back = $ar[0][$i-2];
1151                         if ($i > 1 && $i != 2) 
1152                                 $str_back = $ar[0][$i-1];
1153                 }
1154                 elseif ($i > 0 && isset($ar[0][$i-1]) && !in_array($ar[0][$i-1], $ignorelist))
1155                 {
1156                         if (isset($ar[0][$i+1]))
1157                                 $str_next = $ar[0][$i+1];
1158                         if ($i != 0) 
1159                                 $str_back = $ar[0][$i-1];
1160                 }
1161                 else
1162                 {
1163                         if (isset($ar[0][$i+1]) && !empty($ar[0][$i+1]))
1164                                 $str_next = $ar[0][$i+1];
1165                         elseif ($i > 0 && isset($ar[0][$i-1])) 
1166                                 $str_next = $ar[0][$i-1];
1167                         if ($i > 1 && isset($ar[0][$i-2])) 
1168                                 $str_back = $ar[0][$i-2];
1169                 }
1170                 if (!in_array($str1,$ignorelist))
1171                 {
1172                         if (array_key_exists($str1,$p_chars))
1173                         {
1174                                 if (!$str_back || $str_back==" " || !array_key_exists($str_back,$p_chars))
1175                                 {
1176                                         if (!array_key_exists($str_back, $p_chars) && !array_key_exists($str_next, $p_chars)) 
1177                                                 $output = $str1.$output;
1178                                         else 
1179                                                 $output = $p_chars[$str1][2].$output;
1180                                         continue;
1181                                 }
1182                                 elseif (array_key_exists($str_next, $p_chars) && array_key_exists($str_back, $p_chars))
1183                                 {
1184                                         if (in_array($str_back, $mp_chars) && array_key_exists($str_next, $p_chars))
1185                                                 $output = $p_chars[$str1][2].$output;
1186                                         else
1187                                                 $output = $p_chars[$str1][1].$output;
1188                                         continue;
1189                                 }
1190                                 elseif (array_key_exists($str_back, $p_chars) && !array_key_exists($str_next, $p_chars))
1191                                 {
1192                                         if (in_array($str_back, $mp_chars))
1193                                                 $output = $str1.$output;
1194                                         else
1195                                                 $output = $p_chars[$str1][0].$output;
1196                                         continue;
1197                                 }
1198                         }
1199                         elseif ($z == "we")
1200                         {
1201                                 $number = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1202                                         "\xD9\xA0", "\xD9\xA1", "\xD9\xA2", "\xD9\xA3", "\xD9\xA4", "\xD9\xA5", "\xD9\xA6", 
1203                                         "\xD9\xA7", "\xD9\xA8", "\xD9\xA9",     "\xDB\xB0", "\xDB\xB1", "\xDB\xB2", "\xDB\xB3", 
1204                                         "\xDB\xB4", "\xDB\xB5", "\xDB\xB6", "\xDB\xB7", "\xDB\xB8", "\xDB\xB9");
1205                                 if (in_array($str1, $number))
1206                                 {
1207                                         $num .= $str1;
1208                                         $str1 = "";
1209                                 }
1210                                 if (!in_array($str_next, $number))
1211                                 {
1212                                         $str1 .= $num;
1213                                         $num = "";
1214                                 }
1215                                 //$output = $str1.$output;
1216                                 $output = $output.$str1;
1217                         }
1218                         elseif ($z == "fa")
1219                         {
1220                                 $number = array (utf8_chr(0x0660), utf8_chr(0x0661), utf8_chr(0x0662), 
1221                                         utf8_chr(0x0663), utf8_chr(0x0664), utf8_chr(0x0665), utf8_chr(0x0666), 
1222                                         utf8_chr(0x0667), utf8_chr(0x0668), utf8_chr(0x0669), utf8_chr(0x06f4), 
1223                                         utf8_chr(0x06f5), utf8_chr(0x06f6), utf8_chr(0x0030), utf8_chr(0x0031), 
1224                                         utf8_chr(0x0032), utf8_chr(0x0033), utf8_chr(0x0034), utf8_chr(0x0035), 
1225                                         utf8_chr(0x0036), utf8_chr(0x0037), utf8_chr(0x0038), utf8_chr(0x0039));
1226                                 switch ($str1)
1227                                 {
1228                                         case ")" : 
1229                                                 $str1 = "("; 
1230                                                 break;
1231                                         case "(" : 
1232                                                 $str1 = ")"; 
1233                                                 break;
1234                                         case "}" : 
1235                                                 $str1 = "{"; 
1236                                                 break;
1237                                         case "{" : 
1238                                                 $str1 = "}"; 
1239                                                 break;
1240                                         case "]" : 
1241                                                 $str1 = "["; 
1242                                                 break;
1243                                         case "[" : 
1244                                                 $str1 = "]"; 
1245                                                 break;
1246                                         case ">" : 
1247                                                 $str1 = "<"; 
1248                                                 break;
1249                                         case "<" : 
1250                                                 $str1 = ">"; 
1251                                                 break;
1252                                 }
1253                                 if (in_array($str1, $number))
1254                                 {
1255                                         $num .= $str1;
1256                                         $str1 = "";
1257                                 }
1258                                 if (!in_array($str_next, $number))
1259                                 {
1260                                         $str1 .= $num;
1261                                         $num = "";
1262                                 }
1263                                 $output = $str1.$output;
1264                         }
1265                         else
1266                         {
1267                                 if (($str1 == utf8_chr(0x060c)) || ($str1 == utf8_chr(0x061f)) || ($str1 == utf8_chr(0x0621)) || 
1268                                         (array_key_exists($str_next, $p_chars) && array_key_exists($str_back, $p_chars)) || 
1269                                         ($str1 == " " && array_key_exists($str_back, $p_chars)) || ($str1 == " " && 
1270                                         array_key_exists($str_next, $p_chars)))
1271                                 {
1272                                         if ($e_output)
1273                                         {
1274                                                 $output = $e_output.$output;
1275                                                 $e_output = "";
1276                                         }
1277                                         $output = $str1.$output;
1278                                 }
1279                                 else
1280                                 {
1281                                         $e_output .= $str1;
1282                                         if (array_key_exists($str_next, $p_chars) || $str_next == "")
1283                                         {
1284                                                 $output = $e_output.$output;
1285                                                 $e_output = "";
1286                                         }
1287                                 }
1288                         }
1289                 }
1290                 else
1291                         $output = $str1.$output;
1292                 $str_next = null;
1293                 $str_back = null;
1294         }
1295         return  $output;
1296 }
1297
1298 ?>