PageRenderTime 62ms CodeModel.GetById 25ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 1ms

/trunk/Classes/PHPExcel/Chart/Renderer/jpgraph.php

#
PHP | 831 lines | 614 code | 153 blank | 64 comment | 123 complexity | 6f6bbf350b95d53b62ee60d3777687d6 MD5 | raw file
  1<?php
  2
  3/**
  4 * PHPExcel
  5 *
  6 * Copyright (c) 2006 - 2012 PHPExcel
  7 *
  8 * This library is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU Lesser General Public
 10 * License as published by the Free Software Foundation; either
 11 * version 2.1 of the License, or (at your option) any later version.
 12 *
 13 * This library is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16 * Lesser General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU Lesser General Public
 19 * License along with this library; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 21 *
 22 * @category	PHPExcel
 23 * @package		PHPExcel_Chart
 24 * @copyright	Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
 25 * @license		http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt	LGPL
 26 * @version		##VERSION##, ##DATE##
 27 */
 28
 29
 30require_once(PHPExcel_Settings::getChartRendererPath().'/jpgraph.php');
 31
 32
 33/**
 34 * PHPExcel_Chart_Renderer_jpgraph
 35 *
 36 * @category	PHPExcel
 37 * @package		PHPExcel_Chart_Renderer
 38 * @copyright	Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
 39 */
 40class PHPExcel_Chart_Renderer_jpgraph
 41{
 42	private static $_width	= 640;
 43
 44	private static $_height	= 480;
 45
 46	private static $_colourSet = array( 'mediumpurple1',	'palegreen3',	'gold1',		'cadetblue1',
 47										'darkmagenta',		'coral',		'dodgerblue3',	'eggplant',
 48										'mediumblue',		'magenta',		'sandybrown',	'cyan',
 49										'firebrick1',		'forestgreen',	'deeppink4',	'darkolivegreen',
 50										'goldenrod2'
 51									  );
 52
 53	private static $_markSet = array(	'diamond'	=> MARK_DIAMOND,
 54										'square'	=> MARK_SQUARE,
 55										'triangle'	=> MARK_UTRIANGLE,
 56										'x'			=> MARK_X,
 57										'star'		=> MARK_STAR,
 58										'dot'		=> MARK_FILLEDCIRCLE,
 59										'dash'		=> MARK_DTRIANGLE,
 60										'circle'	=> MARK_CIRCLE,
 61										'plus'		=> MARK_CROSS
 62									);
 63
 64
 65	private $_chart	= null;
 66
 67	private $_graph	= null;
 68
 69	private static $_plotColour	= 0;
 70
 71	private static $_plotMark	= 0;
 72
 73
 74	private function _formatPointMarker($seriesPlot,$markerID) {
 75		$plotMarkKeys = array_keys(self::$_markSet);
 76		if (is_null($markerID)) {
 77			//	Use default plot marker (next marker in the series)
 78			self::$_plotMark %= count(self::$_markSet);
 79			$seriesPlot->mark->SetType(self::$_markSet[$plotMarkKeys[self::$_plotMark++]]);
 80		} elseif ($markerID !== 'none') {
 81			//	Use specified plot marker (if it exists)
 82			if (isset(self::$_markSet[$markerID])) {
 83				$seriesPlot->mark->SetType(self::$_markSet[$markerID]);
 84			} else {
 85				//	If the specified plot marker doesn't exist, use default plot marker (next marker in the series)
 86				self::$_plotMark %= count(self::$_markSet);
 87				$seriesPlot->mark->SetType(self::$_markSet[$plotMarkKeys[self::$_plotMark++]]);
 88			}
 89		} else {
 90			//	Hide plot marker
 91			$seriesPlot->mark->Hide();
 92		}
 93		$seriesPlot->mark->SetColor(self::$_colourSet[self::$_plotColour]);
 94		$seriesPlot->mark->SetFillColor(self::$_colourSet[self::$_plotColour]);
 95		$seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]);
 96
 97		return $seriesPlot;
 98	}	//	function _formatPointMarker()
 99
