1<?php
2/*=======================================================================
3// File:	JPGRAPH_PIE.PHP
4// Description:	Pie plot extension for JpGraph
5// Created: 	2001-02-14
6// Author:	Johan Persson (johanp@aditus.nu)
7// Ver:		$Id: jpgraph_pie.php,v 1.1.1.1 2005/11/30 23:01:57 gth2 Exp $
8//
9// License:	This code is released under QPL
10// Copyright (C) 2001,2002 Johan Persson
11//========================================================================
12*/
13
14
15// Defines for PiePlot::SetLabelType()
16DEFINE("PIE_VALUE_ABS",1);
17DEFINE("PIE_VALUE_PER",0);
18DEFINE("PIE_VALUE_PERCENTAGE",0);
19
20//===================================================
21// CLASS PiePlot
22// Description: Draws a pie plot
23//===================================================
24class PiePlot {
25    var $posx=0.3,$posy=0.5;
26    var $radius=0.3;
27    var $explode_radius=array(),$explode_all=false,$explode_r=20;
28    var $labels, $legends=null;
29    var $csimtargets=null;  // Array of targets for CSIM
30    var $csimareas='';		// Generated CSIM text
31    var $csimalts=null;		// ALT tags for corresponding target
32    var $data=null;
33    var $title;
34    var $startangle=0;
35    var $weight=1, $color="black";
36    var $legend_margin=6,$show_labels=true;
37    var $themearr = array(
38	"earth" 	=> array(136,34,40,45,46,62,63,134,74,10,120,136,141,168,180,77,209,218,346,395,89,430),
39	"pastel" => array(27,415,128,59,66,79,105,110,42,147,152,230,236,240,331,337,405,38),
40	"water"  => array(8,370,24,40,335,56,213,237,268,14,326,387,10,388),
41	"test"   => array(390,28,350,340,130,15,58),
42	"pca"   => array(390,28,350,6,340,89,15,58),
43	"sand"   => array(27,168,34,170,19,50,65,72,131,209,46,393));
44    var $theme="earth";
45    var $setslicecolors=array();
46    var $labeltype=0; // Default to percentage
47    var $pie_border=true,$pie_interior_border=true;
48    var $value;
49    var $ishadowcolor='',$ishadowdrop=4;
50    var $ilabelposadj=1;
51
52
53//---------------
54// CONSTRUCTOR
55    function PiePlot(&$data) {
56	$this->data = $data;
57	$this->title = new Text("");
58	$this->title->SetFont(FF_FONT1,FS_BOLD);
59	$this->value = new DisplayValue();
60	$this->value->Show();
61	$this->value->SetFormat('%.1f%%');
62    }
63
64//---------------
65// PUBLIC METHODS
66    function SetCenter($x,$y=0.5) {
67	$this->posx = $x;
68	$this->posy = $y;
69    }
70
71    function SetColor($aColor) {
72	$this->color = $aColor;
73    }
74
75    function SetShadow($aColor='darkgray',$aDropWidth=4) {
76	$this->ishadowcolor = $aColor;
77	$this->ishadowdrop = $aDropWidth;
78    }
79
80    function SetCSIMTargets(&$targets,$alts=null) {
81	$this->csimtargets=$targets;
82	$this->csimalts=$alts;
83    }
84
85    function GetCSIMareas() {
86	return $this->csimareas;
87    }
88
89    function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {
90        //Slice number, ellipse centre (x,y), height, width, start angle, end angle
91	while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
92	while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
93
94	$sa = 2*M_PI - $sa;
95	$ea = 2*M_PI - $ea;
96
97	//add coordinates of the centre to the map
98	$coords = "$xc, $yc";
99
100	//add coordinates of the first point on the arc to the map
101	$xp = floor(($radius*cos($ea))+$xc);
102	$yp = floor($yc-$radius*sin($ea));
103	$coords.= ", $xp, $yp";
104
105	//add coordinates every 0.2 radians
106	$a=$ea+0.2;
107	while ($a<$sa) {
108	    $xp = floor($radius*cos($a)+$xc);
109	    $yp = floor($yc-$radius*sin($a));
110	    $coords.= ", $xp, $yp";
111	    $a += 0.2;
112	}
113
114	//Add the last point on the arc
115	$xp = floor($radius*cos($sa)+$xc);
116	$yp = floor($yc-$radius*sin($sa));
117	$coords.= ", $xp, $yp";
118	if( !empty($this->csimtargets[$i]) )
119	    $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".
120		$this->csimtargets[$i]."\"";
121	if( !empty($this->csimalts[$i]) ) {
122	    $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
123	    $this->csimareas .= " alt=\"$tmp\" title=\"$tmp\"";
124	}
125	$this->csimareas .= ">\n";
126    }
127
128
129    function SetTheme($aTheme) {
130	if( in_array($aTheme,array_keys($this->themearr)) )
131	    $this->theme = $aTheme;
132	else
133	    JpGraphError::Raise("PiePLot::SetTheme() Unknown theme: $aTheme");
134    }
135
136    function ExplodeSlice($e,$radius=20) {
137	$this->explode_radius[$e]=$radius;
138    }
139
140    function ExplodeAll($radius=20) {
141	$this->explode_all=true;
142	$this->explode_r = $radius;
143    }
144
145    function Explode($aExplodeArr) {
146	if( !is_array($aExplodeArr) ) {
147	    JpGraphError::Raise("Argument to PiePlot::Explode() must be an array.");
148	}
149	$this->explode_radius = $aExplodeArr;
150    }
151
152    function SetSliceColors($aColors) {
153	$this->setslicecolors = $aColors;
154    }
155
156    function SetStartAngle($aStart) {
157	$this->startangle = $aStart;
158    }
159
160    function SetFont($family,$style=FS_NORMAL,$size=10) {
161		JpGraphError::Raise('PiePlot::SetFont() is deprecated. Use PiePlot->value->SetFont() instead.');
162    }
163
164    // Size in percentage
165    function SetSize($aSize) {
166	if( ($aSize>0 && $aSize<=0.5) || ($aSize>10 && $aSize<1000) )
167	    $this->radius = $aSize;
168	else
169	    JpGraphError::Raise("PiePlot::SetSize() Radius for pie must either be specified as a fraction
170                                [0, 0.5] of the size of the image or as an absolute size in pixels
171                                in the range [10, 1000]");
172    }
173
174    function SetFontColor($aColor) {
175	JpGraphError::Raise('PiePlot::SetFontColor() is deprecated. Use PiePlot->value->SetColor() instead.');
176    }
177
178    // Set label arrays
179    function SetLegends($aLegend) {
180	$this->legends = $aLegend;
181    }
182
183    // Set text labels for slices
184    function SetLabels($aLabels,$aLblPosAdj="auto") {
185	$this->labels = $aLabels;
186	$this->ilabelposadj=$aLblPosAdj;
187    }
188
189    function SetLabelPos($aLblPosAdj) {
190	$this->ilabelposadj=$aLblPosAdj;
191    }
192
193    // Should we display actual value or percentage?
194    function SetLabelType($t) {
195	if( $t<0 || $t>1 )
196	    JpGraphError::Raise("PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not $t).");
197	$this->labeltype=$t;
198    }
199
200    function SetValueType($aType) {
201	$this->SetLabelType($aType);
202    }
203
204
205    // Should the circle around a pie plot be displayed
206    function ShowBorder($exterior=true,$interior=true) {
207	$this->pie_border = $exterior;
208	$this->pie_interior_border = $interior;
209    }
210
211    // Setup the legends
212    function Legend(&$graph) {
213	$colors = array_keys($graph->img->rgb->rgb_table);
214   	sort($colors);
215   	$ta=$this->themearr[$this->theme];
216
217   	if( $this->setslicecolors==null )
218	    $numcolors=count($ta);
219   	else
220	    $numcolors=count($this->setslicecolors);
221
222	$sum=0;
223	for($i=0; $i<count($this->data); ++$i)
224	    $sum += $this->data[$i];
225
226	// Bail out with error if the sum is 0
227	if( $sum==0 )
228	    JpGraphError::Raise("Illegal pie plot. Sum of all data is zero for Pie!");
229
230	$i=0;
231	if( count($this->legends)>0 ) {
232	    foreach( $this->legends as $l ) {
233
234		// Replace possible format with actual values
235		if( $this->labeltype==0 )
236		    $l = sprintf($l,100*$this->data[$i]/$sum);
237		else
238		    $l = sprintf($l,$this->data[$i]);
239
240		if( $this->setslicecolors==null )
241		    $graph->legend->Add($l,$colors[$ta[$i%$numcolors]]);
242		else
243		    $graph->legend->Add($l,$this->setslicecolors[$i%$numcolors]);
244		++$i;
245
246				// Breakout if there are more legends then values
247		if( $i==count($this->data) ) return;
248	    }
249	}
250    }
251
252    function Stroke(&$img) {
253
254	$colors = array_keys($img->rgb->rgb_table);
255   	sort($colors);
256   	$ta=$this->themearr[$this->theme];
257
258   	if( $this->setslicecolors==null )
259	    $numcolors=count($ta);
260   	else
261	    $numcolors=count($this->setslicecolors);
262
263	// Draw the slices
264	$sum=0;
265	$n = count($this->data);
266	for($i=0; $i < $n; ++$i)
267	    $sum += $this->data[$i];
268
269	// Bail out with error if the sum is 0
270	if( $sum==0 )
271	    JpGraphError::Raise("Sum of all data is 0 for Pie.");
272
273	// Format the titles for each slice
274	for( $i=0; $i<count($this->data); ++$i) {
275	    if( $this->labeltype==0 )
276		if( $sum != 0 )
277		    $l = 100.0*$this->data[$i]/$sum;
278		else
279		    $l = 0.0;
280	    else
281		$l = $this->data[$i]*1.0;
282	    if( isset($this->labels[$i]) && is_string($this->labels[$i]) )
283		$this->labels[$i]=sprintf($this->labels[$i],$l);
284	    else
285		$this->labels[$i]=$l;
286	}
287
288	// Set up the pie-circle
289	if( $this->radius < 1 )
290	    $this->radius = floor($this->radius*min($img->width,$img->height));
291	else
292	    $this->radius = $this->radius;
293	$xc = round($this->posx*$img->width);
294	$yc = round($this->posy*$img->height);
295
296	$this->startangle = $this->startangle*M_PI/180;
297
298	if( $this->explode_all )
299	    for($i=0;$i<count($this->data);++$i)
300		$this->explode_radius[$i]=$this->explode_r;
301
302	$n = count($this->data);
303
304	if( $this->ishadowcolor != "") {
305	    $accsum=0;
306	    $angle2 = $this->startangle;
307	    $img->SetColor($this->ishadowcolor);
308	    for($i=0; $sum>0 && $i < $n; ++$i) {
309		$d = $this->data[$i];
310		$angle1 = $angle2;
311		$accsum += $d;
312		$angle2 = $this->startangle+2*M_PI*$accsum/$sum;
313		if( empty($this->explode_radius[$i]) )
314		    $this->explode_radius[$i]=0;
315
316		$la = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1);
317		$xcm = $xc + $this->explode_radius[$i]*cos($la);
318		$ycm = $yc - $this->explode_radius[$i]*sin($la);
319
320		$xcm += $this->ishadowdrop;
321		$ycm += $this->ishadowdrop;
322
323		$img->CakeSlice($xcm,$ycm,$this->radius,$this->radius,
324				$angle1*180/M_PI,$angle2*180/M_PI,$this->ishadowcolor);
325
326	    }
327	}
328
329	$accsum=0;
330	$angle2 = $this->startangle;
331	$img->SetColor($this->color);
332
333	for($i=0; $sum>0 && $i < $n; ++$i) {
334	    $d = $this->data[$i];
335	    $angle1 = $angle2;
336	    $accsum += $d;
337	    $angle2 = $this->startangle+2*M_PI*$accsum/$sum;
338
339	    if( $this->setslicecolors==null )
340		$slicecolor=$colors[$ta[$i%$numcolors]];
341	    else
342		$slicecolor=$this->setslicecolors[$i%$numcolors];
343
344	    if( $this->pie_interior_border )
345		$img->SetColor($this->color);
346	    else
347		$img->SetColor($slicecolor);
348
349	    $arccolor = $this->pie_border ? $this->color : "";
350
351	    $this->la[$i] = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1);
352
353	    if( empty($this->explode_radius[$i]) )
354		$this->explode_radius[$i]=0;
355
356	    $xcm = $xc + $this->explode_radius[$i]*cos($this->la[$i]);
357	    $ycm = $yc - $this->explode_radius[$i]*sin($this->la[$i]);
358
359	    $img->CakeSlice($xcm,$ycm,$this->radius-1,$this->radius-1,
360			    $angle1*180/M_PI,$angle2*180/M_PI,$slicecolor,$arccolor);
361
362	    if ($this->csimtargets)
363		$this->AddSliceToCSIM($i,$xcm,$ycm,$this->radius,$angle1,$angle2);
364
365	}
366
367	if( $this->value->show )
368	    $this->StrokeAllLabels($img,$xc,$yc);
369
370	// Adjust title position
371	$this->title->Pos($xc,
372			  $yc-$this->title->GetFontHeight($img)-$this->radius-$this->title->margin,
373			  "center","bottom");
374	$this->title->Stroke($img);
375
376    }
377
378//---------------
379// PRIVATE METHODS
380
381    function StrokeAllLabels($img,$xc,$yc) {
382	$n = count($this->data);
383	for($i=0; $i < $n; ++$i) {
384	    $this->StrokeLabel($this->labels[$i],$img,$xc,$yc,$this->la[$i],
385			       $this->radius + $this->explode_radius[$i]);
386	}
387    }
388
389    // Position the labels of each slice
390    function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
391
392	// Default value
393	if( $this->ilabelposadj === 'auto' )
394	    $this->ilabelposadj = 0.65;
395
396	// We position the values diferntely depending on if they are inside
397	// or outside the pie
398	if( $this->ilabelposadj < 1.0 ) {
399
400	    $this->value->SetAlign('center','center');
401	    $this->value->margin = 0;
402
403	    $xt=round($this->ilabelposadj*$r*cos($a)+$xc);
404	    $yt=round($yc-$this->ilabelposadj*$r*sin($a));
405
406	    $this->value->Stroke($img,$label,$xt,$yt);
407	}
408	else {
409
410	    $this->value->halign = "left";
411	    $this->value->valign = "top";
412	    $this->value->margin = 0;
413
414	    $r += $img->GetFontHeight()/2;
415	    $xt=round($r*cos($a)+$xc);
416	    $yt=round($yc-$r*sin($a));
417
418	    // Position the axis title.
419	    // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
420	    // that intersects with the extension of the corresponding axis. The code looks a little
421	    // bit messy but this is really the only way of having a reasonable position of the
422	    // axis titles.
423	    $img->SetFont($this->value->ff,$this->value->fs,$this->value->fsize);
424	    $h=$img->GetTextHeight($label);
425	    $w=$img->GetTextWidth(sprintf($this->value->format,$label));
426	    while( $a > 2*M_PI ) $a -= 2*M_PI;
427	    if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0;
428	    if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI;
429	    if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1;
430	    if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI);
431
432	    if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI;
433	    if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI);
434	    if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1;
435	    if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI);
436	    if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0;
437
438	    $this->value->Stroke($img,$label,$xt-$dx*$w,$yt-$dy*$h);
439	}
440    }
441} // Class
442
443
444//===================================================
445// CLASS PiePlotC
446// Description: Same as a normal pie plot but with a
447// filled circle in the center
448//===================================================
449class PiePlotC extends PiePlot {
450    var $imidsize=0.5;		// Fraction of total width
451    var $imidcolor='white';
452    var $midtitle='';
453    var $middlecsimtarget="",$middlecsimalt="";
454
455    function PiePlotC($data,$aCenterTitle='') {
456	parent::PiePlot($data);
457	$this->midtitle = new Text();
458	$this->midtitle->ParagraphAlign('center');
459    }
460
461    function SetMid($aTitle,$aColor='white',$aSize=0.5) {
462	$this->midtitle->Set($aTitle);
463	$this->imidsize = $aSize ;
464	$this->imidcolor = $aColor ;
465    }
466
467    function SetMidTitle($aTitle) {
468	$this->midtitle->Set($aTitle);
469    }
470
471    function SetMidSize($aSize) {
472	$this->imidsize = $aSize ;
473    }
474
475    function SetMidColor($aColor) {
476	$this->imidcolor = $aColor ;
477    }
478
479    function SetMidCSIM($aTarget,$aAlt) {
480	$this->middlecsimtarget = $aTarget;
481	$this->middlecsimalt = $aAlt;
482    }
483
484    function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {
485        //Slice number, ellipse centre (x,y), radius, start angle, end angle
486	while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
487	while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
488
489	$sa = 2*M_PI - $sa;
490	$ea = 2*M_PI - $ea;
491
492	// Add inner circle first point
493	$xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
494	$yp = floor($yc-($this->imidsize*$radius*sin($ea)));
495	$coords = "$xp, $yp";
496
497	//add coordinates every 0.25 radians
498	$a=$ea+0.25;
499	while ($a < $sa) {
500	    $xp = floor(($this->imidsize*$radius*cos($a)+$xc));
501	    $yp = floor($yc-($this->imidsize*$radius*sin($a)));
502	    $coords.= ", $xp, $yp";
503	    $a += 0.25;
504	}
505
506	// Make sure we end at the last point
507	$xp = floor(($this->imidsize*$radius*cos($sa)+$xc));
508	$yp = floor($yc-($this->imidsize*$radius*sin($sa)));
509	$coords.= ", $xp, $yp";
510
511	// Straight line to outer circle
512	$xp = floor($radius*cos($sa)+$xc);
513	$yp = floor($yc-$radius*sin($sa));
514	$coords.= ", $xp, $yp";
515
516	//add coordinates every 0.25 radians
517	$a=$sa - 0.25;
518	while ($a > $ea) {
519	    $xp = floor($radius*cos($a)+$xc);
520	    $yp = floor($yc-$radius*sin($a));
521	    $coords.= ", $xp, $yp";
522	    $a -= 0.25;
523	}
524
525	//Add the last point on the arc
526	$xp = floor($radius*cos($ea)+$xc);
527	$yp = floor($yc-$radius*sin($ea));
528	$coords.= ", $xp, $yp";
529
530	// Close the arc
531	$xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
532	$yp = floor($yc-($this->imidsize*$radius*sin($ea)));
533	$coords .= ", $xp, $yp";
534
535	if( !empty($this->csimtargets[$i]) )
536	    $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".
537		$this->csimtargets[$i]."\"";
538	if( !empty($this->csimalts[$i]) ) {
539	    $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
540	    $this->csimareas .= " alt=\"$tmp\" title=\"$tmp\"";
541	}
542	$this->csimareas .= ">\n";
543    }
544
545
546    function Stroke($img) {
547
548	// Stroke the pie but don't stroke values
549	$tmp =  $this->value->show;
550	$this->value->show = false;
551	parent::Stroke($img);
552	$this->value->show = $tmp;
553
554 	$xc = round($this->posx*$img->width);
555	$yc = round($this->posy*$img->height);
556
557	if( $this->ishadowcolor != "" ) {
558	    $img->SetColor($this->ishadowcolor);
559	    $img->FilledCircle($xc+$this->ishadowdrop,$yc+$this->ishadowdrop,
560			       round($this->radius*$this->imidsize));
561	}
562
563	if( $this->imidsize > 0 ) {
564
565	    $img->SetColor($this->imidcolor);
566	    $img->FilledCircle($xc,$yc,round($this->radius*$this->imidsize));
567
568	    if(  $this->pie_border ) {
569		$img->SetColor($this->color);
570		$img->Circle($xc,$yc,round($this->radius*$this->imidsize));
571	    }
572
573	    if( !empty($this->middlecsimtarget) )
574		$this->AddMiddleCSIM($xc,$yc,round($this->radius*$this->imidsize));
575	}
576
577
578
579	if( $this->value->show )
580	    $this->StrokeAllLabels($img,$xc,$yc);
581
582	$this->midtitle->Pos($xc,$yc,'center','center');
583	$this->midtitle->Stroke($img);
584
585    }
586
587    function AddMiddleCSIM($xc,$yc,$r) {
588	$this->csimareas .= "<area shape=\"circle\" coords=\"$xc,$yc,$r\" href=\"".
589	    $this->middlecsimtarget."\"";
590	if( !empty($this->middlecsimalt) ) {
591	    $tmp = $this->middlecsimalt;
592	    $this->csimareas .= " alt=\"$tmp\" title=\"$tmp\"";
593	}
594	$this->csimareas .= ">\n";
595    }
596
597    function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
598
599	if( $this->ilabelposadj === 'auto' )
600	    $this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize;
601
602	parent::StrokeLabel($label,$img,$xc,$yc,$a,$r);
603
604    }
605
606}
607
608
609//===================================================
610// CLASS PieGraph
611// Description:
612//===================================================
613class PieGraph extends Graph {
614    var $posx, $posy, $radius;
615    var $legends=array();
616    var $plots=array();
617//---------------
618// CONSTRUCTOR
619    function PieGraph($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) {
620	$this->Graph($width,$height,$cachedName,$timeout,$inline);
621	$this->posx=$width/2;
622	$this->posy=$height/2;
623	$this->SetColor(array(255,255,255));
624    }
625
626//---------------
627// PUBLIC METHODS
628    function Add(&$pie) {
629	$this->plots[] = $pie;
630    }
631
632    function SetColor($c) {
633	$this->SetMarginColor($c);
634    }
635
636
637    function DisplayCSIMAreas() {
638	    $csim="";
639	    foreach($this->plots as $p ) {
640		$csim .= $p->GetCSIMareas();
641	    }
642	    //$csim.= $this->legend->GetCSIMareas();
643	    if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) {
644		$this->img->SetColor($this->csimcolor);
645		for ($i=0; $i<count($coords[0]); $i++) {
646		    if ($coords[1][$i]=="poly") {
647			preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts);
648			$this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]);
649			for ($j=0; $j<count($pts[0]); $j++) {
650			    $this->img->LineTo($pts[1][$j],$pts[2][$j]);
651			}
652		    } else if ($coords[1][$i]=="rect") {
653			$pts = preg_split('/,/', $coords[2][$i]);
654			$this->img->SetStartPoint($pts[0],$pts[1]);
655			$this->img->LineTo($pts[2],$pts[1]);
656			$this->img->LineTo($pts[2],$pts[3]);
657			$this->img->LineTo($pts[0],$pts[3]);
658			$this->img->LineTo($pts[0],$pts[1]);
659
660		    }
661		}
662	    }
663    }
664
665    // Method description
666    function Stroke($aStrokeFileName="") {
667	// If the filename is the predefined value = '_csim_special_'
668	// we assume that the call to stroke only needs to do enough
669	// to correctly generate the CSIM maps.
670	// We use this variable to skip things we don't strictly need
671	// to do to generate the image map to improve performance
672	// a best we can. Therefor you will see a lot of tests !$_csim in the
673	// code below.
674	$_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
675
676	// We need to know if we have stroked the plot in the
677	// GetCSIMareas. Otherwise the CSIM hasn't been generated
678	// and in the case of GetCSIM called before stroke to generate
679	// CSIM without storing an image to disk GetCSIM must call Stroke.
680	$this->iHasStroked = true;
681
682
683	if( !$_csim ) {
684	    if( $this->background_image != "" ) {
685		$this->StrokeFrameBackground();
686	    }
687	    else {
688		$this->StrokeFrame();
689	    }
690	}
691
692	for($i=0; $i<count($this->plots); ++$i)
693	    $this->plots[$i]->Stroke($this->img);
694	if( !$_csim ) {
695	    foreach( $this->plots as $p)
696		$p->Legend($this);
697
698	    $this->legend->Stroke($this->img);
699	    $this->StrokeTitles();
700
701	    // Stroke texts
702	    if( $this->texts != null )
703		foreach( $this->texts as $t)
704		    $t->Stroke($this->img);
705
706	    if( JPG_DEBUG ) {
707		$this->DisplayCSIMAreas();
708	    }
709
710	    // Finally output the image
711	    $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
712	}
713    }
714} // Class
715
716/* EOF */
717?>
718