EZ-Components

This commit is contained in:
Andreas Österreicher
2009-02-17 15:27:43 +00:00
parent 359c3c55c9
commit 0a8e90a8b3
572 changed files with 64490 additions and 0 deletions
@@ -0,0 +1,438 @@
<?php
/**
* File containing the abstract ezcGraphAxisLabelRenderer class
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Abstract class to render labels and grids on axis. Will be extended to
* make it possible using different algorithms for rendering axis labels.
*
* @property bool $majorStepCount
* Count of major steps.
* @property bool $minorStepCount
* Count of minor steps.
* @property int $majorStepSize
* Size of major steps.
* @property int $minorStepSize
* Size of minor steps.
* @property bool $innerStep
* Indicates if steps are shown on the inner side of axis.
* @property bool $outerStep
* Indicates if steps are shown on the outer side of axis.
* @property bool $outerGrid
* Indicates if the grid is shown on the outer side of axis.
* @property bool $showLables
* Indicates if the labels should be shown
* @property int $labelPadding
* Padding of labels.
*
* @version 1.3
* @package Graph
*/
abstract class ezcGraphAxisLabelRenderer extends ezcBaseOptions
{
/**
* Driver to render axis labels
*
* @var ezcGraphDriver
*/
protected $driver;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['majorStepCount'] = false;
$this->properties['minorStepCount'] = false;
$this->properties['majorStepSize'] = 3;
$this->properties['minorStepSize'] = 1;
$this->properties['innerStep'] = true;
$this->properties['outerStep'] = false;
$this->properties['outerGrid'] = false;
$this->properties['showLabels'] = true;
$this->properties['labelPadding'] = 2;
parent::__construct( $options );
}
/**
* __set
*
* @param mixed $propertyName
* @param mixed $propertyValue
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
* @throws ezcBasePropertyNotFoundException
* If a the value for the property options is not an instance of
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'driver':
if ( $propertyValue instanceof ezcGraphDriver )
{
$this->properties['driver'] = $propertyValue;
}
else
{
throw new ezcGraphInvalidDriverException( $propertyValue );
}
break;
case 'majorStepCount':
if ( ( $propertyValue !== false ) &&
!is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['majorStepCount'] = (int) $propertyValue;
break;
case 'minorStepCount':
if ( ( $propertyValue !== false ) &&
!is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['minorStepCount'] = (int) $propertyValue;
break;
case 'majorStepSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['majorStepSize'] = (int) $propertyValue;
break;
case 'minorStepSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['minorStepSize'] = (int) $propertyValue;
break;
case 'innerStep':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties['innerStep'] = (bool) $propertyValue;
break;
case 'outerStep':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties['outerStep'] = (bool) $propertyValue;
break;
case 'outerGrid':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties['outerGrid'] = (bool) $propertyValue;
break;
case 'showLabels':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties['showLabels'] = (bool) $propertyValue;
break;
case 'labelPadding':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['labelPadding'] = (int) $propertyValue;
break;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
}
}
/**
* Checks for the cutting point of two lines.
*
* The lines are given by a start position and the direction of the line,
* both as instances of {@link ezcGraphCoordinate}. If no cutting point
* could be calculated, because the lines are parallel the function will
* return false. Otherwise the factor returned can be used to calculate the
* cutting point using the following equatation:
* point = $aStart + $factor * $aDir;
*
* We return the factor instead of the resulting point because it can be
* easily determined from the factor if the cutting point is in "behind"
* the line starting point, or if the distance to the cutting point is
* bigger then the direction vector is long ( $factor > 1 ).
*
* @param ezcGraphCoordinate $aStart
* @param ezcGraphCoordinate $aDir
* @param ezcGraphCoordinate $bStart
* @param ezcGraphCoordinate $bDir
* @return mixed
*/
public function determineLineCuttingPoint( ezcGraphCoordinate $aStart, ezcGraphCoordinate $aDir, ezcGraphCoordinate $bStart, ezcGraphCoordinate $bDir )
{
// Check if lines are parallel
if ( ( ( abs( $aDir->x ) < .000001 ) && ( abs( $bDir->x ) < .000001 ) ) ||
( ( abs( $aDir->y ) < .000001 ) && ( abs( $bDir->y ) < .000001 ) ) ||
( ( abs( $aDir->x * $bDir->x * $aDir->y * $bDir->y ) > .000001 ) &&
( abs( ( $aDir->x / $aDir->y ) - ( $bDir->x / $bDir->y ) ) < .000001 )
)
)
{
return false;
}
// Use ? : to prevent division by zero
$denominator =
( abs( $aDir->y ) > .000001 ? $bDir->y / $aDir->y : .0 ) -
( abs( $aDir->x ) > .000001 ? $bDir->x / $aDir->x : .0 );
// Solve equatation
if ( abs( $denominator ) < .000001 )
{
return - (
( abs( $aDir->y ) > .000001 ? $bStart->y / $aDir->y : .0 ) -
( abs( $aDir->y ) > .000001 ? $aStart->y / $aDir->y : .0 ) -
( abs( $aDir->x ) > .000001 ? $bStart->x / $aDir->x : .0 ) +
( abs( $aDir->x ) > .000001 ? $aStart->x / $aDir->x : .0 )
);
}
else
{
return - (
( abs( $aDir->y ) > .000001 ? $bStart->y / $aDir->y : .0 ) -
( abs( $aDir->y ) > .000001 ? $aStart->y / $aDir->y : .0 ) -
( abs( $aDir->x ) > .000001 ? $bStart->x / $aDir->x : .0 ) +
( abs( $aDir->x ) > .000001 ? $aStart->x / $aDir->x : .0 )
) / $denominator;
}
}
/**
* Draw single step on a axis
*
* Draws a step on a axis at the current position
*
* @param ezcGraphRenderer $renderer Renderer to draw the step with
* @param ezcGraphCoordinate $position Position of step
* @param ezcGraphCoordinate $direction Direction of axis
* @param int $axisPosition Position of axis
* @param int $size Step size
* @param ezcGraphColor $color Color of axis
* @return void
*/
public function drawStep( ezcGraphRenderer $renderer, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, $axisPosition, $size, ezcGraphColor $color )
{
if ( ! ( $this->innerStep || $this->outerStep ) )
{
return false;
}
$drawStep = false;
if ( ( ( $axisPosition === ezcGraph::CENTER ) && $this->innerStep ) ||
( ( $axisPosition === ezcGraph::BOTTOM ) && $this->outerStep ) ||
( ( $axisPosition === ezcGraph::TOP ) && $this->innerStep ) ||
( ( $axisPosition === ezcGraph::RIGHT ) && $this->outerStep ) ||
( ( $axisPosition === ezcGraph::LEFT ) && $this->innerStep ) )
{
// Turn direction vector to left by 90 degrees and multiply
// with major step size
$stepStart = new ezcGraphCoordinate(
$position->x - $direction->y * $size,
$position->y + $direction->x * $size
);
$drawStep = true;
}
else
{
$stepStart = $position;
}
if ( ( ( $axisPosition === ezcGraph::CENTER ) && $this->innerStep ) ||
( ( $axisPosition === ezcGraph::BOTTOM ) && $this->innerStep ) ||
( ( $axisPosition === ezcGraph::TOP ) && $this->outerStep ) ||
( ( $axisPosition === ezcGraph::RIGHT ) && $this->innerStep ) ||
( ( $axisPosition === ezcGraph::LEFT ) && $this->outerStep ) )
{
// Turn direction vector to right by 90 degrees and multiply
// with major step size
$stepEnd = new ezcGraphCoordinate(
$position->x + $direction->y * $size,
$position->y - $direction->x * $size
);
$drawStep = true;
}
else
{
$stepEnd = $position;
}
if ( $drawStep )
{
$renderer->drawStepLine(
$stepStart,
$stepEnd,
$color
);
}
}
/**
* Draw grid
*
* Draws a grid line at the current position
*
* @param ezcGraphRenderer $renderer Renderer to draw the grid with
* @param ezcGraphBoundings $boundings Boundings of axis
* @param ezcGraphCoordinate $position Position of step
* @param ezcGraphCoordinate $direction Direction of axis
* @param ezcGraphColor $color Color of axis
* @return void
*/
protected function drawGrid( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, ezcGraphColor $color )
{
// Direction of grid line is direction of axis turned right by 90
// degrees
$gridDirection = new ezcGraphCoordinate(
$direction->y,
- $direction->x
);
$cuttingPoints = array();
foreach ( array( // Bounding lines
array(
'start' => new ezcGraphCoordinate( $boundings->x0, $boundings->y0 ),
'dir' => new ezcGraphCoordinate( 0, $boundings->y1 - $boundings->y0 )
),
array(
'start' => new ezcGraphCoordinate( $boundings->x0, $boundings->y0 ),
'dir' => new ezcGraphCoordinate( $boundings->x1 - $boundings->x0, 0 )
),
array(
'start' => new ezcGraphCoordinate( $boundings->x1, $boundings->y1 ),
'dir' => new ezcGraphCoordinate( 0, $boundings->y0 - $boundings->y1 )
),
array(
'start' => new ezcGraphCoordinate( $boundings->x1, $boundings->y1 ),
'dir' => new ezcGraphCoordinate( $boundings->x0 - $boundings->x1, 0 )
),
) as $boundingLine )
{
// Test for cutting points with bounding lines, where cutting
// position is between 0 and 1, which means, that the line is hit
// on the bounding box rectangle. Use these points as a start and
// ending point for the grid lines. There should *always* be
// exactly two points returned.
$cuttingPosition = $this->determineLineCuttingPoint(
$boundingLine['start'],
$boundingLine['dir'],
$position,
$gridDirection
);
if ( $cuttingPosition === false )
{
continue;
}
// Round to prevent minor float incorectnesses
$cuttingPosition = abs( round( $cuttingPosition, 2 ) );
if ( ( $cuttingPosition >= 0 ) &&
( $cuttingPosition <= 1 ) )
{
$cuttingPoints[] = new ezcGraphCoordinate(
$boundingLine['start']->x + $cuttingPosition * $boundingLine['dir']->x,
$boundingLine['start']->y + $cuttingPosition * $boundingLine['dir']->y
);
}
}
if ( count( $cuttingPoints ) < 2 )
{
// This should not happpen
return false;
}
// Finally draw grid line
$renderer->drawGridLine(
$cuttingPoints[0],
$cuttingPoints[1],
$color
);
}
/**
* Modify chart boundings
*
* Optionally modify boundings of chart data
*
* @param ezcGraphBoundings $boundings Current boundings of chart
* @param ezcGraphCoordinate $direction Direction of the current axis
* @return ezcGraphBoundings Modified boundings
*/
public function modifyChartBoundings( ezcGraphBoundings $boundings, ezcGraphCoordinate $direction )
{
return $boundings;
}
/**
* Modify chart data position
*
* Optionally additionally modify the coodinate of a data point
*
* @param ezcGraphCoordinate $coordinate Data point coordinate
* @return ezcGraphCoordinate Modified coordinate
*/
public function modifyChartDataPosition( ezcGraphCoordinate $coordinate )
{
return $coordinate;
}
/**
* Render Axis labels
*
* Render labels for an axis.
*
* @param ezcGraphRenderer $renderer Renderer used to draw the chart
* @param ezcGraphBoundings $boundings Boundings of the axis
* @param ezcGraphCoordinate $start Axis starting point
* @param ezcGraphCoordinate $end Axis ending point
* @param ezcGraphChartElementAxis $axis Axis instance
* @return void
*/
abstract public function renderLabels(
ezcGraphRenderer $renderer,
ezcGraphBoundings $boundings,
ezcGraphCoordinate $start,
ezcGraphCoordinate $end,
ezcGraphChartElementAxis $axis
);
}
?>
@@ -0,0 +1,288 @@
<?php
/**
* File containing the abstract ezcGraphChart class
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Class to represent a complete chart.
*
* @property ezcGraphRenderer $renderer
* Renderer used to render chart
* @property ezcGraphDriver $driver
* Output driver used for chart
* @property ezcGraphPalette $palette
* Palette used for colorization of chart
* @property-read mixed $renderedFile
* Contains the filename of the rendered file, if rendered.
*
* @package Graph
* @version 1.3
*/
abstract class ezcGraphChart
{
/**
* Contains all general chart options
*
* @var ezcGraphChartConfig
*/
protected $options;
/**
* Contains subelelemnts of the chart like legend and axes
*
* @var array(ezcGraphChartElement)
*/
protected $elements = array();
/**
* Contains the data of the chart
*
* @var ezcGraphChartDataContainer
*/
protected $data;
/**
* Array containing chart properties
*
* @var array
*/
protected $properties;
/**
* Contains the status wheather an element should be rendered
*
* @var array
*/
protected $renderElement;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->palette = new ezcGraphPaletteTango();
$this->data = new ezcGraphChartDataContainer( $this );
// Add standard elements
$this->addElement( 'background', new ezcGraphChartElementBackground() );
$this->elements['background']->position = ezcGraph::CENTER | ezcGraph::MIDDLE;
$this->addElement( 'title', new ezcGraphChartElementText() );
$this->elements['title']->position = ezcGraph::TOP;
$this->renderElement['title'] = false;
$this->addElement( 'legend', new ezcGraphChartElementLegend() );
$this->elements['legend']->position = ezcGraph::LEFT;
// Define standard renderer and driver
$this->properties['driver'] = new ezcGraphSvgDriver();
$this->properties['renderer'] = new ezcGraphRenderer2d();
$this->properties['renderer']->setDriver( $this->driver );
// Initialize other properties
$this->properties['renderedFile'] = null;
}
/**
* Add element to chart
*
* Add a chart element to the chart and perform the required configuration
* tasks for the chart element.
*
* @param string $name Element name
* @param ezcGraphChartElement $element Chart element
* @return void
*/
protected function addElement( $name, ezcGraphChartElement $element )
{
$this->elements[$name] = $element;
$this->elements[$name]->font = $this->options->font;
$this->elements[$name]->setFromPalette( $this->palette );
// Render element by default
$this->renderElement[$name] = true;
}
/**
* Options write access
*
* @throws ezcBasePropertyNotFoundException
* If Option could not be found
* @throws ezcBaseValueException
* If value is out of range
* @param mixed $propertyName Option name
* @param mixed $propertyValue Option value;
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName ) {
case 'title':
$this->elements['title']->title = $propertyValue;
$this->renderElement['title'] = true;
break;
case 'legend':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'boolean' );
}
$this->renderElement['legend'] = (bool) $propertyValue;
break;
case 'renderer':
if ( $propertyValue instanceof ezcGraphRenderer )
{
$this->properties['renderer'] = $propertyValue;
$this->properties['renderer']->setDriver( $this->driver );
return $this->properties['renderer'];
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphRenderer' );
}
break;
case 'driver':
if ( $propertyValue instanceof ezcGraphDriver )
{
$this->properties['driver'] = $propertyValue;
$this->properties['renderer']->setDriver( $this->driver );
return $this->properties['driver'];
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphDriver' );
}
break;
case 'palette':
if ( $propertyValue instanceof ezcGraphPalette )
{
$this->properties['palette'] = $propertyValue;
$this->setFromPalette( $this->palette );
}
else
{
throw new ezcBaseValueException( "palette", $propertyValue, "instanceof ezcGraphPalette" );
}
break;
case 'renderedFile':
$this->properties['renderedFile'] = (string) $propertyValue;
break;
case 'options':
if ( $propertyValue instanceof ezcGraphChartOptions )
{
$this->options = $propertyValue;
}
else
{
throw new ezcBaseValueException( "options", $propertyValue, "instanceof ezcGraphOptions" );
}
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
break;
}
}
/**
* Set colors and border fro this element
*
* @param ezcGraphPalette $palette Palette
* @return void
*/
public function setFromPalette( ezcGraphPalette $palette )
{
$this->options->font->name = $palette->fontName;
$this->options->font->color = $palette->fontColor;
foreach ( $this->elements as $element )
{
$element->setFromPalette( $palette );
}
}
/**
* __get
*
* @param mixed $propertyName
* @throws ezcBasePropertyNotFoundException
* If a the value for the property options is not an instance of
* @return mixed
* @ignore
*/
public function __get( $propertyName )
{
if ( array_key_exists( $propertyName, $this->properties ) )
{
return $this->properties[$propertyName];
}
if ( isset( $this->elements[$propertyName] ) )
{
return $this->elements[$propertyName];
}
if ( ( $propertyName === 'options' ) ||
( $propertyName === 'data' ) )
{
return $this->$propertyName;
}
else
{
throw new ezcGraphNoSuchElementException( $propertyName );
}
}
/**
* Returns the default display type of the current chart type.
*
* @return int Display type
*/
abstract public function getDefaultDisplayType();
/**
* Return filename of rendered file, and false if no file was yet rendered.
*
* @return mixed
*/
public function getRenderedFile()
{
return ( $this->renderedFile !== null ? $this->renderedFile : false );
}
/**
* Renders this chart
*
* Creates basic visual chart elements from the chart to be processed by
* the renderer.
*
* @param int $width
* @param int $height
* @param string $file
* @return void
*/
abstract public function render( $width, $height, $file = null );
/**
* Renders this chart to direct output
*
* Does the same as ezcGraphChart::render(), but renders directly to
* output and not into a file.
*
* @param int $width
* @param int $height
* @return void
*/
abstract public function renderToOutput( $width, $height );
}
?>
@@ -0,0 +1,179 @@
<?php
/**
* File containing the abstract ezcGraphDataSetProperty class
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Abstract class for properties of datasets
*
* @version 1.3
* @package Graph
*/
abstract class ezcGraphDataSetProperty implements ArrayAccess
{
/**
* Default value for this property
*
* @var mixed
*/
protected $defaultValue;
/**
* Contains specified values for single dataset elements
*
* @var array
*/
protected $dataValue;
/**
* Contains a reference to the dataset to check for availability of data
* keys
*
* @var ezcGraphDataSet
*/
protected $dataset;
/**
* Abstract method to contain the check for validity of the value
*
* @param mixed $value
* @return void
*/
abstract protected function checkValue( &$value );
/**
* Constructor
*
* @param ezcGraphDataSet $dataset
* @ignore
* @return void
*/
public function __construct( ezcGraphDataSet $dataset )
{
$this->dataset = $dataset;
}
/**
* Set the default value for this property
*
* @param string $name Property name
* @param mixed $value Property value
* @return void
*/
public function __set( $name, $value )
{
if ( $name === 'default' &&
$this->checkValue( $value ) )
{
$this->defaultValue = $value;
}
}
/**
* Get the default value for this property
*
* @param string $name Property name
* @return mixed
*/
public function __get( $name )
{
if ( $name === 'default' )
{
return $this->defaultValue;
}
}
/**
* Returns if an option exists.
* Allows isset() using ArrayAccess.
*
* @param string $key The name of the option to get.
* @return bool Wether the option exists.
*/
final public function offsetExists( $key )
{
return isset( $this->dataset[$key] );
}
/**
* Returns an option value.
* Get an option value by ArrayAccess.
*
* @param string $key The name of the option to get.
* @return mixed The option value.
*
* @throws ezcBasePropertyNotFoundException
* If a the value for the property options is not an instance of
*/
final public function offsetGet( $key )
{
if ( isset( $this->dataValue[$key] ) )
{
return $this->dataValue[$key];
}
elseif ( isset( $this->dataset[$key] ) )
{
return $this->defaultValue;
}
else
{
throw new ezcGraphNoSuchDataException( $key );
}
}
/**
* Set an option.
* Sets an option using ArrayAccess.
*
* @param string $key The option to set.
* @param mixed $value The value for the option.
* @return void
*
* @throws ezcBasePropertyNotFoundException
* If a the value for the property options is not an instance of
* @throws ezcBaseValueException
* If a the value for a property is out of range.
*/
public function offsetSet( $key, $value )
{
if ( isset( $this->dataset[$key] ) &&
$this->checkValue( $value ) )
{
$this->dataValue[$key] = $value;
}
else
{
throw new ezcGraphNoSuchDataException( $key );
}
}
/**
* Unset an option.
* Unsets an option using ArrayAccess.
*
* @param string $key The options to unset.
* @return void
*
* @throws ezcBasePropertyNotFoundException
* If a the value for the property options is not an instance of
* @throws ezcBaseValueException
* If a the value for a property is out of range.
*/
final public function offsetUnset( $key )
{
if ( isset( $this->dataset[$key] ) )
{
unset( $this->dataValue[$key] );
}
else
{
throw new ezcGraphNoSuchDataException( $key );
}
}
}
?>
@@ -0,0 +1,740 @@
<?php
/**
* File containing the abstract ezcGraphDriver class
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Abstract class to be extended for ezcGraph output drivers.
*
* @version 1.3
* @package Graph
*/
abstract class ezcGraphDriver
{
/**
* Driveroptions
*
* @var ezcDriverOptions
*/
protected $options;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
abstract public function __construct( array $options = array() );
/**
* Options write access
*
* @throws ezcBasePropertyNotFoundException
* If Option could not be found
* @throws ezcBaseValueException
* If value is out of range
* @param mixed $propertyName Option name
* @param mixed $propertyValue Option value;
* @return mixed
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName ) {
case 'options':
if ( $propertyValue instanceof ezcGraphDriverOptions )
{
$this->options = $propertyValue;
}
else
{
throw new ezcBaseValueException( "options", $propertyValue, "instanceof ezcGraphOptions" );
}
break;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
break;
}
}
/**
* __get
*
* @param mixed $propertyName
* @throws ezcBasePropertyNotFoundException
* If a the value for the property options is not an instance of
* @return mixed
* @ignore
*/
public function __get( $propertyName )
{
switch ( $propertyName )
{
case 'options':
return $this->options;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
}
}
/**
* Reduces the size of a polygon
*
* The method takes a polygon defined by a list of points and reduces its
* size by moving all lines to the middle by the given $size value.
*
* The detection of the inner side of the polygon depends on the angle at
* each edge point. This method will always work for 3 edged polygones,
* because the smaller angle will always be on the inner side. For
* polygons with more then 3 edges this method may fail. For ezcGraph this
* is a valid simplification, because we do not have any polygones which
* have an inner angle >= 180 degrees.
*
* @param array(ezcGraphCoordinate) $points
* @param float $size
* @throws ezcGraphReducementFailedException
* @return array( ezcGraphCoordinate )
*/
protected function reducePolygonSize( array $points, $size )
{
$pointCount = count( $points );
// Build normalized vectors between polygon edge points
$vectors = array();
$vectorLength = array();
for ( $i = 0; $i < $pointCount; ++$i )
{
$nextPoint = ( $i + 1 ) % $pointCount;
$vectors[$i] = ezcGraphVector::fromCoordinate( $points[$nextPoint] )
->sub( $points[$i] );
// Throw exception if polygon is too small to reduce
$vectorLength[$i] = $vectors[$i]->length();
if ( $vectorLength[$i] < $size )
{
throw new ezcGraphReducementFailedException();
}
$vectors[$i]->unify();
// Remove point from list if it the same as the next point
if ( ( $vectors[$i]->x == $vectors[$i]->y ) && ( $vectors[$i]->x == 0 ) )
{
$pointCount--;
if ( $i === 0 )
{
$points = array_slice( $points, $i + 1 );
}
else
{
$points = array_merge(
array_slice( $points, 0, $i ),
array_slice( $points, $i + 1 )
);
}
$i--;
}
}
// Remove vectors and appendant point, if local angle equals zero
// dergrees.
for ( $i = 0; $i < $pointCount; ++$i )
{
$nextPoint = ( $i + 1 ) % $pointCount;
if ( ( abs( $vectors[$i]->x - $vectors[$nextPoint]->x ) < .0001 ) &&
( abs( $vectors[$i]->y - $vectors[$nextPoint]->y ) < .0001 ) )
{
$pointCount--;
$points = array_merge(
array_slice( $points, 0, $i + 1 ),
array_slice( $points, $i + 2 )
);
$vectors = array_merge(
array_slice( $vectors, 0, $i + 1 ),
array_slice( $vectors, $i + 2 )
);
$i--;
}
}
// No reducements for lines
if ( $pointCount <= 2 )
{
return $points;
}
// Determine one of the angles - we need to know where the smaller
// angle is, to determine if the inner side of the polygon is on
// the left or right hand.
//
// This is a valid simplification for ezcGraph(, for now).
//
// The sign of the scalar products results indicates on which site
// the smaller angle is, when comparing the orthogonale vector of
// one of the vectors with the other. Why? .. use pen and paper ..
//
// It is sufficant to do this once before iterating over the points,
// because the inner side of the polygon is on the same side of the
// point for each point.
$last = 0;
$next = 1;
$sign = (
-$vectors[$last]->y * $vectors[$next]->x +
$vectors[$last]->x * $vectors[$next]->y
) < 0 ? 1 : -1;
// Move points to center
$newPoints = array();
for ( $i = 0; $i < $pointCount; ++$i )
{
$last = $i;
$next = ( $i + 1 ) % $pointCount;
// Orthogonal vector with direction based on the side of the inner
// angle
$v = clone $vectors[$next];
if ( $sign > 0 )
{
$v->rotateCounterClockwise()->scalar( $size );
}
else
{
$v->rotateClockwise()->scalar( $size );
}
// get last vector not pointing in reverse direction
$lastVector = clone $vectors[$last];
$lastVector->scalar( -1 );
// Calculate new point: Move point to the center site of the
// polygon using the normalized orthogonal vectors next to the
// point and the size as distance to move.
// point + v + size / tan( angle / 2 ) * startVector
$newPoint = clone $vectors[$next];
$v ->add(
$newPoint
->scalar(
$size /
tan(
$lastVector->angle( $vectors[$next] ) / 2
)
)
);
// A fast guess: If the movement of the point exceeds the length of
// the surrounding edge vectors the angle was to small to perform a
// valid size reducement. In this case we just reduce the length of
// the movement to the minimal length of the surrounding vectors.
// This should fit in most cases.
//
// The correct way to check would be a test, if the calculated
// point is still in the original polygon, but a test for a point
// in a polygon is too expensive.
$movement = $v->length();
if ( ( $movement > $vectorLength[$last] ) &&
( $movement > $vectorLength[$next] ) )
{
$v->unify()->scalar( min( $vectorLength[$last], $vectorLength[$next] ) );
}
$newPoints[$next] = $v->add( $points[$next] );
}
return $newPoints;
}
/**
* Reduce the size of an ellipse
*
* The method returns a the edgepoints and angles for an ellipse where all
* borders are moved to the inner side of the ellipse by the give $size
* value.
*
* The method returns an
* array (
* 'center' => (ezcGraphCoordinate) New center point,
* 'start' => (ezcGraphCoordinate) New outer start point,
* 'end' => (ezcGraphCoordinate) New outer end point,
* )
*
* @param ezcGraphCoordinate $center
* @param float $width
* @param float $height
* @param float $startAngle
* @param float $endAngle
* @param float $size
* @throws ezcGraphReducementFailedException
* @return array
*/
protected function reduceEllipseSize( ezcGraphCoordinate $center, $width, $height, $startAngle, $endAngle, $size )
{
$oldStartPoint = new ezcGraphVector(
$width * cos( deg2rad( $startAngle ) ) / 2,
$height * sin( deg2rad( $startAngle ) ) / 2
);
$oldEndPoint = new ezcGraphVector(
$width * cos( deg2rad( $endAngle ) ) / 2,
$height * sin( deg2rad( $endAngle ) ) / 2
);
// We always need radian values..
$degAngle = abs( $endAngle - $startAngle );
$startAngle = deg2rad( $startAngle );
$endAngle = deg2rad( $endAngle );
// Calculate normalized vectors for the lines spanning the ellipse
$unifiedStartVector = ezcGraphVector::fromCoordinate( $oldStartPoint )->unify();
$unifiedEndVector = ezcGraphVector::fromCoordinate( $oldEndPoint )->unify();
$startVector = ezcGraphVector::fromCoordinate( $oldStartPoint );
$endVector = ezcGraphVector::fromCoordinate( $oldEndPoint );
$oldStartPoint->add( $center );
$oldEndPoint->add( $center );
// Use orthogonal vectors of normalized ellipse spanning vectors to
$v = clone $unifiedStartVector;
$v->rotateClockwise()->scalar( $size );
// calculate new center point
// center + v + size / tan( angle / 2 ) * startVector
$centerMovement = clone $unifiedStartVector;
$newCenter = $v->add( $centerMovement->scalar( $size / tan( ( $endAngle - $startAngle ) / 2 ) ) )->add( $center );
// Test if center is still inside the ellipse, otherwise the sector
// was to small to be reduced
$innerBoundingBoxSize = 0.7 * min( $width, $height );
if ( ( $newCenter->x < ( $center->x + $innerBoundingBoxSize ) ) &&
( $newCenter->x > ( $center->x - $innerBoundingBoxSize ) ) &&
( $newCenter->y < ( $center->y + $innerBoundingBoxSize ) ) &&
( $newCenter->y > ( $center->y - $innerBoundingBoxSize ) ) )
{
// Point is in inner bounding box -> everything is OK
}
elseif ( ( $newCenter->x < ( $center->x - $width ) ) ||
( $newCenter->x > ( $center->x + $width ) ) ||
( $newCenter->y < ( $center->y - $height ) ) ||
( $newCenter->y > ( $center->y + $height ) ) )
{
// Quick outer boundings check
if ( $degAngle > 180 )
{
// Use old center for very big angles
$newCenter = clone $center;
}
else
{
// Do not draw for very small angles
throw new ezcGraphReducementFailedException();
}
}
else
{
// Perform exact check
$distance = new ezcGraphVector(
$newCenter->x - $center->x,
$newCenter->y - $center->y
);
// Convert elipse to circle for correct angle calculation
$direction = clone $distance;
$direction->y *= ( $width / $height );
$angle = $direction->angle( new ezcGraphVector( 0, 1 ) );
$outerPoint = new ezcGraphVector(
sin( $angle ) * $width / 2,
cos( $angle ) * $height / 2
);
// Point is not in ellipse any more
if ( abs( $distance->x ) > abs( $outerPoint->x ) )
{
if ( $degAngle > 180 )
{
// Use old center for very big angles
$newCenter = clone $center;
}
else
{
// Do not draw for very small angles
throw new ezcGraphReducementFailedException();
}
}
}
// Use start spanning vector and its orthogonal vector to calculate
// new start point
$newStartPoint = clone $oldStartPoint;
// Create tangent vector from tangent angle
// Ellipse tangent factor
$ellipseTangentFactor = sqrt(
pow( $height, 2 ) *
pow( cos( $startAngle ), 2 ) +
pow( $width, 2 ) *
pow( sin( $startAngle ), 2 )
);
$ellipseTangentVector = new ezcGraphVector(
$width * -sin( $startAngle ) / $ellipseTangentFactor,
$height * cos( $startAngle ) / $ellipseTangentFactor
);
// Reverse spanning vector
$innerVector = clone $unifiedStartVector;
$innerVector->scalar( $size )->scalar( -1 );
$newStartPoint->add( $innerVector)->add( $ellipseTangentVector->scalar( $size ) );
$newStartVector = clone $startVector;
$newStartVector->add( $ellipseTangentVector );
// Use end spanning vector and its orthogonal vector to calculate
// new end point
$newEndPoint = clone $oldEndPoint;
// Create tangent vector from tangent angle
// Ellipse tangent factor
$ellipseTangentFactor = sqrt(
pow( $height, 2 ) *
pow( cos( $endAngle ), 2 ) +
pow( $width, 2 ) *
pow( sin( $endAngle ), 2 )
);
$ellipseTangentVector = new ezcGraphVector(
$width * -sin( $endAngle ) / $ellipseTangentFactor,
$height * cos( $endAngle ) / $ellipseTangentFactor
);
// Reverse spanning vector
$innerVector = clone $unifiedEndVector;
$innerVector->scalar( $size )->scalar( -1 );
$newEndPoint->add( $innerVector )->add( $ellipseTangentVector->scalar( $size )->scalar( -1 ) );
$newEndVector = clone $endVector;
$newEndVector->add( $ellipseTangentVector );
return array(
'center' => $newCenter,
'start' => $newStartPoint,
'end' => $newEndPoint,
'startAngle' => rad2deg( $startAngle + $startVector->angle( $newStartVector ) ),
'endAngle' => rad2deg( $endAngle - $endVector->angle( $newEndVector ) ),
);
}
/**
* Draws a single polygon.
*
* @param array $points Point array
* @param ezcGraphColor $color Polygon color
* @param mixed $filled Filled
* @param float $thickness Line thickness
* @return void
*/
abstract public function drawPolygon( array $points, ezcGraphColor $color, $filled = true, $thickness = 1. );
/**
* Draws a line
*
* @param ezcGraphCoordinate $start Start point
* @param ezcGraphCoordinate $end End point
* @param ezcGraphColor $color Line color
* @param float $thickness Line thickness
* @return void
*/
abstract public function drawLine( ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphColor $color, $thickness = 1. );
/**
* Returns boundings of text depending on the available font extension
*
* @param float $size Textsize
* @param ezcGraphFontOptions $font Font
* @param string $text Text
* @return ezcGraphBoundings Boundings of text
*/
abstract protected function getTextBoundings( $size, ezcGraphFontOptions $font, $text );
/**
* Test if string fits in a box with given font size
*
* This method splits the text up into tokens and tries to wrap the text
* in an optimal way to fit in the Box defined by width and height.
*
* If the text fits into the box an array with lines is returned, which
* can be used to render the text later:
* array(
* // Lines
* array( 'word', 'word', .. ),
* )
* Otherwise the function will return false.
*
* @param string $string Text
* @param ezcGraphCoordinate $position Topleft position of the text box
* @param float $width Width of textbox
* @param float $height Height of textbox
* @param int $size Fontsize
* @return mixed Array with lines or false on failure
*/
protected function testFitStringInTextBox( $string, ezcGraphCoordinate $position, $width, $height, $size )
{
// Tokenize String
$tokens = preg_split( '/\s+/', $string );
$initialHeight = $height;
$lines = array( array() );
$line = 0;
foreach ( $tokens as $nr => $token )
{
// Add token to tested line
$selectedLine = $lines[$line];
$selectedLine[] = $token;
$boundings = $this->getTextBoundings( $size, $this->options->font, implode( ' ', $selectedLine ) );
// Check if line is too long
if ( $boundings->width > $width )
{
if ( count( $selectedLine ) == 1 )
{
// Return false if one single word does not fit into one line
// Scale down font size to fit this word in one line
return $width / $boundings->width;
}
else
{
// Put word in next line instead and reduce available height by used space
$lines[++$line][] = $token;
$height -= $size * ( 1 + $this->options->lineSpacing );
}
}
else
{
// Everything is ok - put token in this line
$lines[$line][] = $token;
}
// Return false if text exceeds vertical limit
if ( $size > $height )
{
return 1;
}
}
// Check width of last line
$boundings = $this->getTextBoundings( $size, $this->options->font, implode( ' ', $lines[$line] ) );
if ( $boundings->width > $width )
{
return 1;
}
// It seems to fit - return line array
return $lines;
}
/**
* If it is allow to shortened the string, this method tries to extract as
* many chars as possible to display a decent amount of characters.
*
* If no complete token (word) does fit, the largest possible amount of
* chars from the first word are taken. If the amount of chars is bigger
* then strlen( shortenedStringPostFix ) * 2 the last chars are replace by
* the postfix.
*
* If one complete word fits the box as many words are taken as possible
* including a appended shortenedStringPostFix.
*
* @param mixed $string
* @param ezcGraphCoordinate $position
* @param mixed $width
* @param mixed $height
* @param mixed $size
* @access protected
* @return void
*/
protected function tryFitShortenedString( $string, ezcGraphCoordinate $position, $width, $height, $size )
{
$tokens = preg_split( '/\s+/', $string );
// Try to fit a complete word first
$boundings = $this->getTextBoundings(
$size,
$this->options->font,
reset( $tokens ) . ( $postfix = $this->options->autoShortenStringPostFix )
);
if ( $boundings->width > $width )
{
// Not even one word fits the box
$word = reset( $tokens );
// Test if first character fits the box
$boundigs = $this->getTextBoundings(
$size,
$this->options->font,
$hit = $word[0]
);
if ( $boundigs->width > $width )
{
// That is a really small box.
throw new ezcGraphFontRenderingException( $string, $size, $width, $height );
}
// Try to put more charactes in there
$postLength = strlen( $postfix );
$wordLength = strlen( $word );
for ( $i = 2; $i <= $wordLength; ++$i )
{
$string = substr( $word, 0, $i );
if ( strlen( $string ) > ( $postLength << 1 ) )
{
$string = substr( $string, 0, -$postLength ) . $postfix;
}
$boundigs = $this->getTextBoundings( $size, $this->options->font, $string );
if ( $boundigs->width < $width )
{
$hit = $string;
}
else
{
// Use last string which fit
break;
}
}
}
else
{
// Try to use as many words as possible
$hit = reset( $tokens );
for ( $i = 2; $i < count( $tokens ); ++$i )
{
$string = implode( ' ', array_slice( $tokens, 0, $i ) ) .
$postfix;
$boundings = $this->getTextBoundings( $size, $this->options->font, $string );
if ( $boundings->width <= $width )
{
$hit .= ' ' . $tokens[$i - 1];
}
else
{
// Use last valid hit
break;
}
}
$hit .= $postfix;
}
return array( array( $hit ) );
}
/**
* Writes text in a box of desired size
*
* @param string $string Text
* @param ezcGraphCoordinate $position Top left position
* @param float $width Width of text box
* @param float $height Height of text box
* @param int $align Alignement of text
* @param ezcGraphRotation $rotation
* @return void
*/
abstract public function drawTextBox( $string, ezcGraphCoordinate $position, $width, $height, $align, ezcGraphRotation $rotation = null );
/**
* Draws a sector of cirlce
*
* @param ezcGraphCoordinate $center Center of circle
* @param mixed $width Width
* @param mixed $height Height
* @param mixed $startAngle Start angle of circle sector
* @param mixed $endAngle End angle of circle sector
* @param ezcGraphColor $color Color
* @param mixed $filled Filled
* @return void
*/
abstract public function drawCircleSector( ezcGraphCoordinate $center, $width, $height, $startAngle, $endAngle, ezcGraphColor $color, $filled = true );
/**
* Draws a circular arc
*
* @param ezcGraphCoordinate $center Center of ellipse
* @param integer $width Width of ellipse
* @param integer $height Height of ellipse
* @param integer $size Height of border
* @param float $startAngle Starting angle of circle sector
* @param float $endAngle Ending angle of circle sector
* @param ezcGraphColor $color Color of Border
* @param bool $filled Fill state
* @return void
*/
abstract public function drawCircularArc( ezcGraphCoordinate $center, $width, $height, $size, $startAngle, $endAngle, ezcGraphColor $color, $filled = true );
/**
* Draw circle
*
* @param ezcGraphCoordinate $center Center of ellipse
* @param mixed $width Width of ellipse
* @param mixed $height height of ellipse
* @param ezcGraphColor $color Color
* @param mixed $filled Filled
* @return void
*/
abstract public function drawCircle( ezcGraphCoordinate $center, $width, $height, ezcGraphColor $color, $filled = true );
/**
* Draw an image
*
* @param mixed $file Image file
* @param ezcGraphCoordinate $position Top left position
* @param mixed $width Width of image in destination image
* @param mixed $height Height of image in destination image
* @return void
*/
abstract public function drawImage( $file, ezcGraphCoordinate $position, $width, $height );
/**
* Return mime type for current image format
*
* @return string
*/
abstract public function getMimeType();
/**
* Render image directly to output
*
* The method renders the image directly to the standard output. You
* normally do not want to use this function, because it makes it harder
* to proper cache the generated graphs.
*
* @return void
*/
public function renderToOutput()
{
header( 'Content-Type: ' . $this->getMimeType() );
$this->render( 'php://output' );
}
/**
* Finally save image
*
* @param string $file Destination filename
* @return void
*/
abstract public function render( $file );
}
?>
@@ -0,0 +1,280 @@
<?php
/**
* File containing the abstract ezcGraphChartElement class
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Class for basic chart elements
*
* @property string $title
* Title of chart element.
* @property ezcGraphColor $background
* Background color of chart element.
* @property ezcGraphColor $border
* Border color of chart element.
* @property int $padding
* Distance between border and content of element.
* @property int $margin
* Distance between outer boundings and border of an element.
* @property int $borderWidth
* Border width.
* @property int $position
* Integer defining the elements position in the chart.
* @property int $maxTitleHeight
* Maximum size of the title.
* @property float $portraitTitleSize
* Percentage of boundings which are used for the title with
* position left, right or center.
* @property float $landscapeTitleSize
* Percentage of boundings which are used for the title with
* position top or bottom.
* @property ezcGraphFontOptions $font
* Font used for this element.
* @property-read bool $fontCloned
* Indicates if font configuration was already cloned for this
* specific element.
* @property-read ezcGraphBoundings $boundings
* Boundings of this elements.
*
* @version 1.3
* @package Graph
*/
abstract class ezcGraphChartElement extends ezcBaseOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['title'] = false;
$this->properties['background'] = false;
$this->properties['boundings'] = new ezcGraphBoundings();
$this->properties['border'] = false;
$this->properties['borderWidth'] = 0;
$this->properties['padding'] = 0;
$this->properties['margin'] = 0;
$this->properties['position'] = ezcGraph::LEFT;
$this->properties['maxTitleHeight'] = 16;
$this->properties['portraitTitleSize'] = .15;
$this->properties['landscapeTitleSize'] = .2;
$this->properties['font'] = new ezcGraphFontOptions();
$this->properties['fontCloned'] = false;
parent::__construct( $options );
}
/**
* Set colors and border fro this element
*
* @param ezcGraphPalette $palette Palette
* @return void
*/
public function setFromPalette( ezcGraphPalette $palette )
{
$this->properties['border'] = $palette->elementBorderColor;
$this->properties['borderWidth'] = $palette->elementBorderWidth;
$this->properties['background'] = $palette->elementBackground;
$this->properties['padding'] = $palette->padding;
$this->properties['margin'] = $palette->margin;
}
/**
* __set
*
* @param mixed $propertyName
* @param mixed $propertyValue
* @throws ezcBaseValueException
* If a submitted parameter was out of range or type.
* @throws ezcBasePropertyNotFoundException
* If a the value for the property options is not an instance of
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'title':
$this->properties['title'] = (string) $propertyValue;
break;
case 'background':
$this->properties['background'] = ezcGraphColor::create( $propertyValue );
break;
case 'border':
$this->properties['border'] = ezcGraphColor::create( $propertyValue );
break;
case 'padding':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['padding'] = (int) $propertyValue;
break;
case 'margin':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['margin'] = (int) $propertyValue;
break;
case 'borderWidth':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['borderWidth'] = (int) $propertyValue;
break;
case 'font':
if ( $propertyValue instanceof ezcGraphFontOptions )
{
$this->properties['font'] = $propertyValue;
}
elseif ( is_string( $propertyValue ) )
{
if ( !$this->fontCloned )
{
$this->properties['font'] = clone $this->font;
$this->properties['fontCloned'] = true;
}
$this->properties['font']->path = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphFontOptions' );
}
break;
case 'position':
$positions = array(
ezcGraph::TOP,
ezcGraph::BOTTOM,
ezcGraph::LEFT,
ezcGraph::RIGHT,
);
if ( in_array( $propertyValue, $positions, true ) )
{
$this->properties['position'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( 'position', $propertyValue, 'integer' );
}
break;
case 'maxTitleHeight':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['maxTitleHeight'] = (int) $propertyValue;
break;
case 'portraitTitleSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['portraitTitleSize'] = (float) $propertyValue;
break;
case 'landscapeTitleSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['landscapeTitleSize'] = (float) $propertyValue;
break;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
break;
}
}
/**
* __get
*
* @param mixed $propertyName
* @throws ezcBasePropertyNotFoundException
* If a the value for the property options is not an instance of
* @return mixed
* @ignore
*/
public function __get( $propertyName )
{
switch ( $propertyName )
{
case 'font':
// Clone font configuration when requested for this element
if ( !$this->fontCloned )
{
$this->properties['font'] = clone $this->properties['font'];
$this->properties['fontCloned'] = true;
}
return $this->properties['font'];
default:
return parent::__get( $propertyName );
}
}
/**
* Renders this chart element
*
* This method receives and returns a part of the canvas where it can be
* rendered on.
*
* @param ezcGraphRenderer $renderer
* @param ezcGraphBoundings $boundings
* @return ezcGraphBoundings Part of canvas, which is still free to draw on
*/
abstract public function render( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings );
/**
* Returns calculated boundings based on available percentual space of
* given bounding box specified in the elements options and direction of
* the box.
*
* @param ezcGraphBoundings $boundings
* @param int $direction
* @return ezcGraphBoundings
*/
protected function getTitleSize( ezcGraphBoundings $boundings, $direction = ezcGraph::HORIZONTAL )
{
if ( $direction === ezcGraph::HORIZONTAL )
{
return min(
$this->maxTitleHeight,
( $boundings->y1 - $boundings->y0 ) * $this->landscapeTitleSize
);
}
else
{
return min(
$this->maxTitleHeight,
( $boundings->y1 - $boundings->y0 ) * $this->portraitTitleSize
);
}
}
}
?>
@@ -0,0 +1,51 @@
<?php
/**
* File containing the ezcGraphOdometerRenderer interface
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Interface which adds the methods required for rendering radar charts to a
* renderer
*
* @version 1.3
* @package Graph
*/
interface ezcGraphOdometerRenderer
{
/**
* Render odometer chart
*
* @param ezcGraphBoundings $boundings
* @param ezcGraphChartElementAxis $axis
* @param ezcGraphOdometerChartOptions $options
* @return ezcGraphBoundings
*/
public function drawOdometer(
ezcGraphBoundings $boundings,
ezcGraphChartElementAxis $axis,
ezcGraphOdometerChartOptions $options
);
/**
* Draw a single odometer marker.
*
* @param ezcGraphBoundings $boundings
* @param ezcGraphCoordinate $position
* @param int $symbol
* @param ezcGraphColor $color
* @param int $width
*/
public function drawOdometerMarker(
ezcGraphBoundings $boundings,
ezcGraphCoordinate $position,
$symbol,
ezcGraphColor $color,
$width
);
}
?>
@@ -0,0 +1,284 @@
<?php
/**
* File containing the abstract ezcGraphPalette class
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Abstract class to contain pallet definitions
*
* @version 1.3
* @package Graph
* @mainclass
*/
abstract class ezcGraphPalette
{
/**
* Indicates which color should be used for the next dataset
*
* @var integer
*/
protected $colorIndex = -1;
/**
* Indicates which symbol should be used for the nect dataset
*
* @var integer
*/
protected $symbolIndex = -1;
/**
* Axiscolor
*
* @var ezcGraphColor
*/
protected $axisColor;
/**
* Color of grid lines
*
* @var ezcGraphColor
*/
protected $majorGridColor;
/**
* Color of minor grid lines
*
* @var ezcGraphColor
*/
protected $minorGridColor;
/**
* Array with colors for datasets
*
* @var array
*/
protected $dataSetColor;
/**
* Array with symbols for datasets
*
* @var array
*/
protected $dataSetSymbol;
/**
* Name of font to use
*
* @var string
*/
protected $fontName;
/**
* Fontcolor
*
* @var ezcGraphColor
*/
protected $fontColor;
/**
* Backgroundcolor
*
* @var ezcGraphColor
*/
protected $chartBackground;
/**
* Bordercolor the chart
*
* @var ezcGraphColor
*/
protected $chartBorderColor;
/**
* Borderwidth for the chart
*
* @var integer
* @access protected
*/
protected $chartBorderWidth = 0;
/**
* Backgroundcolor for elements
*
* @var ezcGraphColor
*/
protected $elementBackground;
/**
* Bordercolor for elements
*
* @var ezcGraphColor
*/
protected $elementBorderColor;
/**
* Borderwidth for elements
*
* @var integer
* @access protected
*/
protected $elementBorderWidth = 0;
/**
* Padding in elements
*
* @var integer
*/
protected $padding = 1;
/**
* Margin of elements
*
* @var integer
*/
protected $margin = 0;
/**
* Ensure value to be a color
*
* @param mixed $color Color to transform into a ezcGraphColor object
* @return ezcGraphColor
*/
protected function checkColor( &$color )
{
if ( $color == null )
{
return ezcGraphColor::fromHex( '#000000FF' );
}
elseif ( !( $color instanceof ezcGraphColor ) )
{
$color = ezcGraphColor::create( $color );
}
return $color;
}
/**
* Manually reset the color counter to use the first color again
*
* @access public
*/
public function resetColorCounter()
{
$this->colorIndex = -1;
$this->symbolIndex = -1;
}
/**
* Returns the requested property
*
* @param string $propertyName Name of property
* @return mixed
* @ignore
*/
public function __get( $propertyName )
{
switch ( $propertyName )
{
case 'axisColor':
case 'majorGridColor':
case 'minorGridColor':
case 'fontColor':
case 'chartBackground':
case 'chartBorderColor':
case 'elementBackground':
case 'elementBorderColor':
return ( $this->$propertyName = $this->checkColor( $this->$propertyName ) );
case 'dataSetColor':
$this->colorIndex = ( ( $this->colorIndex + 1 ) % count( $this->dataSetColor ) );
return $this->checkColor( $this->dataSetColor[ $this->colorIndex ] );
case 'dataSetSymbol':
$this->symbolIndex = ( ( $this->symbolIndex + 1 ) % count( $this->dataSetSymbol ) );
return $this->dataSetSymbol[ $this->symbolIndex ];
case 'fontName':
case 'chartBorderWidth':
case 'elementBorderWidth':
case 'padding':
case 'margin':
return $this->$propertyName;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
}
}
/**
* __set
*
* @param mixed $propertyName Property name
* @param mixed $propertyValue Property value
* @access public
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'axisColor':
case 'majorGridColor':
case 'minorGridColor':
case 'fontColor':
case 'chartBackground':
case 'chartBorderColor':
case 'elementBackground':
case 'elementBorderColor':
$this->$propertyName = ezcGraphColor::create( $propertyValue );
break;
case 'dataSetColor':
if ( !is_array( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'array( ezcGraphColor )' );
}
$this->dataSetColor = array();
foreach ( $propertyValue as $value )
{
$this->dataSetColor[] = ezcGraphColor::create( $value );
}
$this->colorIndex = -1;
break;
case 'dataSetSymbol':
if ( !is_array( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'array( (int) ezcGraph::SYMBOL_TYPE )' );
}
$this->dataSetSymbol = array();
foreach ( $propertyValue as $value )
{
$this->dataSetSymbol[] = (int) $value;
}
$this->symbolIndex = -1;
break;
case 'fontName':
$this->$propertyName = (string) $propertyValue;
break;
case 'chartBorderWidth':
case 'elementBorderWidth':
case 'padding':
case 'margin':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->$propertyName = (int) $propertyValue;
break;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
}
}
}
?>
@@ -0,0 +1,54 @@
<?php
/**
* File containing the ezcGraphRadarRenderer interface
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Interface which adds the methods required for rendering radar charts to a
* renderer
*
* @version 1.3
* @package Graph
*/
interface ezcGraphRadarRenderer
{
/**
* Draw radar chart data line
*
* Draws a line as a data element in a radar chart
*
* @param ezcGraphBoundings $boundings Chart boundings
* @param ezcGraphContext $context Context of call
* @param ezcGraphColor $color Color of line
* @param ezcGraphCoordinate $center Center of radar chart
* @param ezcGraphCoordinate $start Starting point
* @param ezcGraphCoordinate $end Ending point
* @param int $dataNumber Number of dataset
* @param int $dataCount Count of datasets in chart
* @param int $symbol Symbol to draw for line
* @param ezcGraphColor $symbolColor Color of the symbol, defaults to linecolor
* @param ezcGraphColor $fillColor Color to fill line with
* @param float $thickness Line thickness
* @return void
*/
public function drawRadarDataLine(
ezcGraphBoundings $boundings,
ezcGraphContext $context,
ezcGraphColor $color,
ezcGraphCoordinate $center,
ezcGraphCoordinate $start,
ezcGraphCoordinate $end,
$dataNumber = 1,
$dataCount = 1,
$symbol = ezcGraph::NO_SYMBOL,
ezcGraphColor $symbolColor = null,
ezcGraphColor $fillColor = null,
$thickness = 1.
);
}
?>
@@ -0,0 +1,571 @@
<?php
/**
* File containing the abstract ezcGraphRenderer class
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Abstract class to transform the basic chart components. To be extended by
* three- and twodimensional renderers.
*
* @version 1.3
* @package Graph
*/
abstract class ezcGraphRenderer
{
/**
* Driver used to render results
*
* @var ezcGraphDriver
*/
protected $driver;
/**
* Axis space used for the x axis
*
* @var float
*/
protected $xAxisSpace = false;
/**
* Axis space used for the y axis
*
* @var float
*/
protected $yAxisSpace = false;
/**
* Context sensitive references to chart elements to use for referencing
* image elements depending on the output driver, like image maps, etc.
*
* @var array
*/
protected $elements = array();
/**
* Set renderers driver
*
* @param ezcGraphDriver $driver Output driver
* @return void
*/
public function setDriver( ezcGraphDriver $driver )
{
$this->driver = $driver;
}
/**
* Adds a element reference for context
*
* @param ezcGraphContext $context Dataoint context
* @param mixed $reference Driver dependant reference
* @return void
*/
protected function addElementReference( ezcGraphContext $context, $reference )
{
$this->elements['data'][$context->dataset][$context->datapoint][] = $reference;
}
/**
* Return all chart element references
*
* @return array chart element references
*/
public function getElementReferences()
{
return $this->elements;
}
/**
* __get
*
* @param string $propertyName
* @throws ezcBasePropertyNotFoundException
* If a the value for the property options is not an instance of
* @return mixed
* @ignore
*/
public function __get( $propertyName )
{
switch ( $propertyName )
{
case 'xAxisSpace':
case 'yAxisSpace':
return $this->$propertyName;
case 'elements':
return $this->elements;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
}
}
/**
* Draw pie segment
*
* Draws a single pie segment
*
* @param ezcGraphBoundings $boundings Chart boundings
* @param ezcGraphContext $context Context of call
* @param ezcGraphColor $color Color of pie segment
* @param float $startAngle Start angle
* @param float $endAngle End angle
* @param mixed $label Label of pie segment
* @param bool $moveOut Move out from middle for hilighting
* @return void
*/
abstract public function drawPieSegment(
ezcGraphBoundings $boundings,
ezcGraphContext $context,
ezcGraphColor $color,
$startAngle = .0,
$endAngle = 360.,
$label = false,
$moveOut = false
);
/**
* Draw bar
*
* Draws a bar as a data element in a line chart
*
* @param ezcGraphBoundings $boundings Chart boundings
* @param ezcGraphContext $context Context of call
* @param ezcGraphColor $color Color of line
* @param ezcGraphCoordinate $position Position of data point
* @param float $stepSize Space which can be used for bars
* @param int $dataNumber Number of dataset
* @param int $dataCount Count of datasets in chart
* @param int $symbol Symbol to draw for line
* @param float $axisPosition Position of axis for drawing filled lines
* @return void
*/
abstract public function drawBar(
ezcGraphBoundings $boundings,
ezcGraphContext $context,
ezcGraphColor $color,
ezcGraphCoordinate $position,
$stepSize,
$dataNumber = 1,
$dataCount = 1,
$symbol = ezcGraph::NO_SYMBOL,
$axisPosition = 0.
);
/**
* Draw data line
*
* Draws a line as a data element in a line chart
*
* @param ezcGraphBoundings $boundings Chart boundings
* @param ezcGraphContext $context Context of call
* @param ezcGraphColor $color Color of line
* @param ezcGraphCoordinate $start Starting point
* @param ezcGraphCoordinate $end Ending point
* @param int $dataNumber Number of dataset
* @param int $dataCount Count of datasets in chart
* @param int $symbol Symbol to draw for line
* @param ezcGraphColor $symbolColor Color of the symbol, defaults to linecolor
* @param ezcGraphColor $fillColor Color to fill line with
* @param float $axisPosition Position of axis for drawing filled lines
* @param float $thickness Line thickness
* @return void
*/
abstract public function drawDataLine(
ezcGraphBoundings $boundings,
ezcGraphContext $context,
ezcGraphColor $color,
ezcGraphCoordinate $start,
ezcGraphCoordinate $end,
$dataNumber = 1,
$dataCount = 1,
$symbol = ezcGraph::NO_SYMBOL,
ezcGraphColor $symbolColor = null,
ezcGraphColor $fillColor = null,
$axisPosition = 0.,
$thickness = 1.
);
/**
* Draws a highlight textbox for a datapoint.
*
* A highlight textbox for line and bar charts means a box with the current
* value in the graph.
*
* @param ezcGraphBoundings $boundings Chart boundings
* @param ezcGraphContext $context Context of call
* @param ezcGraphCoordinate $end Ending point
* @param float $axisPosition Position of axis for drawing filled lines
* @param int $dataNumber Number of dataset
* @param int $dataCount Count of datasets in chart
* @param ezcGraphFontOptions $font Font used for highlight string
* @param string $text Acutual value
* @param int $size Size of highlight text
* @param ezcGraphColor $markLines
* @return void
*/
abstract public function drawDataHighlightText(
ezcGraphBoundings $boundings,
ezcGraphContext $context,
ezcGraphCoordinate $end,
$axisPosition = 0.,
$dataNumber = 1,
$dataCount = 1,
ezcGraphFontOptions $font,
$text,
$size,
ezcGraphColor $markLines = null
);
/**
* Draw legend
*
* Will draw a legend in the bounding box
*
* @param ezcGraphBoundings $boundings Bounding of legend
* @param ezcGraphChartElementLegend $legend Legend to draw
* @param int $type Type of legend: Protrait or landscape
* @return void
*/
abstract public function drawLegend(
ezcGraphBoundings $boundings,
ezcGraphChartElementLegend $legend,
$type = ezcGraph::VERTICAL
);
/**
* Draw box
*
* Box are wrapping each major chart element and draw border, background
* and title to each chart element.
*
* Optionally a padding and margin for each box can be defined.
*
* @param ezcGraphBoundings $boundings Boundings of the box
* @param ezcGraphColor $background Background color
* @param ezcGraphColor $borderColor Border color
* @param int $borderWidth Border width
* @param int $margin Margin
* @param int $padding Padding
* @param mixed $title Title of the box
* @param int $titleSize Size of title in the box
* @return ezcGraphBoundings Remaining inner boundings
*/
abstract public function drawBox(
ezcGraphBoundings $boundings,
ezcGraphColor $background = null,
ezcGraphColor $borderColor = null,
$borderWidth = 0,
$margin = 0,
$padding = 0,
$title = false,
$titleSize = 16
);
/**
* Draw text
*
* Draws the provided text in the boundings
*
* @param ezcGraphBoundings $boundings Boundings of text
* @param string $text Text
* @param int $align Alignement of text
* @param ezcGraphRotation $rotation
* @return void
*/
abstract public function drawText(
ezcGraphBoundings $boundings,
$text,
$align = ezcGraph::LEFT,
ezcGraphRotation $rotation = null
);
/**
* Draw axis
*
* Draws an axis form the provided start point to the end point. A specific
* angle of the axis is not required.
*
* For the labeleing of the axis a sorted array with major steps and an
* array with minor steps is expected, which are build like this:
* array(
* array(
* 'position' => (float),
* 'label' => (string),
* )
* )
* where the label is optional.
*
* The label renderer class defines how the labels are rendered. For more
* documentation on this topic have a look at the basic label renderer
* class.
*
* Additionally it can be specified if a major and minor grid are rendered
* by defining a color for them. Teh axis label is used to add a caption
* for the axis.
*
* @param ezcGraphBoundings $boundings Boundings of axis
* @param ezcGraphCoordinate $start Start point of axis
* @param ezcGraphCoordinate $end Endpoint of axis
* @param ezcGraphChartElementAxis $axis Axis to render
* @param ezcGraphAxisLabelRenderer $labelClass Used label renderer
* @return void
*/
abstract public function drawAxis(
ezcGraphBoundings $boundings,
ezcGraphCoordinate $start,
ezcGraphCoordinate $end,
ezcGraphChartElementAxis $axis,
ezcGraphAxisLabelRenderer $labelClass = null
);
/**
* Draw background image
*
* Draws a background image at the defined position. If repeat is set the
* background image will be repeated like any texture.
*
* @param ezcGraphBoundings $boundings Boundings for the background image
* @param string $file Filename of background image
* @param int $position Position of background image
* @param int $repeat Type of repetition
* @return void
*/
abstract public function drawBackgroundImage(
ezcGraphBoundings $boundings,
$file,
$position = 48, // ezcGraph::CENTER | ezcGraph::MIDDLE
$repeat = ezcGraph::NO_REPEAT
);
/**
* Draw Symbol
*
* Draws a single symbol defined by the symbol constants in ezcGraph. for
* NO_SYMBOL a rect will be drawn.
*
* @param ezcGraphBoundings $boundings Boundings of symbol
* @param ezcGraphColor $color Color of symbol
* @param int $symbol Type of symbol
* @return void
*/
public function drawSymbol(
ezcGraphBoundings $boundings,
ezcGraphColor $color,
$symbol = ezcGraph::NO_SYMBOL )
{
switch ( $symbol )
{
case ezcGraph::NO_SYMBOL:
$return = $this->driver->drawPolygon(
array(
new ezcGraphCoordinate( $boundings->x0, $boundings->y0 ),
new ezcGraphCoordinate( $boundings->x1, $boundings->y0 ),
new ezcGraphCoordinate( $boundings->x1, $boundings->y1 ),
new ezcGraphCoordinate( $boundings->x0, $boundings->y1 ),
),
$color,
true
);
// Draw optional gleam
if ( $this->options->legendSymbolGleam !== false )
{
$this->driver->drawPolygon(
array(
$topLeft = new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) * $this->options->legendSymbolGleamSize,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) * $this->options->legendSymbolGleamSize
),
new ezcGraphCoordinate(
$boundings->x1 - ( $boundings->x1 - $boundings->x0 ) * $this->options->legendSymbolGleamSize,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) * $this->options->legendSymbolGleamSize
),
$bottomRight = new ezcGraphCoordinate(
$boundings->x1 - ( $boundings->x1 - $boundings->x0 ) * $this->options->legendSymbolGleamSize,
$boundings->y1 - ( $boundings->y1 - $boundings->y0 ) * $this->options->legendSymbolGleamSize
),
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) * $this->options->legendSymbolGleamSize,
$boundings->y1 - ( $boundings->y1 - $boundings->y0 ) * $this->options->legendSymbolGleamSize
),
),
new ezcGraphLinearGradient(
$bottomRight,
$topLeft,
$color->darken( -$this->options->legendSymbolGleam ),
$color->darken( $this->options->legendSymbolGleam )
),
true
);
}
return $return;
case ezcGraph::DIAMOND:
$return = $this->driver->drawPolygon(
array(
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) / 2,
$boundings->y0
),
new ezcGraphCoordinate(
$boundings->x1,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) / 2
),
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) / 2,
$boundings->y1
),
new ezcGraphCoordinate(
$boundings->x0,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) / 2
),
),
$color,
true
);
// Draw optional gleam
if ( $this->options->legendSymbolGleam !== false )
{
$this->driver->drawPolygon(
array(
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) / 2,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) * $this->options->legendSymbolGleamSize
),
new ezcGraphCoordinate(
$boundings->x1 - ( $boundings->x1 - $boundings->x0 ) * $this->options->legendSymbolGleamSize,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) / 2
),
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) / 2,
$boundings->y1 - ( $boundings->y1 - $boundings->y0 ) * $this->options->legendSymbolGleamSize
),
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) * $this->options->legendSymbolGleamSize,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) / 2
),
),
new ezcGraphLinearGradient(
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) * 0.353553391,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) * 0.353553391
),
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) * ( 1 - 0.353553391 ),
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) * ( 1 - 0.353553391 )
),
$color->darken( -$this->options->legendSymbolGleam ),
$color->darken( $this->options->legendSymbolGleam )
),
true
);
}
return $return;
case ezcGraph::BULLET:
$return = $this->driver->drawCircle(
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) / 2,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) / 2
),
$boundings->x1 - $boundings->x0,
$boundings->y1 - $boundings->y0,
$color,
true
);
// Draw optional gleam
if ( $this->options->legendSymbolGleam !== false )
{
$this->driver->drawCircle(
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) / 2,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) / 2
),
( $boundings->x1 - $boundings->x0 ) * $this->options->legendSymbolGleamSize,
( $boundings->y1 - $boundings->y0 ) * $this->options->legendSymbolGleamSize,
new ezcGraphLinearGradient(
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) * 0.292893219,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) * 0.292893219
),
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) * 0.707106781,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) * 0.707106781
),
$color->darken( -$this->options->legendSymbolGleam ),
$color->darken( $this->options->legendSymbolGleam )
),
true
);
}
return $return;
case ezcGraph::CIRCLE:
return $this->driver->drawCircle(
new ezcGraphCoordinate(
$boundings->x0 + ( $boundings->x1 - $boundings->x0 ) / 2,
$boundings->y0 + ( $boundings->y1 - $boundings->y0 ) / 2
),
$boundings->x1 - $boundings->x0,
$boundings->y1 - $boundings->y0,
$color,
false
);
}
}
/**
* Finish rendering
*
* Method is called before the final image is renderer, so that finishing
* operations can be performed here.
*
* @return void
*/
abstract protected function finish();
/**
* Reset renderer properties
*
* Reset all renderer properties, which were calculated during the
* rendering process, to offer a clean environment for rerendering.
*
* @return void
*/
protected function resetRenderer()
{
$this->xAxisSpace = false;
$this->yAxisSpace = false;
// Reset driver, maintaining its configuration
$driverClass = get_class( $this->driver );
$driverOptions = $this->driver->options;
$this->driver = new $driverClass();
$this->driver->options = $driverOptions;
}
/**
* Finally renders the image
*
* @param string $file Filename of destination file
* @return void
*/
public function render( $file = null )
{
$this->finish();
if ( $file === null )
{
$this->driver->renderToOutput();
}
else
{
$this->driver->render( $file );
}
$this->resetRenderer();
}
}
?>
@@ -0,0 +1,46 @@
<?php
/**
* File containing the ezcGraphRadarRenderer interface
*
* @package Graph
* @version 1.3
* @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Interface which adds the methods required for rendering radar charts to a
* renderer
*
* @version 1.3
* @package Graph
*/
interface ezcGraphStackedBarsRenderer
{
/**
* Draw stacked bar
*
* Draws a stacked bar part as a data element in a line chart
*
* @param ezcGraphBoundings $boundings Chart boundings
* @param ezcGraphContext $context Context of call
* @param ezcGraphColor $color Color of line
* @param ezcGraphCoordinate $start
* @param ezcGraphCoordinate $position
* @param float $stepSize Space which can be used for bars
* @param int $symbol Symbol to draw for line
* @param float $axisPosition Position of axis for drawing filled lines
* @return void
*/
public function drawStackedBar(
ezcGraphBoundings $boundings,
ezcGraphContext $context,
ezcGraphColor $color,
ezcGraphCoordinate $start,
ezcGraphCoordinate $position,
$stepSize,
$symbol = ezcGraph::NO_SYMBOL,
$axisPosition = 0.
);
}
?>