100
101	private function _formatDataSetLabels($groupID,$datasetLabels,$rotation = '') {
102		$datasetLabelFormatCode = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode();
103		if (!is_null($datasetLabelFormatCode)) {
104			//	Retrieve any label formatting code
105			$datasetLabelFormatCode = stripslashes($datasetLabelFormatCode);
106		}
107
108		$testCurrentIndex = 0;
109		foreach($datasetLabels as $i => $datasetLabel) {
110			//	Fill in any missing values in the $datasetLabels array
111			while ($i != $testCurrentIndex) {
112				$datasetLabels[$testCurrentIndex] = '';
113				++$testCurrentIndex;
114			}
115			if (is_array($datasetLabel)) {
116				if ($rotation == 'bar') {
117					$datasetLabel = array_reverse($datasetLabel);
118					$datasetLabels[$i] = implode(" ",$datasetLabel);
119				} else {
120					$datasetLabels[$i] = implode("\n",$datasetLabel);
121				}
122			} else {
123				//	Format labels according to any formatting code
124				if (!is_null($datasetLabelFormatCode)) {
125					$datasetLabels[$i] = PHPExcel_Style_NumberFormat::toFormattedString($datasetLabel,$datasetLabelFormatCode);
126				}
127			}
128			++$testCurrentIndex;
129		}
130
131		return $datasetLabels;
132	}	//	function _formatDataSetLabels()
133
134
135	private function _percentageSumCalculation($groupID,$seriesCount) {
136		//	Adjust our values to a percentage value across all series in the group
137		for($i = 0; $i < $seriesCount; ++$i) {
138			if ($i == 0) {
139				$sumValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
140			} else {
141				$nextValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
142				foreach($nextValues as $k => $value) {
143					if (isset($sumValues[$k])) {
144						$sumValues[$k] += $value;
145					} else {
146						$sumValues[$k] = $value;
147					}
148				}
149			}
150		}
151
152		return $sumValues;
153	}	//	function _percentageSumCalculation()
154
155
156	private function _percentageAdjustValues($dataValues,$sumValues) {
157		foreach($dataValues as $k => $dataValue) {
158			$dataValues[$k] = $dataValue / $sumValues[$k] * 100;
159		}
160
161		return $dataValues;
162	}	//	function _percentageAdjustValues()
163
164
165	private function _getCaption($captionElement) {
166		//	Read any caption
167		$caption = (!is_null($captionElement)) ? $captionElement->getCaption() : NULL;
168		//	Test if we have a title caption to display
169		if (!is_null($caption)) {
170			//	If we do, it could be a plain string or an array
171			if (is_array($caption)) {
172				//	Implode an array to a plain string
173				$caption = implode('',$caption);
174			}
175		}
176		return $caption;
177	}	//	function _getCaption()
178
179
180	private function _renderTitle() {
181		$title = $this->_getCaption($this->_chart->getTitle());
182		if (!is_null($title)) {
183			$this->_graph->title->Set($title);
184		}
185	}	//	function _renderTitle()
186
187
188	private function _renderLegend() {
189		$legend = $this->_chart->getLegend();
190		if (!is_null($legend)) {
191			$legendPosition = $legend->getPosition();
192			$legendOverlay = $legend->getOverlay();
193			switch ($legendPosition) {
194				case 'r'	:
195					$this->_graph->legend->SetPos(0.01,0.5,'right','center');	//	right
196					break;
197				case 'l'	:
198					$this->_graph->legend->SetPos(0.01,0.5,'left','center');	//	left
199					break;
200				case 't'	:
201					$this->_graph->legend->SetPos(0.5,0.01,'center','top');	//	top
202					break;
203				case 'b'	:
204					$this->_graph->legend->SetPos(0.5,0.99,'center','bottom');	//	bottom
205					break;
206				default		:
207					$this->_graph->legend->SetPos(0.01,0.01,'right','top');	//	top-right
208					break;
209			}
210		}
211	}	//	function _renderLegend()
212
213
214	private function _renderCartesianPlotArea($type='textlin') {
215		$this->_graph = new Graph(self::$_width,self::$_height);
216		$this->_graph->SetScale($type);
217
218		$this->_renderTitle();
219
220		//	Rotate for bar rather than column chart
221		$rotation = $this->_chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotDirection();
222		$reverse = ($rotation == 'bar') ? true : false;
223
224		$xAxisLabel = $this->_chart->getXAxisLabel();
225		if (!is_null($xAxisLabel)) {
226			$title = $this->_getCaption($xAxisLabel);
227			if (!is_null($title)) {
228				$this->_graph->xaxis->SetTitle($title,'center');
229				$this->_graph->xaxis->title->SetMargin(35);
230				if ($reverse) {
231					$this->_graph->xaxis->title->SetAngle(90);
232					$this->_graph->xaxis->title->SetMargin(90);
233				}
234			}
235		}
236
237		$yAxisLabel = $this->_chart->getYAxisLabel();
238		if (!is_null($yAxisLabel)) {
239			$title = $this->_getCaption($yAxisLabel);
240			if (!is_null($title)) {
241				$this->_graph->yaxis->SetTitle($title,'center');
242				if ($reverse) {
243					$this->_graph->yaxis->title->SetAngle(0);
244					$this->_graph->yaxis->title->SetMargin(-55);
245				}
246			}
247		}
248	}	//	function _renderCartesianPlotArea()
249
250
251	private function _renderPiePlotArea($doughnut = False) {
252		$this->_graph = new PieGraph(self::$_width,self::$_height);
253
254		$this->_renderTitle();
255	}	//	function _renderPiePlotArea()
256
257
258	private function _renderRadarPlotArea() {
259		$this->_graph = new RadarGraph(self::$_width,self::$_height);
260		$this->_graph->SetScale('lin');
261
262		$this->_renderTitle();
263	}	//	function _renderRadarPlotArea()
264
265
266	private function _renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d') {
267		$grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
268
269		$datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
270		if (count($datasetLabels) > 0) {
271			$datasetLabels = $this->_formatDataSetLabels($groupID,$datasetLabels);
272			$this->_graph->xaxis->SetTickLabels($datasetLabels);
273		}
274
275		$seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
276		$seriesPlots = array();
277		if ($grouping == 'percentStacked') {
278			$sumValues = $this->_percentageSumCalculation($groupID,$seriesCount);
279		}
280
281		//	Loop through each data series in turn
282		for($i = 0; $i < $seriesCount; ++$i) {
283			$dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
284			$marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
285
286			if ($grouping == 'percentStacked') {
287				$dataValues = $this->_percentageAdjustValues($dataValues,$sumValues);
288			}
289
290			//	Fill in any missing values in the $dataValues array
291			$testCurrentIndex = 0;
292			foreach($dataValues as $k => $dataValue) {
293				while($k != $testCurrentIndex) {
294					$dataValues[$testCurrentIndex] = null;
295					++$testCurrentIndex;
296				}
297				++$testCurrentIndex;
298			}
299
300			$seriesPlot = new LinePlot($dataValues);
301			if ($combination) {
302				$seriesPlot->SetBarCenter();
303			}
304
305			if ($filled) {
306				$seriesPlot->SetFilled(true);
307				$seriesPlot->SetColor('black');
308				$seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour++]);
309			} else {
310				//	Set the appropriate plot marker
311				$this->_formatPointMarker($seriesPlot,$marker);
312			}
313			$dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
314			$seriesPlot->SetLegend($dataLabel);
315
316			$seriesPlots[] = $seriesPlot;
317		}
318
319		if ($grouping == 'standard') {
320			$groupPlot = $seriesPlots;
321		} else {
322			$groupPlot = new AccLinePlot($seriesPlots);
323		}
324		$this->_graph->Add($groupPlot);
325	}	//	function _renderPlotLine()
326
327
328	private function _renderPlotBar($groupID, $dimensions = '2d') {
329		$rotation = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection();
330		//	Rotate for bar rather than column chart
331		if (($groupID == 0) && ($rotation == 'bar')) {
332			$this->_graph->Set90AndMargin();
333		}
334		$grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
335
336		$datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
337		if (count($datasetLabels) > 0) {
338			$datasetLabels = $this->_formatDataSetLabels($groupID,$datasetLabels,$rotation);
339			//	Rotate for bar rather than column chart
340			if ($rotation == 'bar') {
341				$datasetLabels = array_reverse($datasetLabels);
342				$this->_graph->yaxis->SetPos('max');
343				$this->_graph->yaxis->SetLabelAlign('center','top');
344				$this->_graph->yaxis->SetLabelSide(SIDE_RIGHT);
345			}
346			$this->_graph->xaxis->SetTickLabels($datasetLabels);
347		}
348
349
350		$seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
351		$seriesPlots = array();
352		if ($grouping == 'percentStacked') {
353			$sumValues = $this->_percentageSumCalculation($groupID,$seriesCount);
354		}
355
356		//	Loop through each data series in turn
357		for($j = 0; $j < $seriesCount; ++$j) {
358			$dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
359			if ($grouping == 'percentStacked') {
360				$dataValues = $this->_percentageAdjustValues($dataValues,$sumValues);
361			}
362
363			//	Fill in any missing values in the $dataValues array
364			$testCurrentIndex = 0;
365			foreach($dataValues as $k => $dataValue) {
366				while($k != $testCurrentIndex) {
367					$dataValues[$testCurrentIndex] = null;
368					++$testCurrentIndex;
369				}
370				++$testCurrentIndex;
371			}
372
373			//	Reverse the $dataValues order for bar rather than column chart
374			if ($rotation == 'bar') {
375				$dataValues = array_reverse($dataValues);
376			}
377			$seriesPlot = new BarPlot($dataValues);
378			$seriesPlot->SetColor('black');
379			$seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour++]);
380			if ($dimensions == '3d') {
381				$seriesPlot->SetShadow();
382			}
383			if (!$this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)) {
384				$dataLabel = '';
385			} else {
386				$dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)->getDataValue();
387			}
388			$seriesPlot->SetLegend($dataLabel);
389
390			$seriesPlots[] = $seriesPlot;
391		}
392		//	Reverse the plot order for bar rather than column chart
393		if (($rotation == 'bar') && (!($grouping == 'percentStacked'))) {
394			$seriesPlots = array_reverse($seriesPlots);
395		}
396
397		if ($grouping == 'clustered') {
398			$groupPlot = new GroupBarPlot($seriesPlots);
399		} elseif ($grouping == 'standard') {
400			$groupPlot = new GroupBarPlot($seriesPlots);
401		} else {
402			$groupPlot = new AccBarPlot($seriesPlots);
403			if ($dimensions == '3d') {
404				$groupPlot->SetShadow();
405			}
406		}
407
408		$this->_graph->Add($groupPlot);
409	}	//	function _renderPlotBar()
410
411
412	private function _renderPlotScatter($groupID,$bubble) {
413		$grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
414		$scatterStyle = $bubbleSize = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
415
416		$seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
417		$seriesPlots = array();
418
419		//	Loop through each data series in turn
420		for($i = 0; $i < $seriesCount; ++$i) {
421			$dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
422			$dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
423
424			foreach($dataValuesY as $k => $dataValueY) {
425				$dataValuesY[$k] = $k;
426			}
427
428			$seriesPlot = new ScatterPlot($dataValuesX,$dataValuesY);
429			if ($scatterStyle == 'lineMarker') {
430				$seriesPlot->SetLinkPoints();
431				$seriesPlot->link->SetColor(self::$_colourSet[self::$_plotColour]);
432			} elseif ($scatterStyle == 'smoothMarker') {
433				$spline = new Spline($dataValuesY,$dataValuesX);
434				list($splineDataY,$splineDataX) = $spline->Get(count($dataValuesX) * self::$_width / 20);
435				$lplot = new LinePlot($splineDataX,$splineDataY);
436				$lplot->SetColor(self::$_colourSet[self::$_plotColour]);
437
438				$this->_graph->Add($lplot);
439			}
440
441			if ($bubble) {
442				$this->_formatPointMarker($seriesPlot,'dot');
443				$seriesPlot->mark->SetColor('black');
444				$seriesPlot->mark->SetSize($bubbleSize);
445			} else {
446				$marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
447				$this->_formatPointMarker($seriesPlot,$marker);
448			}
449			$dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
450			$seriesPlot->SetLegend($dataLabel);
451
452			$this->_graph->Add($seriesPlot);
453		}
454	}	//	function _renderPlotScatter()
455
456
457	private function _renderPlotRadar($groupID) {
458		$radarStyle = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
459
460		$seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
461		$seriesPlots = array();
462
463		//	Loop through each data series in turn
464		for($i = 0; $i < $seriesCount; ++$i) {
465			$dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
466			$dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
467			$marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
468
469			$dataValues = array();
470			foreach($dataValuesY as $k => $dataValueY) {
471				$dataValues[$k] = implode(' ',array_reverse($dataValueY));
472			}
473			$tmp = array_shift($dataValues);
474			$dataValues[] = $tmp;
475			$tmp = array_shift($dataValuesX);
476			$dataValuesX[] = $tmp;
477
478			$this->_graph->SetTitles(array_reverse($dataValues));
479
480			$seriesPlot = new RadarPlot(array_reverse($dataValuesX));
481
482			$dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
483			$seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]);
484			if ($radarStyle == 'filled') {
485				$seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour]);
486			}
487			$this->_formatPointMarker($seriesPlot,$marker);
488			$seriesPlot->SetLegend($dataLabel);
489
490			$this->_graph->Add($seriesPlot);
491		}
492	}	//	function _renderPlotRadar()
493
494
495	private function _renderPlotContour($groupID) {
496		$contourStyle = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
497
498		$seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
499		$seriesPlots = array();
500
501		$dataValues = array();
502		//	Loop through each data series in turn
503		for($i = 0; $i < $seriesCount; ++$i) {
504			$dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
505			$dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
506
507			$dataValues[$i] = $dataValuesX;
508		}
509		$seriesPlot = new ContourPlot($dataValues);
510
511		$this->_graph->Add($seriesPlot);
512	}	//	function _renderPlotContour()
513
514
515	private function _renderPlotStock($groupID) {
516		$seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
517		$plotOrder = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder();
518		$seriesPlots = array();
519
520		$dataValues = array();
521		//	Loop through each data series in turn
522		for($i = 0; $i < $seriesCount; ++$i) {
523			$dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
524			$dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
525
526			foreach($dataValuesX as $j => $dataValueX)
527			$dataValues[$j][$plotOrder[$i]] = $dataValueX;
528		}
529
530		$seriesPlot = new StockPlot($dataValues);
531
532		$this->_graph->Add($seriesPlot);
533	}	//	function _renderPlotStock()
534
535
536	private function _renderAreaChart($groupCount, $dimensions = '2d') {
537		require_once('jpgraph_line.php');
538
539		$this->_renderCartesianPlotArea();
540
541		for($i = 0; $i < $groupCount; ++$i) {
542			$this->_renderPlotLine($i,True,False,$dimensions);
543		}
544	}	//	function _renderAreaChart()
545
546
547	private function _renderLineChart($groupCount, $dimensions = '2d') {
548		require_once('jpgraph_line.php');
549
550		$this->_renderCartesianPlotArea();
551
552		for($i = 0; $i < $groupCount; ++$i) {
553			$this->_renderPlotLine($i,False,False,$dimensions);
554		}
555	}	//	function _renderLineChart()
556
557
558	private function _renderBarChart($groupCount, $dimensions = '2d') {
559		require_once('jpgraph_bar.php');
560
561		$this->_renderCartesianPlotArea();
562
563		for($i = 0; $i < $groupCount; ++$i) {
564			$this->_renderPlotBar($i,$dimensions);
565		}
566	}	//	function _renderBarChart()
567
568
569	private function _renderScatterChart($groupCount) {
570		require_once('jpgraph_scatter.php');
571		require_once('jpgraph_regstat.php');
572		require_once('jpgraph_line.php');
573
574		$this->_renderCartesianPlotArea('linlin');
575
576		for($i = 0; $i < $groupCount; ++$i) {
577			$this->_renderPlotScatter($i,false);
578		}
579	}	//	function _renderScatterChart()
580
581
582	private function _renderBubbleChart($groupCount) {
583		require_once('jpgraph_scatter.php');
584
585		$this->_renderCartesianPlotArea('linlin');
586
587		for($i = 0; $i < $groupCount; ++$i) {
588			$this->_renderPlotScatter($i,true);
589		}
590	}	//	function _renderBubbleChart()
591
592
593	private function _renderPieChart($groupCount, $dimensions = '2d', $doughnut = False, $multiplePlots = False) {
594		require_once('jpgraph_pie.php');
595		if ($dimensions == '3d') {
596			require_once('jpgraph_pie3d.php');
597		}
598
599		$this->_renderPiePlotArea($doughnut);
600
601		$iLimit = ($multiplePlots) ? $groupCount : 1;
602		for($i = 0; $i < $iLimit; ++$i) {
603			$grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotGrouping();
604			$exploded = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotStyle();
605			if ($i == 0) {
606				$datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotCategoryByIndex(0)->getDataValues();
607				if (count($datasetLabels) > 0) {
608					$datasetLabels = $this->_formatDataSetLabels($i,$datasetLabels);
609				}
610			}
611
612			$seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotSeriesCount();
613			$seriesPlots = array();
614			//	For pie charts, we only display the first series: doughnut charts generally display all series
615			$jLimit = ($multiplePlots) ? $seriesCount : 1;
616			//	Loop through each data series in turn
617			for($j = 0; $j < $jLimit; ++$j) {
618				$dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotValuesByIndex($j)->getDataValues();
619
620				//	Fill in any missing values in the $dataValues array
621				$testCurrentIndex = 0;
622				foreach($dataValues as $k => $dataValue) {
623					while($k != $testCurrentIndex) {
624						$dataValues[$testCurrentIndex] = null;
625						++$testCurrentIndex;
626					}
627					++$testCurrentIndex;
628				}
629
630				if ($dimensions == '3d') {
631					$seriesPlot = new PiePlot3D($dataValues);
632				} else {
633					if ($doughnut) {
634						$seriesPlot = new PiePlotC($dataValues);
635					} else {
636						$seriesPlot = new PiePlot($dataValues);
637					}
638				}
639
640				if ($multiplePlots) {
641					$seriesPlot->SetSize(($jLimit-$j) / ($jLimit * 4));
642				}
643
644				if ($doughnut) {
645					$seriesPlot->SetMidColor('white');
646				}
647
648				$seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]);
649				$seriesPlot->SetLabels(array_fill(0,count($datasetLabels),''));
650				if ($dimensions != '3d') {
651					$seriesPlot->SetGuideLines(false);
652				}
653				if ($j == 0) {
654					if ($exploded) {
655						$seriesPlot->ExplodeAll();
656					}
657					$seriesPlot->SetLegends($datasetLabels);
658				}
659
660				$this->_graph->Add($seriesPlot);
661			}
662		}
663	}	//	function _renderPieChart()
664
665
666	private function _renderRadarChart($groupCount) {
667		require_once('jpgraph_radar.php');
668
669		$this->_renderRadarPlotArea();
670
671		for($i = 0; $i < $groupCount; ++$i) {
672			$this->_renderPlotRadar($i);
673		}
674	}	//	function _renderRadarChart()
675
676
677	private function _renderStockChart($groupCount) {
678		require_once('jpgraph_stock.php');
679
680		$this->_renderCartesianPlotArea();
681
682		for($i = 0; $i < $groupCount; ++$i) {
683			$this->_renderPlotStock($i);
684		}
685	}	//	function _renderStockChart()
686
687
688	private function _renderContourChart($groupCount,$dimensions) {
689		require_once('jpgraph_contour.php');
690
691		$this->_renderCartesianPlotArea('intint');
692
693		for($i = 0; $i < $groupCount; ++$i) {
694			$this->_renderPlotContour($i);
695		}
696	}	//	function _renderContourChart()
697
698
699	private function _renderCombinationChart($groupCount,$dimensions,$outputDestination) {
700		require_once('jpgraph_line.php');
701		require_once('jpgraph_bar.php');
702		require_once('jpgraph_scatter.php');
703		require_once('jpgraph_regstat.php');
704		require_once('jpgraph_line.php');
705
706		$this->_renderCartesianPlotArea();
707
708		for($i = 0; $i < $groupCount; ++$i) {
709			$dimensions = null;
710			$chartType = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
711			switch ($chartType) {
712				case 'area3DChart' :
713					$dimensions = '3d';
714				case 'areaChart' :
715					$this->_renderPlotLine($i,True,True,$dimensions);
716					break;
717				case 'bar3DChart' :
718					$dimensions = '3d';
719				case 'barChart' :
720					$this->_renderPlotBar($i,$dimensions);
721					break;
722				case 'line3DChart' :
723					$dimensions = '3d';
724				case 'lineChart' :
725					$this->_renderPlotLine($i,False,True,$dimensions);
726					break;
727				case 'scatterChart' :
728					$this->_renderPlotScatter($i,false);
729					break;
730				case 'bubbleChart' :
731					$this->_renderPlotScatter($i,true);
732					break;
733				default	:
734					$this->_graph = null;
735					return false;
736			}
737		}
738
739		$this->_renderLegend();
740
741		$this->_graph->Stroke($outputDestination);
742		return true;
743	}	//	function _renderCombinationChart()
744
745
746	public function render($outputDestination) {
747		$groupCount = $this->_chart->getPlotArea()->getPlotGroupCount();
748
749		$dimensions = null;
750		if ($groupCount == 1) {
751			$chartType = $this->_chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType();
752		} else {
753			$chartTypes = array();
754			for($i = 0; $i < $groupCount; ++$i) {
755				$chartTypes[] = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
756			}
757			$chartTypes = array_unique($chartTypes);
758			if (count($chartTypes) == 1) {
759				$chartType = array_pop($chartTypes);
760			} elseif (count($chartTypes) == 0) {
761				echo 'Chart is not yet implemented<br />';
762				return false;
763			} else {
764				return $this->_renderCombinationChart($groupCount,$dimensions,$outputDestination);
765			}
766		}
767
768		switch ($chartType) {
769			case 'area3DChart' :
770				$dimensions = '3d';
771			case 'areaChart' :
772				$this->_renderAreaChart($groupCount,$dimensions);
773				break;
774			case 'bar3DChart' :
775				$dimensions = '3d';
776			case 'barChart' :
777				$this->_renderBarChart($groupCount,$dimensions);
778				break;
779			case 'line3DChart' :
780				$dimensions = '3d';
781			case 'lineChart' :
782				$this->_renderLineChart($groupCount,$dimensions);
783				break;
784			case 'pie3DChart' :
785				$dimensions = '3d';
786			case 'pieChart' :
787				$this->_renderPieChart($groupCount,$dimensions,False,False);
788				break;
789			case 'doughnut3DChart' :
790				$dimensions = '3d';
791			case 'doughnutChart' :
792				$this->_renderPieChart($groupCount,$dimensions,True,True);
793				break;
794			case 'scatterChart' :
795				$this->_renderScatterChart($groupCount);
796				break;
797			case 'bubbleChart' :
798				$this->_renderBubbleChart($groupCount);
799				break;
800			case 'radarChart' :
801				$this->_renderRadarChart($groupCount);
802				break;
803			case 'surface3DChart' :
804				$dimensions = '3d';
805			case 'surfaceChart' :
806				$this->_renderContourChart($groupCount,$dimensions);
807				break;
808			case 'stockChart' :
809				$this->_renderStockChart($groupCount,$dimensions);
810				break;
811			default	:
812				echo $chartType.' is not yet implemented<br />';
813				return false;
814		}
815		$this->_renderLegend();
816
817		$this->_graph->Stroke($outputDestination);
818		return true;
819	}	//	function render()
820
821
822	/**
823	 * Create a new PHPExcel_Chart_Renderer_jpgraph
824	 */
825	public function __construct(PHPExcel_Chart $chart)
826	{
827		$this->_graph	= null;
828		$this->_chart	= $chart;
829	}	//	function __construct()
830
831}	//	PHPExcel_Chart_Renderer_jpgraph