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,221 @@
<?php
/**
* File containing the ezcGraphAxisContainer 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
*/
/**
* The axis container class is internally used to store and validate sets of
* axis, and offering access using the SPL ArrayAccess interface to add or
* modify its contents.
*
* @version 1.3
* @package Graph
*/
class ezcGraphAxisContainer
implements
Countable,
ArrayAccess,
Iterator
{
/**
* Chart the container is used with
*
* @var ezcGraphLineChart
*/
protected $chart;
/**
* Contains the data of a chart
*
* @var array(ezcGraphChartElementAxis)
*/
protected $data = array();
/**
* Construct container with corresponding chart.
*
* @param ezcGraphLineChart $chart
* @return void
* @ignore
*/
public function __construct( ezcGraphLineChart $chart )
{
$this->chart = $chart;
}
/**
* Returns if the given offset exists.
*
* This method is part of the ArrayAccess interface to allow access to the
* data of this object as if it was an array.
*
* @param string $key Identifier of dataset.
* @return bool True when the offset exists, otherwise false.
*/
public function offsetExists( $key )
{
return isset( $this->data[$key] );
}
/**
* Returns the element with the given offset.
*
* This method is part of the ArrayAccess interface to allow access to the
* data of this object as if it was an array.
*
* @param string $key Identifier of dataset.
* @return ezcGraphChartElementAxis
*
* @throws ezcBasePropertyNotFoundException
* If no dataset with identifier exists
*/
public function offsetGet( $key )
{
if ( !isset( $this->data[$key] ) )
{
throw new ezcBasePropertyNotFoundException( $key );
}
return $this->data[$key];
}
/**
* Set the element with the given offset.
*
* This method is part of the ArrayAccess interface to allow access to the
* data of this object as if it was an array.
*
* @param string $key
* @param ezcGraphChartElementAxis $value
* @return void
*
* @throws ezcBaseValueException
* If supplied value is not an ezcGraphChartElementAxis
*/
public function offsetSet( $key, $value )
{
if ( !$value instanceof ezcGraphChartElementAxis )
{
throw new ezcBaseValueException( $key, $value, 'ezcGraphChartElementAxis' );
}
if ( $key === null )
{
$key = count( $this->data );
}
// Add axis and configure it with current font and palette
$this->data[$key] = $value;
$value->font = $this->chart->options->font;
$value->setFromPalette( $this->chart->palette );
return $value;
}
/**
* Unset the element with the given offset.
*
* This method is part of the ArrayAccess interface to allow access to the
* data of this object as if it was an array.
*
* @param string $key
* @return void
*/
public function offsetUnset( $key )
{
if ( !isset( $this->data[$key] ) )
{
throw new ezcBasePropertyNotFoundException( $key );
}
unset( $this->data[$key] );
}
/**
* Returns the currently selected dataset.
*
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return ezcGraphChartElementAxis The currently selected dataset.
*/
public function current()
{
return current( $this->data );
}
/**
* Returns the next dataset and selects it or false on the last dataset.
*
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return mixed ezcGraphChartElementAxis if the next dataset exists, or false.
*/
public function next()
{
return next( $this->data );
}
/**
* Returns the key of the currently selected dataset.
*
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return int The key of the currently selected dataset.
*/
public function key()
{
return key( $this->data );
}
/**
* Returns if the current dataset is valid.
*
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return bool If the current dataset is valid
*/
public function valid()
{
return ( current( $this->data ) !== false );
}
/**
* Selects the very first dataset and returns it.
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return ezcGraphChartElementAxis The very first dataset.
*/
public function rewind()
{
return reset( $this->data );
}
/**
* Returns the number of datasets in the row.
*
* This method is part of the Countable interface to allow the usage of
* PHP's count() function to check how many datasets exist.
*
* @return int Number of datasets.
*/
public function count()
{
return count( $this->data );
}
}
?>
@@ -0,0 +1,585 @@
<?php
/**
* File containing the ezcGraphChartElementDateAxis 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 date axis. Date axis will try to find a "nice" interval
* based on the values on the x axis. If non numeric values are given,
* ezcGraphChartElementDateAxis will convert them to timestamps using PHPs
* strtotime function.
*
* It is always possible to set start date, end date and the interval manually
* by yourself.
*
* @property float $startDate
* Starting date used to display on axis.
* @property float $endDate
* End date used to display on axis.
* @property float $interval
* Time interval between steps on axis.
* @property string $dateFormat
* Format of date string
* Like http://php.net/date
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphChartElementDateAxis extends ezcGraphChartElementAxis
{
const MONTH = 2629800;
const YEAR = 31536000;
const DECADE = 315360000;
/**
* Minimum inserted date
*
* @var int
*/
protected $minValue = false;
/**
* Maximum inserted date
*
* @var int
*/
protected $maxValue = false;
/**
* Nice time intervals to used if there is no user defined interval
*
* @var array
*/
protected $predefinedIntervals = array(
// Second
1 => 'H:i.s',
// Ten seconds
10 => 'H:i.s',
// Thirty seconds
30 => 'H:i.s',
// Minute
60 => 'H:i',
// Ten minutes
600 => 'H:i',
// Half an hour
1800 => 'H:i',
// Hour
3600 => 'H:i',
// Four hours
14400 => 'H:i',
// Six hours
21600 => 'H:i',
// Half a day
43200 => 'd.m a',
// Day
86400 => 'd.m',
// Week
604800 => 'W',
// Month
self::MONTH => 'M y',
// Year
self::YEAR => 'Y',
// Decade
self::DECADE => 'Y',
);
/**
* Constant used for calculation of automatic definition of major scaling
* steps
*/
const MAJOR_COUNT = 10;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['startDate'] = false;
$this->properties['endDate'] = false;
$this->properties['interval'] = false;
$this->properties['dateFormat'] = false;
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 'startDate':
$this->properties['startDate'] = (int) $propertyValue;
break;
case 'endDate':
$this->properties['endDate'] = (int) $propertyValue;
break;
case 'interval':
$this->properties['interval'] = (int) $propertyValue;
$this->properties['initialized'] = true;
break;
case 'dateFormat':
$this->properties['dateFormat'] = (string) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
/**
* Ensure proper timestamp
*
* Takes a mixed value from datasets, like timestamps, or strings
* describing some time and converts it to a timestamp.
*
* @param mixed $value
* @return int
*/
protected static function ensureTimestamp( $value )
{
if ( is_numeric( $value ) )
{
$timestamp = (int) $value;
}
elseif ( ( $timestamp = strtotime( $value ) ) === false )
{
throw new ezcGraphErrorParsingDateException( $value );
}
return $timestamp;
}
/**
* Add data for this axis
*
* @param array $values Value which will be displayed on this axis
* @return void
*/
public function addData( array $values )
{
foreach ( $values as $nr => $value )
{
$value = self::ensureTimestamp( $value );
if ( $this->minValue === false ||
$value < $this->minValue )
{
$this->minValue = $value;
}
if ( $this->maxValue === false ||
$value > $this->maxValue )
{
$this->maxValue = $value;
}
}
$this->properties['initialized'] = true;
}
/**
* Calculate nice time interval
*
* Use the best fitting time interval defined in class property array
* predefinedIntervals.
*
* @param int $min Start time
* @param int $max End time
* @return void
*/
protected function calculateInterval( $min, $max )
{
$diff = $max - $min;
foreach ( $this->predefinedIntervals as $interval => $format )
{
if ( ( $diff / $interval ) <= self::MAJOR_COUNT )
{
break;
}
}
if ( ( $this->properties['startDate'] !== false ) &&
( $this->properties['endDate'] !== false ) )
{
// Use interval between defined borders
if ( ( $diff % $interval ) > 0 )
{
// Stil use predefined date format from old interval if not set
if ( $this->properties['dateFormat'] === false )
{
$this->properties['dateFormat'] = $this->predefinedIntervals[$interval];
}
$count = ceil( $diff / $interval );
$interval = round( $diff / $count, 0 );
}
}
$this->properties['interval'] = $interval;
}
/**
* Calculate lower nice date
*
* Calculates a date which is earlier or equal to the given date, and is
* divisible by the given interval.
*
* @param int $min Date
* @param int $interval Interval
* @return int Earlier date
*/
protected function calculateLowerNiceDate( $min, $interval )
{
switch ( $interval )
{
case self::MONTH:
// Special handling for months - not covered by the default
// algorithm
return mktime(
1,
0,
0,
(int) date( 'm', $min ),
1,
(int) date( 'Y', $min )
);
default:
$dateSteps = array( 60, 60, 24, 7, 52 );
$date = array(
(int) date( 's', $min ),
(int) date( 'i', $min ),
(int) date( 'H', $min ),
(int) date( 'd', $min ),
(int) date( 'm', $min ),
(int) date( 'Y', $min ),
);
$element = 0;
while ( ( $step = array_shift( $dateSteps ) ) &&
( $interval > $step ) )
{
$interval /= $step;
$date[$element++] = (int) ( $element > 2 );
}
$date[$element] -= $date[$element] % $interval;
return mktime(
$date[2],
$date[1],
$date[0],
$date[4],
$date[3],
$date[5]
);
}
}
/**
* Calculate start date
*
* Use calculateLowerNiceDate to get a date earlier or equal date then the
* minimum date to use it as the start date for the axis depending on the
* selected interval.
*
* @param mixed $min Minimum date
* @param mixed $max Maximum date
* @return void
*/
public function calculateMinimum( $min, $max )
{
if ( $this->properties['endDate'] === false )
{
$this->properties['startDate'] = $this->calculateLowerNiceDate( $min, $this->interval );
}
else
{
$this->properties['startDate'] = $this->properties['endDate'];
while ( $this->properties['startDate'] > $min )
{
switch ( $this->interval )
{
case self::MONTH:
$this->properties['startDate'] = strtotime( '-1 month', $this->properties['startDate'] );
break;
case self::YEAR:
$this->properties['startDate'] = strtotime( '-1 year', $this->properties['startDate'] );
break;
case self::DECADE:
$this->properties['startDate'] = strtotime( '-10 years', $this->properties['startDate'] );
break;
default:
$this->properties['startDate'] -= $this->interval;
}
}
}
}
/**
* Calculate end date
*
* Use calculateLowerNiceDate to get a date later or equal date then the
* maximum date to use it as the end date for the axis depending on the
* selected interval.
*
* @param mixed $min Minimum date
* @param mixed $max Maximum date
* @return void
*/
public function calculateMaximum( $min, $max )
{
$this->properties['endDate'] = $this->properties['startDate'];
while ( $this->properties['endDate'] < $max )
{
switch ( $this->interval )
{
case self::MONTH:
$this->properties['endDate'] = strtotime( '+1 month', $this->properties['endDate'] );
break;
case self::YEAR:
$this->properties['endDate'] = strtotime( '+1 year', $this->properties['endDate'] );
break;
case self::DECADE:
$this->properties['endDate'] = strtotime( '+10 years', $this->properties['endDate'] );
break;
default:
$this->properties['endDate'] += $this->interval;
}
}
}
/**
* Calculate axis bounding values on base of the assigned values
*
* @return void
*/
public function calculateAxisBoundings()
{
// Prevent division by zero, when min == max
if ( $this->minValue == $this->maxValue )
{
if ( $this->minValue == 0 )
{
$this->maxValue = 1;
}
else
{
$this->minValue -= ( $this->minValue * .1 );
$this->maxValue += ( $this->maxValue * .1 );
}
}
// Use custom minimum and maximum if available
if ( $this->properties['startDate'] !== false )
{
$this->minValue = $this->properties['startDate'];
}
if ( $this->properties['endDate'] !== false )
{
$this->maxValue = $this->properties['endDate'];
}
// Calculate "nice" values for scaling parameters
if ( $this->properties['interval'] === false )
{
$this->calculateInterval( $this->minValue, $this->maxValue );
}
if ( $this->properties['dateFormat'] === false && isset( $this->predefinedIntervals[$this->interval] ) )
{
$this->properties['dateFormat'] = $this->predefinedIntervals[$this->interval];
}
if ( $this->properties['startDate'] === false )
{
$this->calculateMinimum( $this->minValue, $this->maxValue );
}
if ( $this->properties['endDate'] === false )
{
$this->calculateMaximum( $this->minValue, $this->maxValue );
}
}
/**
* Get coordinate for a dedicated value on the chart
*
* @param float $value Value to determine position for
* @return float Position on chart
*/
public function getCoordinate( $value )
{
// Force typecast, because ( false < -100 ) results in (bool) true
$intValue = ( $value === false ? false : self::ensureTimestamp( $value ) );
if ( ( $value === false ) &&
( ( $intValue < $this->startDate ) || ( $intValue > $this->endDate ) ) )
{
switch ( $this->position )
{
case ezcGraph::LEFT:
case ezcGraph::TOP:
return 0.;
case ezcGraph::RIGHT:
case ezcGraph::BOTTOM:
return 1.;
}
}
else
{
switch ( $this->position )
{
case ezcGraph::LEFT:
case ezcGraph::TOP:
return ( $intValue - $this->startDate ) / ( $this->endDate - $this->startDate );
case ezcGraph::RIGHT:
case ezcGraph::BOTTOM:
return 1 - ( $intValue - $this->startDate ) / ( $this->endDate - $this->startDate );
}
}
}
/**
* Return count of minor steps
*
* @return integer Count of minor steps
*/
public function getMinorStepCount()
{
return false;
}
/**
* Return count of major steps
*
* @return integer Count of major steps
*/
public function getMajorStepCount()
{
return (int) ceil( ( $this->properties['endDate'] - $this->startDate ) / $this->interval );
}
/**
* Get label for a dedicated step on the axis
*
* @param integer $step Number of step
* @return string label
*/
public function getLabel( $step )
{
return $this->getLabelFromTimestamp( $this->startDate + ( $step * $this->interval ), $step );
}
/**
* Get label for timestamp
*
* @param int $time
* @param int $step
* @return string
*/
protected function getLabelFromTimestamp( $time, $step )
{
if ( $this->properties['labelCallback'] !== null )
{
return call_user_func_array(
$this->properties['labelCallback'],
array(
date( $this->properties['dateFormat'], $time ),
$step,
)
);
}
else
{
return date( $this->properties['dateFormat'], $time );
}
}
/**
* Return array of steps on this axis
*
* @return array( ezcGraphAxisStep )
*/
public function getSteps()
{
$steps = array();
$start = $this->properties['startDate'];
$end = $this->properties['endDate'];
$distance = $end - $start;
$step = 0;
for ( $time = $start; $time <= $end; )
{
$steps[] = new ezcGraphAxisStep(
( $time - $start ) / $distance,
$this->interval / $distance,
$this->getLabelFromTimestamp( $time, $step++ ),
array(),
$step === 1,
$time >= $end
);
switch ( $this->interval )
{
case self::MONTH:
$time = strtotime( '+1 month', $time );
break;
case self::YEAR:
$time = strtotime( '+1 year', $time );
break;
case self::DECADE:
$time = strtotime( '+10 years', $time );
break;
default:
$time += $this->interval;
break;
}
}
return $steps;
}
/**
* Is zero step
*
* Returns true if the given step is the one on the initial axis position
*
* @param int $step Number of step
* @return bool Status If given step is initial axis position
*/
public function isZeroStep( $step )
{
return ( $step == 0 );
}
}
?>
@@ -0,0 +1,448 @@
<?php
/**
* File containing the ezcGraphChartElementLabeledAxis 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 labeled axis. Values on the x axis are considered as
* strings and used in the given order.
*
* @property float $labelCount
* Define count of displayed labels on the axis
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphChartElementLabeledAxis extends ezcGraphChartElementAxis
{
/**
* Array with labeles for data
*
* @var array
*/
protected $labels = array();
/**
* Reduced amount of labels which will be displayed in the chart
*
* @var array
*/
protected $displayedLabels = array();
/**
* Maximum count of labels which can be displayed on one axis
* @todo Perhaps base this on the chart size
*/
const MAX_LABEL_COUNT = 10;
/**
* Precalculated steps on the axis
*
* @var array(ezcGraphAxisStep)
*/
protected $steps;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['labelCount'] = null;
$this->axisLabelRenderer = new ezcGraphAxisCenteredLabelRenderer();
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 'labelCount':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int > 1' );
}
$this->properties['labelCount'] = (int) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
/**
* Increase the keys of all elements in the array up from the start key, to
* insert an additional element at the correct position.
*
* @param array $array Array
* @param int $startKey Key to increase keys from
* @return array Updated array
*/
protected function increaseKeys( array $array, $startKey )
{
foreach ( $array as $key => $value )
{
if ( $key === $startKey )
{
// Recursive check, if next key should be increased, too
if ( isset ( $array[$key + 1] ) )
{
$array = $this->increaseKeys( $array, $key + 1 );
}
// Increase key
$array[$key + 1] = $array[$key];
unset( $array[$key] );
}
}
return $array;
}
/**
* Add data for this axis
*
* @param array $values Value which will be displayed on this axis
* @return void
*/
public function addData( array $values )
{
$position = 0;
foreach ( $values as $label )
{
$label = (string) $label;
if ( !in_array( $label, $this->labels, true ) )
{
if ( isset( $this->labels[$position] ) )
{
$this->labels = $this->increaseKeys( $this->labels, $position );
$this->labels[$position++] = $label;
}
else
{
$this->labels[$position++] = $label;
}
}
else
{
$position = array_search( $label, $this->labels, true ) + 1;
}
}
ksort( $this->labels );
$this->properties['initialized'] = true;
}
/**
* Calculate axis bounding values on base of the assigned values
*
* @abstract
* @access public
* @return void
*/
public function calculateAxisBoundings()
{
$this->steps = array();
// Apply label format callback function
if ( $this->properties['labelCallback'] !== null )
{
foreach ( $this->labels as $nr => $label )
{
$this->labels[$nr] = call_user_func_array(
$this->properties['labelCallback'],
array(
$label,
$nr
)
);
}
}
$labelCount = count( $this->labels ) - 1;
if ( $labelCount === 0 )
{
// Create single only step
$this->steps = array(
new ezcGraphAxisStep(
0,
1,
reset( $this->labels ),
array(),
true,
true
),
);
return true;
}
if ( $this->properties['labelCount'] === null )
{
if ( $labelCount <= self::MAX_LABEL_COUNT )
{
$stepSize = 1 / $labelCount;
foreach ( $this->labels as $nr => $label )
{
$this->steps[] = new ezcGraphAxisStep(
$stepSize * $nr,
$stepSize,
$label,
array(),
$nr === 0,
$nr === $labelCount
);
}
// @TODO: This line is deprecated and only build for
// deprecated getLabel()
$this->displayedLabels = $this->labels;
return true;
}
for ( $div = self::MAX_LABEL_COUNT; $div > 1; --$div )
{
if ( ( $labelCount % $div ) === 0 )
{
// @TODO: This part is deprecated and only build for
// deprecated getLabel()
$step = $labelCount / $div;
foreach ( $this->labels as $nr => $label )
{
if ( ( $nr % $step ) === 0 )
{
$this->displayedLabels[] = $label;
}
}
// End of deprecated part
break;
}
}
}
else
{
$div = false;
}
// Build up step array
if ( $div > 2 )
{
$step = $labelCount / $div;
$stepSize = 1 / $div;
$minorStepSize = $stepSize / $step;
foreach ( $this->labels as $nr => $label )
{
if ( ( $nr % $step ) === 0 )
{
$mainstep = new ezcGraphAxisStep(
$stepSize * ( $nr / $step ),
$stepSize,
$label,
array(),
$nr === 0,
$nr === $labelCount
);
$this->steps[] = $mainstep;
}
else
{
$mainstep->childs[] = new ezcGraphAxisStep(
$mainstep->position + $minorStepSize * ( $nr % $step ),
$minorStepSize
);
}
}
}
else
{
if ( $this->properties['labelCount'] === null )
{
$floatStep = $labelCount / ( self::MAX_LABEL_COUNT - 1 );
}
else
{
$floatStep = $labelCount / min( $labelCount, $this->properties['labelCount'] - 1 );
}
$position = 0;
$minorStepSize = 1 / $labelCount;
foreach ( $this->labels as $nr => $label )
{
if ( $nr >= $position )
{
$position += $floatStep;
// Add as major step
$mainstep = new ezcGraphAxisStep(
$minorStepSize * $nr,
ceil( $position - $nr ) * $minorStepSize,
$label,
array(),
$nr === 0,
$nr === $labelCount
);
// @TODO: This line is deprecated and only build for
// deprecated getLabel()
$this->displayedLabels[] = $label;
$this->steps[] = $mainstep;
}
else
{
$mainstep->childs[] = new ezcGraphAxisStep(
$minorStepSize * $nr,
$minorStepSize
);
}
}
}
}
/**
* Return array of steps on this axis
*
* @return array( ezcGraphAxisStep )
*/
public function getSteps()
{
return $this->steps;
}
/**
* Get coordinate for a dedicated value on the chart
*
* @param string $value Value to determine position for
* @return float Position on chart
*/
public function getCoordinate( $value )
{
if ( $value === false ||
$value === null ||
( $key = array_search( $value, $this->labels ) ) === false )
{
switch ( $this->position )
{
case ezcGraph::LEFT:
case ezcGraph::TOP:
return 0.;
case ezcGraph::RIGHT:
case ezcGraph::BOTTOM:
return 1.;
}
}
else
{
switch ( $this->position )
{
case ezcGraph::LEFT:
case ezcGraph::TOP:
if ( count( $this->labels ) > 1 )
{
return (float) $key / ( count ( $this->labels ) - 1 );
}
else
{
return 0;
}
case ezcGraph::BOTTOM:
case ezcGraph::RIGHT:
if ( count( $this->labels ) > 1 )
{
return (float) 1 - $key / ( count ( $this->labels ) - 1 );
}
else
{
return 1;
}
}
}
}
/**
* Return count of minor steps
*
* @return integer Count of minor steps
*/
public function getMinorStepCount()
{
return 0;
}
/**
* Return count of major steps
*
* @return integer Count of major steps
*/
public function getMajorStepCount()
{
return max( count( $this->displayedLabels ) - 1, 1 );
}
/**
* Get label for a dedicated step on the axis
*
* @param integer $step Number of step
* @return string label
*/
public function getLabel( $step )
{
if ( isset( $this->displayedLabels[$step] ) )
{
return $this->displayedLabels[$step];
}
else
{
return false;
}
}
/**
* Is zero step
*
* Returns true if the given step is the one on the initial axis position
*
* @param int $step Number of step
* @return bool Status If given step is initial axis position
*/
public function isZeroStep( $step )
{
return !$step;
}
}
?>
@@ -0,0 +1,303 @@
<?php
/**
* File containing the ezcGraphChartElementLogarithmicalAxis 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 numeric axis. The axis tries to calculate "nice" start
* and end values for the axis scale. The used interval is considered as nice,
* if it is equal to [1,2,5] * 10^x with x in [.., -1, 0, 1, ..].
*
* The start and end value are the next bigger / smaller multiple of the
* intervall compared to the maximum / minimum axis value.
*
* @property float $min
* Minimum value of displayed scale on axis.
* @property float $max
* Maximum value of displayed scale on axis.
* @property float $base
* Base for logarithmical scaling.
* @property string $logarithmicalFormatString
* Sprintf formatstring for the axis labels where
* $1 is the base and
* $2 is the exponent.
* @property-read float $minValue
* Minimum Value to display on this axis.
* @property-read float $maxValue
* Maximum value to display on this axis.
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphChartElementLogarithmicalAxis extends ezcGraphChartElementAxis
{
/**
* Constant used for calculation of automatic definition of major scaling
* steps
*/
const MAX_STEPS = 9;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['min'] = null;
$this->properties['max'] = null;
$this->properties['base'] = 10;
$this->properties['logarithmicalFormatString'] = '%1$d^%2$d';
$this->properties['minValue'] = null;
$this->properties['maxValue'] = null;
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 'min':
case 'max':
if ( !is_numeric( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float' );
}
$this->properties[$propertyName] = (float) $propertyValue;
$this->properties['initialized'] = true;
break;
case 'base':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties[$propertyName] = (float) $propertyValue;
break;
case 'logarithmicalFormatString':
$this->properties['logarithmicalFormatString'] = (string) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
/**
* Add data for this axis
*
* @param array $values Value which will be displayed on this axis
* @return void
*/
public function addData( array $values )
{
foreach ( $values as $value )
{
if ( $this->properties['minValue'] === null ||
$value < $this->properties['minValue'] )
{
$this->properties['minValue'] = $value;
}
if ( $this->properties['maxValue'] === null ||
$value > $this->properties['maxValue'] )
{
$this->properties['maxValue'] = $value;
}
}
$this->properties['initialized'] = true;
}
/**
* Calculate axis bounding values on base of the assigned values
*
* @abstract
* @access public
* @return void
*/
public function calculateAxisBoundings()
{
// Prevent division by zero, when min == max
if ( $this->properties['minValue'] == $this->properties['maxValue'] )
{
if ( $this->properties['minValue'] == 0 )
{
$this->properties['maxValue'] = 1;
}
else
{
$this->properties['minValue'] -= ( $this->properties['minValue'] * .1 );
$this->properties['maxValue'] += ( $this->properties['maxValue'] * .1 );
}
}
if ( $this->properties['minValue'] <= 0 )
{
throw new ezcGraphOutOfLogithmicalBoundingsException( $this->properties['minValue'] );
}
// Use custom minimum and maximum if available
if ( $this->properties['min'] !== null )
{
$this->properties['minValue'] = pow( $this->properties['base'], $this->properties['min'] );
}
if ( $this->properties['max'] !== null )
{
$this->properties['maxValue'] = pow( $this->properties['base'], $this->properties['max'] );
}
// Calculate "nice" values for scaling parameters
if ( $this->properties['min'] === null )
{
$this->properties['min'] = floor( log( $this->properties['minValue'], $this->properties['base'] ) );
}
if ( $this->properties['max'] === null )
{
$this->properties['max'] = ceil( log( $this->properties['maxValue'], $this->properties['base'] ) );
}
$this->properties['minorStep'] = 1;
if ( ( $modifier = ( ( $this->properties['max'] - $this->properties['min'] ) / self::MAX_STEPS ) ) > 1 )
{
$this->properties['majorStep'] = $modifier = ceil( $modifier );
$this->properties['min'] = floor( $this->properties['min'] / $modifier ) * $modifier;
$this->properties['max'] = floor( $this->properties['max'] / $modifier ) * $modifier;
}
else
{
$this->properties['majorStep'] = 1;
}
}
/**
* Get coordinate for a dedicated value on the chart
*
* @param float $value Value to determine position for
* @return float Position on chart
*/
public function getCoordinate( $value )
{
// Force typecast, because ( false < -100 ) results in (bool) true
$floatValue = (float) $value;
if ( $value === false )
{
switch ( $this->position )
{
case ezcGraph::LEFT:
case ezcGraph::TOP:
return 0.;
case ezcGraph::RIGHT:
case ezcGraph::BOTTOM:
return 1.;
}
}
else
{
$position = ( log( $value, $this->properties['base'] ) - $this->properties['min'] ) / ( $this->properties['max'] - $this->properties['min'] );
switch ( $this->position )
{
case ezcGraph::LEFT:
case ezcGraph::TOP:
return $position;
case ezcGraph::RIGHT:
case ezcGraph::BOTTOM:
return 1 - $position;
}
}
}
/**
* Return count of minor steps
*
* @return integer Count of minor steps
*/
public function getMinorStepCount()
{
return (int) ( ( $this->properties['max'] - $this->properties['min'] ) / $this->properties['minorStep'] );
}
/**
* Return count of major steps
*
* @return integer Count of major steps
*/
public function getMajorStepCount()
{
return (int) ( ( $this->properties['max'] - $this->properties['min'] ) / $this->properties['majorStep'] );
}
/**
* Get label for a dedicated step on the axis
*
* @param integer $step Number of step
* @return string label
*/
public function getLabel( $step )
{
if ( $this->properties['labelCallback'] !== null )
{
return call_user_func_array(
$this->properties['labelCallback'],
array(
sprintf(
$this->properties['logarithmicalFormatString'],
$this->properties['base'],
$this->properties['min'] + ( $step * $this->properties['majorStep'] )
),
$step,
)
);
}
else
{
return sprintf(
$this->properties['logarithmicalFormatString'],
$this->properties['base'],
$this->properties['min'] + ( $step * $this->properties['majorStep'] )
);
}
}
/**
* Is zero step
*
* Returns true if the given step is the one on the initial axis position
*
* @param int $step Number of step
* @return bool Status If given step is initial axis position
*/
public function isZeroStep( $step )
{
return ( $step == 0 );
}
}
?>
@@ -0,0 +1,422 @@
<?php
/**
* File containing the abstract ezcGraphChartElementNumericAxis 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 numeric axis. The axis tries to calculate "nice" start
* and end values for the axis scale. The used interval is considered as nice,
* if it is equal to [1,2,5] * 10^x with x in [.., -1, 0, 1, ..].
*
* The start and end value are the next bigger / smaller multiple of the
* intervall compared to the maximum / minimum axis value.
*
* @property float $min
* Minimum value of displayed scale on axis.
* @property float $max
* Maximum value of displayed scale on axis.
* @property-read float $minValue
* Minimum Value to display on this axis.
* @property-read float $maxValue
* Maximum value to display on this axis.
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphChartElementNumericAxis extends ezcGraphChartElementAxis
{
/**
* Constant used for calculation of automatic definition of major scaling
* steps
*/
const MIN_MAJOR_COUNT = 5;
/**
* Constant used for automatic calculation of minor steps from given major
* steps
*/
const MIN_MINOR_COUNT = 8;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['min'] = null;
$this->properties['max'] = null;
$this->properties['minValue'] = null;
$this->properties['maxValue'] = null;
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 'min':
if ( !is_numeric( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float' );
}
$this->properties['min'] = (float) $propertyValue;
$this->properties['initialized'] = true;
break;
case 'max':
if ( !is_numeric( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float' );
}
$this->properties['max'] = (float) $propertyValue;
$this->properties['initialized'] = true;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
/**
* Returns a "nice" number for a given floating point number.
*
* Nice numbers are steps on a scale which are easily recognized by humans
* like 0.5, 25, 1000 etc.
*
* @param float $float Number to be altered
* @return float Nice number
*/
protected function getNiceNumber( $float )
{
// Get absolute value and save sign
$abs = abs( $float );
$sign = $float / $abs;
// Normalize number to a range between 1 and 10
$log = (int) round( log10( $abs ), 0 );
$abs /= pow( 10, $log );
// find next nice number
if ( $abs > 5 )
{
$abs = 10.;
}
elseif ( $abs > 2.5 )
{
$abs = 5.;
}
elseif ( $abs > 1 )
{
$abs = 2.5;
}
else
{
$abs = 1;
}
// unnormalize number to original values
return $abs * pow( 10, $log ) * $sign;
}
/**
* Calculate minimum value for displayed axe basing on real minimum and
* major step size
*
* @param float $min Real data minimum
* @param float $max Real data maximum
* @return void
*/
protected function calculateMinimum( $min, $max )
{
if ( $this->properties['max'] === null )
{
$this->properties['min'] = floor( $min / $this->properties['majorStep'] ) * $this->properties['majorStep'];
}
else
{
$calculatedMin = $this->properties['max'];
do {
$calculatedMin -= $this->properties['majorStep'];
} while ( $calculatedMin > $min );
$this->properties['min'] = $calculatedMin;
}
}
/**
* Calculate maximum value for displayed axe basing on real maximum and
* major step size
*
* @param float $min Real data minimum
* @param float $max Real data maximum
* @return void
*/
protected function calculateMaximum( $min, $max )
{
$calculatedMax = $this->properties['min'];
do {
$calculatedMax += $this->properties['majorStep'];
} while ( $calculatedMax < $max );
$this->properties['max'] = $calculatedMax;
}
/**
* Calculate size of minor steps based on the size of the major step size
*
* @param float $min Real data minimum
* @param float $max Real data maximum
* @return void
*/
protected function calculateMinorStep( $min, $max )
{
$stepSize = $this->properties['majorStep'] / self::MIN_MINOR_COUNT;
$this->properties['minorStep'] = $this->getNiceNumber( $stepSize );
}
/**
* Calculate size of major step based on the span to be displayed and the
* defined MIN_MAJOR_COUNT constant.
*
* @param float $min Real data minimum
* @param float $max Real data maximum
* @return void
*/
protected function calculateMajorStep( $min, $max )
{
$span = $max - $min;
$stepSize = $span / self::MIN_MAJOR_COUNT;
$this->properties['majorStep'] = $this->getNiceNumber( $stepSize );
}
/**
* Add data for this axis
*
* @param array $values Value which will be displayed on this axis
* @return void
*/
public function addData( array $values )
{
foreach ( $values as $value )
{
if ( $this->properties['minValue'] === null ||
$value < $this->properties['minValue'] )
{
$this->properties['minValue'] = $value;
}
if ( $this->properties['maxValue'] === null ||
$value > $this->properties['maxValue'] )
{
$this->properties['maxValue'] = $value;
}
}
$this->properties['initialized'] = true;
}
/**
* Calculate axis bounding values on base of the assigned values
*
* @abstract
* @access public
* @return void
*/
public function calculateAxisBoundings()
{
// Prevent division by zero, when min == max
if ( $this->properties['minValue'] == $this->properties['maxValue'] )
{
if ( $this->properties['minValue'] == 0 )
{
$this->properties['maxValue'] = 1;
}
else
{
if ( $this->properties['majorStep'] !== null )
{
$this->properties['minValue'] -= $this->properties['majorStep'];
$this->properties['maxValue'] += $this->properties['majorStep'];
}
else
{
$this->properties['minValue'] -= ( $this->properties['minValue'] * .1 );
$this->properties['maxValue'] += ( $this->properties['maxValue'] * .1 );
}
}
}
// Use custom minimum and maximum if available
if ( $this->properties['min'] !== null )
{
$this->properties['minValue'] = $this->properties['min'];
}
if ( $this->properties['max'] !== null )
{
$this->properties['maxValue'] = $this->properties['max'];
}
// If min and max values are forced, we may not be able to find a
// "nice" number for the steps. Try to find such a nice step size, or
// fall back to a step size, which is just the span divided by 5.
if ( ( $this->properties['min'] !== null ) &&
( $this->properties['max'] !== null ) )
{
$diff = $this->properties['max'] - $this->properties['min'];
$this->calculateMajorStep( $this->properties['minValue'], $this->properties['maxValue'] );
$stepInvariance = $diff / $this->properties['majorStep'];
if ( ( $stepInvariance - floor( $stepInvariance ) ) > .0000001 )
{
// For too big step invariances calculate the step size just
// from the given difference between min and max value.
$this->properties['majorStep'] = ( $this->properties['max'] - $this->properties['min'] ) / self::MIN_MAJOR_COUNT;
$this->properties['minorStep'] = $this->properties['majorStep'] / self::MIN_MAJOR_COUNT;
}
}
// Calculate "nice" values for scaling parameters
if ( $this->properties['majorStep'] === null )
{
$this->calculateMajorStep( $this->properties['minValue'], $this->properties['maxValue'] );
}
if ( $this->properties['minorStep'] === null )
{
$this->calculateMinorStep( $this->properties['minValue'], $this->properties['maxValue'] );
}
if ( $this->properties['min'] === null )
{
$this->calculateMinimum( $this->properties['minValue'], $this->properties['maxValue'] );
}
if ( $this->properties['max'] === null )
{
$this->calculateMaximum( $this->properties['minValue'], $this->properties['maxValue'] );
}
}
/**
* Get coordinate for a dedicated value on the chart
*
* @param float $value Value to determine position for
* @return float Position on chart
*/
public function getCoordinate( $value )
{
// Force typecast, because ( false < -100 ) results in (bool) true
$floatValue = (float) $value;
if ( ( $value === false ) &&
( ( $floatValue < $this->properties['min'] ) || ( $floatValue > $this->properties['max'] ) ) )
{
switch ( $this->position )
{
case ezcGraph::LEFT:
case ezcGraph::TOP:
return 0.;
case ezcGraph::RIGHT:
case ezcGraph::BOTTOM:
return 1.;
}
}
else
{
switch ( $this->position )
{
case ezcGraph::LEFT:
case ezcGraph::TOP:
return ( $value - $this->properties['min'] ) / ( $this->properties['max'] - $this->properties['min'] );
case ezcGraph::RIGHT:
case ezcGraph::BOTTOM:
return 1 - ( $value - $this->properties['min'] ) / ( $this->properties['max'] - $this->properties['min'] );
}
}
}
/**
* Return count of minor steps
*
* @return integer Count of minor steps
*/
public function getMinorStepCount()
{
return (int) ( ( $this->properties['max'] - $this->properties['min'] ) / $this->properties['minorStep'] );
}
/**
* Return count of major steps
*
* @return integer Count of major steps
*/
public function getMajorStepCount()
{
return (int) ( ( $this->properties['max'] - $this->properties['min'] ) / $this->properties['majorStep'] );
}
/**
* Get label for a dedicated step on the axis
*
* @param integer $step Number of step
* @return string label
*/
public function getLabel( $step )
{
if ( $this->properties['labelCallback'] !== null )
{
return call_user_func_array(
$this->properties['labelCallback'],
array(
$this->properties['min'] + ( $step * $this->properties['majorStep'] ),
$step,
)
);
}
else
{
return $this->properties['min'] + ( $step * $this->properties['majorStep'] );
}
}
/**
* Is zero step
*
* Returns true if the given step is the one on the initial axis position
*
* @param int $step Number of step
* @return bool Status If given step is initial axis position
*/
public function isZeroStep( $step )
{
return ( $this->getLabel( $step ) == 0 );
}
}
?>
@@ -0,0 +1,94 @@
<?php
/**
* File containing the ezcGraphBarChart 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 bar charts. Can make use of an unlimited amount of datasets and
* will display them as bars by default.
* X axis:
* - Labeled axis
* - Boxed axis label renderer
* Y axis:
* - Numeric axis
* - Exact axis label renderer
*
* <code>
* // Create a new line chart
* $chart = new ezcGraphBarChart();
*
* // Add data to line chart
* $chart->data['sample dataset'] = new ezcGraphArrayDataSet(
* array(
* '100' => 1.2,
* '200' => 43.2,
* '300' => -34.14,
* '350' => 65,
* '400' => 123,
* )
* );
*
* // Render chart with default 2d renderer and default SVG driver
* $chart->render( 500, 200, 'bar_chart.svg' );
* </code>
*
* Each chart consists of several chart elements which represents logical
* parts of the chart and can be formatted independently. The bar chart
* consists of:
* - title ( {@link ezcGraphChartElementText} )
* - legend ( {@link ezcGraphChartElementLegend} )
* - background ( {@link ezcGraphChartElementBackground} )
* - xAxis ( {@link ezcGraphChartElementLabeledAxis} )
* - yAxis ( {@link ezcGraphChartElementNumericAxis} )
*
* The type of the axis may be changed and all elements can be configured by
* accessing them as properties of the chart:
*
* <code>
* $chart->legend->position = ezcGraph::RIGHT;
* </code>
*
* The chart itself also offers several options to configure the appearance. As
* bar charts extend line charts the the extended configure options are
* available in {@link ezcGraphLineChartOptions} extending the
* {@link ezcGraphChartOptions}.
*
* @property ezcGraphLineChartOptions $options
* Chart options class
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphBarChart extends ezcGraphLineChart
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
parent::__construct();
$this->elements['xAxis']->axisLabelRenderer = new ezcGraphAxisBoxedLabelRenderer();
}
/**
* Returns the default display type of the current chart type.
*
* @return int Display type
*/
public function getDefaultDisplayType()
{
return ezcGraph::BAR;
}
}
?>
@@ -0,0 +1,652 @@
<?php
/**
* File containing the ezcGraphLineChart 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 line charts. Can make use of an unlimited amount of datasets and
* will display them as lines by default.
* X axis:
* - Labeled axis
* - Centered axis label renderer
* Y axis:
* - Numeric axis
* - Exact axis label renderer
*
* <code>
* // Create a new line chart
* $chart = new ezcGraphLineChart();
*
* // Add data to line chart
* $chart->data['sample dataset'] = new ezcGraphArrayDataSet(
* array(
* '100' => 1.2,
* '200' => 43.2,
* '300' => -34.14,
* '350' => 65,
* '400' => 123,
* )
* );
*
* // Render chart with default 2d renderer and default SVG driver
* $chart->render( 500, 200, 'line_chart.svg' );
* </code>
*
* Each chart consists of several chart elements which represents logical
* parts of the chart and can be formatted independently. The line chart
* consists of:
* - title ( {@link ezcGraphChartElementText} )
* - legend ( {@link ezcGraphChartElementLegend} )
* - background ( {@link ezcGraphChartElementBackground} )
* - xAxis ( {@link ezcGraphChartElementLabeledAxis} )
* - yAxis ( {@link ezcGraphChartElementNumericAxis} )
*
* The type of the axis may be changed and all elements can be configured by
* accessing them as properties of the chart:
*
* <code>
* $chart->legend->position = ezcGraph::RIGHT;
* </code>
*
* The chart itself also offers several options to configure the appearance.
* The extended configure options are available in
* {@link ezcGraphLineChartOptions} extending the {@link ezcGraphChartOptions}.
*
* @property ezcGraphLineChartOptions $options
* Chart options class
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphLineChart extends ezcGraphChart
{
/**
* Array with additional axis for the chart
*
* @var ezcGraphAxisContainer
*/
protected $additionalAxis;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->additionalAxis = new ezcGraphAxisContainer( $this );
$this->options = new ezcGraphLineChartOptions( $options );
$this->options->highlightFont = $this->options->font;
parent::__construct();
$this->addElement( 'xAxis', new ezcGraphChartElementLabeledAxis() );
$this->elements['xAxis']->position = ezcGraph::LEFT;
$this->addElement( 'yAxis', new ezcGraphChartElementNumericAxis() );
$this->elements['yAxis']->position = ezcGraph::BOTTOM;
}
/**
* __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 'additionalAxis':
return $this->additionalAxis;
}
return parent::__get( $propertyName );
}
/**
* 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 'xAxis':
if ( $propertyValue instanceof ezcGraphChartElementAxis )
{
$this->addElement( 'xAxis', $propertyValue );
$this->elements['xAxis']->position = ezcGraph::LEFT;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphChartElementAxis' );
}
break;
case 'yAxis':
if ( $propertyValue instanceof ezcGraphChartElementAxis )
{
$this->addElement( 'yAxis', $propertyValue );
$this->elements['yAxis']->position = ezcGraph::BOTTOM;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphChartElementAxis' );
}
break;
default:
parent::__set( $propertyName, $propertyValue );
}
}
/**
* Set colors and border for this element
*
* @param ezcGraphPalette $palette Palette
* @return void
*/
public function setFromPalette( ezcGraphPalette $palette )
{
foreach ( $this->additionalAxis as $element )
{
$element->setFromPalette( $palette );
}
parent::setFromPalette( $palette );
}
/**
* Render the assigned data
*
* Will renderer all charts data in the remaining boundings after drawing
* all other chart elements. The data will be rendered depending on the
* settings in the dataset.
*
* @param ezcGraphRenderer $renderer Renderer
* @param ezcGraphBoundings $boundings Remaining boundings
* @return void
*/
protected function renderData( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings )
{
// Apply axis space
$xAxisSpace = ( $boundings->x1 - $boundings->x0 ) * $this->yAxis->axisSpace;
$yAxisSpace = ( $boundings->y1 - $boundings->y0 ) * $this->xAxis->axisSpace;
$boundings->x0 += $xAxisSpace;
$boundings->x1 -= $xAxisSpace;
$boundings->y0 += $yAxisSpace;
$boundings->y1 -= $yAxisSpace;
$yAxisNullPosition = $this->elements['yAxis']->getCoordinate( false );
// Initialize counters
$nr = array();
$count = array();
foreach ( $this->data as $data )
{
if ( !isset( $nr[$data->displayType->default] ) )
{
$nr[$data->displayType->default] = 0;
$count[$data->displayType->default] = 0;
}
$nr[$data->displayType->default]++;
$count[$data->displayType->default]++;
}
$checkedRegularSteps = false;
// Display data
foreach ( $this->data as $datasetName => $data )
{
--$nr[$data->displayType->default];
// Check which axis should be used
$xAxis = ( $data->xAxis->default ? $data->xAxis->default: $this->elements['xAxis'] );
$yAxis = ( $data->yAxis->default ? $data->yAxis->default: $this->elements['yAxis'] );
// Determine fill color for dataset
if ( $this->options->fillLines !== false )
{
$fillColor = clone $data->color->default;
$fillColor->alpha = (int) round( ( 255 - $fillColor->alpha ) * ( $this->options->fillLines / 255 ) );
}
else
{
$fillColor = null;
}
// Ensure regular steps on axis when used with bar charts and
// precalculate some values use to render bar charts
//
// Called only once and only when bars should be rendered
if ( ( $checkedRegularSteps === false ) &&
( $data->displayType->default === ezcGraph::BAR ) )
{
$steps = $xAxis->getSteps();
$stepWidth = null;
foreach ( $steps as $step )
{
if ( $stepWidth === null )
{
$stepWidth = $step->width;
}
elseif ( $step->width !== $stepWidth )
{
throw new ezcGraphUnregularStepsException();
}
}
$step = reset( $steps );
if ( count( $step->childs ) )
{
// Keep this for BC reasons
$barCount = ( $xAxis->getMajorStepCount() + 1 ) * ( $xAxis->getMinorStepCount() - 1 );
$stepWidth = 1 / $barCount;
}
$checkedRegularSteps = true;
$width = $xAxis->axisLabelRenderer->modifyChartDataPosition(
$yAxis->axisLabelRenderer->modifyChartDataPosition(
new ezcGraphCoordinate(
( $boundings->x1 - $boundings->x0 ) * $stepWidth,
0
)
)
)->x;
}
// Draw lines for dataset
$lastPoint = false;
foreach ( $data as $key => $value )
{
// Calculate point in chart
$point = $xAxis->axisLabelRenderer->modifyChartDataPosition(
$yAxis->axisLabelRenderer->modifyChartDataPosition(
new ezcGraphCoordinate(
$xAxis->getCoordinate( $key ),
$yAxis->getCoordinate( $value )
)
)
);
// Render depending on display type of dataset
switch ( true )
{
case $data->displayType->default === ezcGraph::LINE:
$renderer->drawDataLine(
$boundings,
new ezcGraphContext( $datasetName, $key, $data->url[$key] ),
$data->color->default,
( $lastPoint === false ? $point : $lastPoint ),
$point,
$nr[$data->displayType->default],
$count[$data->displayType->default],
$data->symbol[$key],
$data->color[$key],
$fillColor,
$yAxisNullPosition,
( $data->lineThickness->default ? $data->lineThickness->default : $this->options->lineThickness )
);
break;
case ( $data->displayType->default === ezcGraph::BAR ) &&
$this->options->stackBars :
// Check if a bar has already been stacked
if ( !isset( $stackedValue[(int) ( $point->x * 10000 )][(int) $value > 0] ) )
{
$start = new ezcGraphCoordinate(
$point->x,
$yAxisNullPosition
);
$stackedValue[(int) ( $point->x * 10000 )][(int) $value > 0] = $value;
}
else
{
$start = $xAxis->axisLabelRenderer->modifyChartDataPosition(
$yAxis->axisLabelRenderer->modifyChartDataPosition(
new ezcGraphCoordinate(
$xAxis->getCoordinate( $key ),
$yAxis->getCoordinate( $stackedValue[(int) ( $point->x * 10000 )][(int) $value > 0] )
)
)
);
$point = $xAxis->axisLabelRenderer->modifyChartDataPosition(
$yAxis->axisLabelRenderer->modifyChartDataPosition(
new ezcGraphCoordinate(
$xAxis->getCoordinate( $key ),
$yAxis->getCoordinate( $stackedValue[(int) ( $point->x * 10000 )][(int) $value > 0] += $value )
)
)
);
}
// Force one symbol for each stacked bar
if ( !isset( $stackedSymbol[(int) ( $point->x * 10000 )] ) )
{
$stackedSymbol[(int) ( $point->x * 10000 )] = $data->symbol[$key];
}
// Store stacked value for next iteration
$stacked[(int) ( $point->x * 10000 )][$point->y / abs( $point->y )] = $point;
$renderer->drawStackedBar(
$boundings,
new ezcGraphContext( $datasetName, $key, $data->url[$key] ),
$data->color->default,
$start,
$point,
$width,
$stackedSymbol[(int) ( $point->x * 10000 )],
$yAxisNullPosition
);
break;
case $data->displayType->default === ezcGraph::BAR:
$renderer->drawBar(
$boundings,
new ezcGraphContext( $datasetName, $key, $data->url[$key] ),
$data->color[$key],
$point,
$width,
$nr[$data->displayType->default],
$count[$data->displayType->default],
$data->symbol[$key],
$yAxisNullPosition
);
break;
default:
throw new ezcGraphInvalidDisplayTypeException( $data->displayType->default );
break;
}
// Render highlight string if requested
if ( $data->highlight[$key] )
{
$renderer->drawDataHighlightText(
$boundings,
new ezcGraphContext( $datasetName, $key, $data->url[$key] ),
$point,
$yAxisNullPosition,
$nr[$data->displayType->default],
$count[$data->displayType->default],
$this->options->highlightFont,
( $data->highlightValue[$key] ? $data->highlightValue[$key] : $value ),
$this->options->highlightSize + $this->options->highlightFont->padding * 2,
( $this->options->highlightLines ? $data->color[$key] : null )
);
}
// Store last point, used to connect lines in line chart.
$lastPoint = $point;
}
}
}
/**
* Returns the default display type of the current chart type.
*
* @return int Display type
*/
public function getDefaultDisplayType()
{
return ezcGraph::LINE;
}
/**
* Check if renderer supports features requested by some special chart
* options.
*
* @throws ezcBaseValueException
* If some feature is not supported
*
* @return void
*/
protected function checkRenderer()
{
// When stacked bars are enabled, check if renderer supports them
if ( $this->options->stackBars )
{
if ( !$this->renderer instanceof ezcGraphStackedBarsRenderer )
{
throw new ezcBaseValueException( 'renderer', $this->renderer, 'ezcGraphStackedBarsRenderer' );
}
}
}
/**
* Aggregate and calculate value boundings on axis.
*
* @return void
*/
protected function setAxisValues()
{
// Virtual data set build for agrregated values sums for bar charts
$virtualBarSumDataSet = array( array(), array() );
// Calculate axis scaling and labeling
foreach ( $this->data as $dataset )
{
$nr = 0;
$labels = array();
$values = array();
foreach ( $dataset as $label => $value )
{
$labels[] = $label;
$values[] = $value;
// Build sum of all bars
if ( $this->options->stackBars &&
( $dataset->displayType->default === ezcGraph::BAR ) )
{
if ( !isset( $virtualBarSumDataSet[(int) $value >= 0][$nr] ) )
{
$virtualBarSumDataSet[(int) $value >= 0][$nr++] = $value;
}
else
{
$virtualBarSumDataSet[(int) $value >= 0][$nr++] += $value;
}
}
}
// Check if data has been associated with another custom axis, use
// default axis otherwise.
if ( $dataset->xAxis->default )
{
$dataset->xAxis->default->addData( $labels );
}
else
{
$this->elements['xAxis']->addData( $labels );
}
if ( $dataset->yAxis->default )
{
$dataset->yAxis->default->addData( $values );
}
else
{
$this->elements['yAxis']->addData( $values );
}
}
// Also use stacked bar values as base for y axis value span
// calculation
if ( $this->options->stackBars )
{
$this->elements['yAxis']->addData( $virtualBarSumDataSet[0] );
$this->elements['yAxis']->addData( $virtualBarSumDataSet[1] );
}
// There should always be something assigned to the main x and y axis.
if ( !$this->elements['xAxis']->initialized ||
!$this->elements['yAxis']->initialized )
{
throw new ezcGraphNoDataException();
}
// Calculate boundings from assigned data
$this->elements['xAxis']->calculateAxisBoundings();
$this->elements['yAxis']->calculateAxisBoundings();
}
/**
* Renders the basic elements of this chart type
*
* @param int $width
* @param int $height
* @return void
*/
protected function renderElements( $width, $height )
{
if ( !count( $this->data ) )
{
throw new ezcGraphNoDataException();
}
// Check if renderer supports requested features
$this->checkRenderer();
// Set values form datasets on axis to calculate correct spans
$this->setAxisValues();
// Generate legend
$this->elements['legend']->generateFromDataSets( $this->data );
// Get boundings from parameters
$this->options->width = $width;
$this->options->height = $height;
// Set image properties in driver
$this->driver->options->width = $width;
$this->driver->options->height = $height;
// Render subelements
$boundings = new ezcGraphBoundings();
$boundings->x1 = $this->options->width;
$boundings->y1 = $this->options->height;
$boundings = $this->elements['xAxis']->axisLabelRenderer->modifyChartBoundings(
$this->elements['yAxis']->axisLabelRenderer->modifyChartBoundings(
$boundings, new ezcGraphCoordinate( 1, 0 )
), new ezcGraphCoordinate( -1, 0 )
);
// Render subelements
foreach ( $this->elements as $name => $element )
{
// Skip element, if it should not get rendered
if ( $this->renderElement[$name] === false )
{
continue;
}
// Special settings for special elements
switch ( $name )
{
case 'xAxis':
// get Position of 0 on the Y-axis for orientation of the x-axis
$element->nullPosition = $this->elements['yAxis']->getCoordinate( false );
break;
case 'yAxis':
// get Position of 0 on the X-axis for orientation of the y-axis
$element->nullPosition = $this->elements['xAxis']->getCoordinate( false );
break;
}
$this->driver->options->font = $element->font;
$boundings = $element->render( $this->renderer, $boundings );
}
// Render additional axis
foreach ( $this->additionalAxis as $element )
{
if ( $element->initialized )
{
// Calculate all required step sizes if values has been
// assigned to axis.
$element->calculateAxisBoundings();
}
else
{
// Do not render any axis labels, if no values were assigned
// and no step sizes were defined.
$element->axisLabelRenderer = new ezcGraphAxisNoLabelRenderer();
}
$this->driver->options->font = $element->font;
$element->nullPosition = $element->chartPosition;
$boundings = $element->render( $this->renderer, $boundings );
}
// Render graph
$this->renderData( $this->renderer, $boundings );
}
/**
* Render the line chart
*
* Renders the chart into a file or stream. The width and height are
* needed to specify the dimensions of the resulting image. For direct
* output use 'php://stdout' as output file.
*
* @param int $width Image width
* @param int $height Image height
* @param string $file Output file
* @apichange
* @return void
*/
public function render( $width, $height, $file = null )
{
$this->renderElements( $width, $height );
if ( !empty( $file ) )
{
$this->renderer->render( $file );
}
$this->renderedFile = $file;
}
/**
* 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
* @apichange
* @return void
*/
public function renderToOutput( $width, $height )
{
// @TODO: merge this function with render an deprecate ommit of third
// argument in render() when API break is possible
$this->renderElements( $width, $height );
$this->renderer->render( null );
}
}
?>
@@ -0,0 +1,296 @@
<?php
/**
* File containing the ezcGraphOdometerChart 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 odometer charts. Can only use one dataset which will be dispalyed
* as a odometer chart.
*
* <code>
* $graph = new ezcGraphOdometerChart();
* $graph->title = 'Custom odometer';
*
* $graph->data['data'] = new ezcGraphArrayDataSet(
* array( 87 )
* );
*
* // Set the marker color
* $graph->data['data']->color[0] = '#A0000055';
*
* // Set colors for the background gradient
* $graph->options->startColor = '#2E3436';
* $graph->options->endColor = '#EEEEEC';
*
* // Define a border for the odometer
* $graph->options->borderWidth = 2;
* $graph->options->borderColor = '#BABDB6';
*
* // Set marker width
* $graph->options->markerWidth = 5;
*
* // Set space, which the odometer may consume
* $graph->options->odometerHeight = .7;
*
* // Set axis span and label
* $graph->axis->min = 0;
* $graph->axis->max = 100;
* $graph->axis->label = 'Coverage ';
*
* $graph->render( 400, 150, 'custom_odometer_chart.svg' );
* </code>
*
* Each chart consists of several chart elements which represents logical parts
* of the chart and can be formatted independently. The odometer chart consists
* of:
* - title ( {@link ezcGraphChartElementText} )
* - background ( {@link ezcGraphChartElementBackground} )
*
* All elements can be configured by accessing them as properties of the chart:
*
* <code>
* $chart->title->position = ezcGraph::BOTTOM;
* </code>
*
* The chart itself also offers several options to configure the appearance.
* The extended configure options are available in
* {@link ezcGraphOdometerChartOptions} extending the {@link
* ezcGraphChartOptions}.
*
* @property ezcGraphOdometerChartOptions $options
* Chart options class
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphOdometerChart extends ezcGraphChart
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->options = new ezcGraphOdometerChartOptions( $options );
parent::__construct( $options );
$this->data = new ezcGraphChartSingleDataContainer( $this );
$this->addElement( 'axis', new ezcGraphChartElementNumericAxis());
$this->elements['axis']->axisLabelRenderer = new ezcGraphAxisCenteredLabelRenderer();
$this->elements['axis']->axisLabelRenderer->showZeroValue = true;
$this->elements['axis']->position = ezcGraph::LEFT;
$this->elements['axis']->axisSpace = .05;
}
/**
* Property write access
*
* @throws ezcBasePropertyNotFoundException
* If Option could not be found
* @throws ezcBaseValueException
* If value is out of range
* @param string $propertyName Option name
* @param mixed $propertyValue Option value;
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName ) {
case 'axis':
if ( $propertyValue instanceof ezcGraphChartElementAxis )
{
$this->addElement( 'axis', $propertyValue );
$this->elements['axis']->axisLabelRenderer = new ezcGraphAxisCenteredLabelRenderer();
$this->elements['axis']->axisLabelRenderer->showZeroValue = true;
$this->elements['axis']->position = ezcGraph::LEFT;
$this->elements['axis']->axisSpace = .05;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphChartElementAxis' );
}
break;
case 'renderer':
if ( $propertyValue instanceof ezcGraphOdometerRenderer )
{
parent::__set( $propertyName, $propertyValue );
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphOdometerRenderer' );
}
break;
default:
parent::__set( $propertyName, $propertyValue );
}
}
/**
* Render the assigned data
*
* Will renderer all charts data in the remaining boundings after drawing
* all other chart elements. The data will be rendered depending on the
* settings in the dataset.
*
* @param ezcGraphRenderer $renderer Renderer
* @param ezcGraphBoundings $boundings Remaining boundings
* @return void
*/
protected function renderData( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings )
{
// Draw the odometer data
$dataset = $this->data->rewind();
foreach ( $dataset as $key => $value )
{
$renderer->drawOdometerMarker(
$boundings,
$this->elements['axis']->axisLabelRenderer->modifyChartDataPosition(
new ezcGraphCoordinate(
$this->elements['axis']->getCoordinate( $value ),
0
)
),
$dataset->symbol[$key],
$dataset->color[$key],
$this->options->markerWidth
);
}
}
/**
* Returns the default display type of the current chart type.
*
* @return int Display type
*/
public function getDefaultDisplayType()
{
return ezcGraph::ODOMETER;
}
/**
* Renders the basic elements of this chart type
*
* @param int $width
* @param int $height
* @return void
*/
protected function renderElements( $width, $height )
{
if ( !count( $this->data ) )
{
throw new ezcGraphNoDataException();
}
// Set image properties in driver
$this->driver->options->width = $width;
$this->driver->options->height = $height;
// no legend
$this->renderElement['legend'] = false;
// Get boundings from parameters
$this->options->width = $width;
$this->options->height = $height;
$boundings = new ezcGraphBoundings();
$boundings->x1 = $this->options->width;
$boundings->y1 = $this->options->height;
// Get values out the single used dataset to calculate axis boundings
$values = array();
foreach ( $this->data->rewind() as $value )
{
$values[] = $value;
}
// Set values for Axis
$this->elements['axis']->addData( $values );
$this->elements['axis']->nullPosition = 0.5 + $this->options->odometerHeight / 2;
$this->elements['axis']->calculateAxisBoundings();
// Render subelements exept axis, which will be drawn together with the
// odometer bar
foreach ( $this->elements as $name => $element )
{
// Skip element, if it should not get rendered
if ( $this->renderElement[$name] === false ||
$name === 'axis' )
{
continue;
}
$this->driver->options->font = $element->font;
$boundings = $element->render( $this->renderer, $boundings );
}
// Draw basic odometer
$this->driver->options->font = $this->elements['axis']->font;
$boundings = $this->renderer->drawOdometer(
$boundings,
$this->elements['axis'],
$this->options
);
// Render graph
$this->renderData( $this->renderer, $boundings );
}
/**
* Render the pie chart
*
* Renders the chart into a file or stream. The width and height are
* needed to specify the dimensions of the resulting image. For direct
* output use 'php://stdout' as output file.
*
* @param int $width Image width
* @param int $height Image height
* @param string $file Output file
* @apichange
* @return void
*/
public function render( $width, $height, $file = null )
{
$this->renderElements( $width, $height );
if ( !empty( $file ) )
{
$this->renderer->render( $file );
}
$this->renderedFile = $file;
}
/**
* 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
* @apichange
* @return void
*/
public function renderToOutput( $width, $height )
{
// @TODO: merge this function with render an deprecate ommit of third
// argument in render() when API break is possible
$this->renderElements( $width, $height );
$this->renderer->render( null );
}
}
?>
@@ -0,0 +1,308 @@
<?php
/**
* File containing the ezcGraphPieChart 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 pie charts. Can only use one dataset which will be dispalyed as a
* pie chart.
*
* <code>
* // Create a new pie chart
* $chart = new ezcGraphPieChart();
*
* // Add data to line chart
* $chart->data['sample dataset'] = new ezcGraphArrayDataSet(
* array(
* 'one' => 1.2,
* 'two' => 43.2,
* 'three' => -34.14,
* 'four' => 65,
* 'five' => 123,
* )
* );
*
* // Render chart with default 2d renderer and default SVG driver
* $chart->render( 500, 200, 'pie_chart.svg' );
* </code>
*
* Each chart consists of several chart elements which represents logical
* parts of the chart and can be formatted independently. The pie chart
* consists of:
* - title ( {@link ezcGraphChartElementText} )
* - legend ( {@link ezcGraphChartElementLegend} )
* - background ( {@link ezcGraphChartElementBackground} )
*
* All elements can be configured by accessing them as properties of the chart:
*
* <code>
* $chart->legend->position = ezcGraph::RIGHT;
* </code>
*
* The chart itself also offers several options to configure the appearance.
* The extended configure options are available in
* {@link ezcGraphPieChartOptions} extending the {@link ezcGraphChartOptions}.
*
* @property ezcGraphPieChartOptions $options
* Chart options class
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphPieChart extends ezcGraphChart
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->options = new ezcGraphPieChartOptions( $options );
parent::__construct( $options );
$this->data = new ezcGraphChartSingleDataContainer( $this );
}
/**
* Render the assigned data
*
* Will renderer all charts data in the remaining boundings after drawing
* all other chart elements. The data will be rendered depending on the
* settings in the dataset.
*
* @param ezcGraphRenderer $renderer Renderer
* @param ezcGraphBoundings $boundings Remaining boundings
* @return void
*/
protected function renderData( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings )
{
// Only draw the first (and only) dataset
$dataset = $this->data->rewind();
$datasetName = $this->data->key();
$this->driver->options->font = $this->options->font;
// Calculate sum of all values to be able to calculate percentage
$sum = 0;
foreach ( $dataset as $name => $value )
{
if ( $value < 0 )
{
throw new ezcGraphInvalidDataException( "Values >= 0 required, '$name' => '$value'." );
}
$sum += $value;
}
if ( $this->options->sum !== false )
{
$sum = max( $sum, $this->options->sum );
}
if ( $sum <= 0 )
{
throw new ezcGraphInvalidDataException( "Pie charts require a value sum > 0, your value: '$sum'." );
}
$angle = 0;
foreach ( $dataset as $label => $value )
{
// Skip rendering values which equals 0
if ( $value <= 0 )
{
continue;
}
switch ( $dataset->displayType->default )
{
case ezcGraph::PIE:
$displayLabel = ( $this->options->labelCallback !== null
? call_user_func( $this->options->labelCallback, $label, $value, $value / $sum )
: sprintf( $this->options->label, $label, $value, $value / $sum * 100 ) );
$renderer->drawPieSegment(
$boundings,
new ezcGraphContext( $datasetName, $label, $dataset->url[$label] ),
$dataset->color[$label],
$angle,
$angle += $value / $sum * 360,
$displayLabel,
$dataset->highlight[$label]
);
break;
default:
throw new ezcGraphInvalidDisplayTypeException( $dataset->displayType->default );
break;
}
}
}
/**
* Returns the default display type of the current chart type.
*
* @return int Display type
*/
public function getDefaultDisplayType()
{
return ezcGraph::PIE;
}
/**
* Apply tresh hold
*
* Iterates over the dataset and applies the configured tresh hold to
* the datasets data.
*
* @return void
*/
protected function applyThreshold()
{
if ( $this->options->percentThreshold || $this->options->absoluteThreshold )
{
$dataset = $this->data->rewind();
$sum = 0;
foreach ( $dataset as $value )
{
$sum += $value;
}
if ( $this->options->sum !== false )
{
$sum = max( $sum, $this->options->sum );
}
$unset = array();
foreach ( $dataset as $label => $value )
{
if ( $label === $this->options->summarizeCaption )
{
continue;
}
if ( ( $value <= $this->options->absoluteThreshold ) ||
( ( $value / $sum ) <= $this->options->percentThreshold ) )
{
if ( !isset( $dataset[$this->options->summarizeCaption] ) )
{
$dataset[$this->options->summarizeCaption] = $value;
}
else
{
$dataset[$this->options->summarizeCaption] += $value;
}
$unset[] = $label;
}
}
foreach ( $unset as $label )
{
unset( $dataset[$label] );
}
}
}
/**
* Renders the basic elements of this chart type
*
* @param int $width
* @param int $height
* @return void
*/
protected function renderElements( $width, $height )
{
if ( !count( $this->data ) )
{
throw new ezcGraphNoDataException();
}
// Set image properties in driver
$this->driver->options->width = $width;
$this->driver->options->height = $height;
// Apply tresh hold
$this->applyThreshold();
// Generate legend
$this->elements['legend']->generateFromDataSet( $this->data->rewind() );
// Get boundings from parameters
$this->options->width = $width;
$this->options->height = $height;
$boundings = new ezcGraphBoundings();
$boundings->x1 = $this->options->width;
$boundings->y1 = $this->options->height;
// Render subelements
foreach ( $this->elements as $name => $element )
{
// Skip element, if it should not get rendered
if ( $this->renderElement[$name] === false )
{
continue;
}
$this->driver->options->font = $element->font;
$boundings = $element->render( $this->renderer, $boundings );
}
// Render graph
$this->renderData( $this->renderer, $boundings );
}
/**
* Render the pie chart
*
* Renders the chart into a file or stream. The width and height are
* needed to specify the dimensions of the resulting image. For direct
* output use 'php://stdout' as output file.
*
* @param int $width Image width
* @param int $height Image height
* @param string $file Output file
* @apichange
* @return void
*/
public function render( $width, $height, $file = null )
{
$this->renderElements( $width, $height );
if ( !empty( $file ) )
{
$this->renderer->render( $file );
}
$this->renderedFile = $file;
}
/**
* 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
* @apichange
* @return void
*/
public function renderToOutput( $width, $height )
{
// @TODO: merge this function with render an deprecate ommit of third
// argument in render() when API break is possible
$this->renderElements( $width, $height );
$this->renderer->render( null );
}
}
?>
@@ -0,0 +1,457 @@
<?php
/**
* File containing the ezcGraphRadarChart 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 radar charts.
* Can make use of an unlimited amount of datasets and will display them as
* lines by default.
* Rotation axis:
* - Labeled axis
* - Centered axis label renderer
* Axis:
* - Numeric axis
* - radar axis label renderer
*
* <code>
* // Create a new radar chart
* $chart = new ezcGraphRadarChart();
*
* // Add data to line chart
* $chart->data['sample dataset'] = new ezcGraphArrayDataSet(
* array(
* '100' => 1.2,
* '200' => 43.2,
* '300' => -34.14,
* '350' => 65,
* '400' => 123,
* )
* );
*
* // Render chart with default 2d renderer and default SVG driver
* $chart->render( 500, 200, 'radar_chart.svg' );
* </code>
*
* Each chart consists of several chart elements which represents logical
* parts of the chart and can be formatted independently. The line chart
* consists of:
* - title ( {@link ezcGraphChartElementText} )
* - legend ( {@link ezcGraphChartElementLegend} )
* - background ( {@link ezcGraphChartElementBackground} )
* - axis ( {@link ezcGraphChartElementNumericAxis} )
* - ratation axis ( {@link ezcGraphChartElementLabeledAxis} )
*
* The type of the axis may be changed and all elements can be configured by
* accessing them as properties of the chart:
*
* The chart itself also offers several options to configure the appearance.
* The extended configure options are available in
* {@link ezcGraphRadarChartOptions} extending the
* {@link ezcGraphChartOptions}.
*
* <code>
* $chart->legend->position = ezcGraph::RIGHT;
* </code>
*
* @property ezcGraphRadarChartOptions $options
* Chart options class
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphRadarChart extends ezcGraphChart
{
/**
* Store major grid color for child axis.
*
* @var ezcGraphColor
*/
protected $childAxisColor;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->options = new ezcGraphRadarChartOptions( $options );
$this->options->highlightFont = $this->options->font;
parent::__construct();
$this->elements['rotationAxis'] = new ezcGraphChartElementLabeledAxis();
$this->addElement( 'axis', new ezcGraphChartElementNumericAxis() );
$this->elements['axis']->position = ezcGraph::BOTTOM;
$this->elements['axis']->axisLabelRenderer = new ezcGraphAxisRadarLabelRenderer();
$this->elements['axis']->axisLabelRenderer->outerStep = true;
$this->addElement( 'rotationAxis', new ezcGraphChartElementLabeledAxis() );
// Do not render axis with default method, because we need an axis for
// each label in dataset
$this->renderElement['axis'] = false;
$this->renderElement['rotationAxis'] = false;
}
/**
* Set colors and border fro this element
*
* @param ezcGraphPalette $palette Palette
* @return void
*/
public function setFromPalette( ezcGraphPalette $palette )
{
$this->childAxisColor = $palette->majorGridColor;
parent::setFromPalette( $palette );
}
/**
* Property write access
*
* @throws ezcBasePropertyNotFoundException
* If Option could not be found
* @throws ezcBaseValueException
* If value is out of range
* @param string $propertyName Option name
* @param mixed $propertyValue Option value;
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName ) {
case 'axis':
if ( $propertyValue instanceof ezcGraphChartElementAxis )
{
$this->addElement( 'axis', $propertyValue );
$this->elements['axis']->position = ezcGraph::BOTTOM;
$this->elements['axis']->axisLabelRenderer = new ezcGraphAxisRadarLabelRenderer();
$this->renderElement['axis'] = false;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphChartElementAxis' );
}
break;
case 'rotationAxis':
if ( $propertyValue instanceof ezcGraphChartElementAxis )
{
$this->addElement( 'rotationAxis', $propertyValue );
$this->renderElement['rotationAxis'] = false;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphChartElementAxis' );
}
break;
case 'renderer':
if ( $propertyValue instanceof ezcGraphRadarRenderer )
{
parent::__set( $propertyName, $propertyValue );
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphRadarRenderer' );
}
break;
default:
parent::__set( $propertyName, $propertyValue );
}
}
/**
* Draws a single rotated axis
*
* Sets the axis label position depending on the axis rotation.
*
* @param ezcGraphChartElementAxis $axis
* @param ezcGraphBoundings $boundings
* @param ezcGraphCoordinate $center
* @param float $position
* @param float $lastPosition
* @return void
*/
protected function drawRotatedAxis( ezcGraphChartElementAxis $axis, ezcGraphBoundings $boundings, ezcGraphCoordinate $center, $position, $lastPosition = null )
{
// Set axis position depending on angle for better axis label
// positioning
$angle = $position * 2 * M_PI;
switch ( (int) ( ( $position + .125 ) * 4 ) )
{
case 0:
case 4:
$axis->position = ezcGraph::BOTTOM;
break;
case 1:
$axis->position = ezcGraph::LEFT;
break;
case 2:
$axis->position = ezcGraph::TOP;
break;
case 3:
$axis->position = ezcGraph::RIGHT;
break;
}
// Set last step to correctly draw grid
if ( $axis->axisLabelRenderer instanceof ezcGraphAxisRadarLabelRenderer )
{
$axis->axisLabelRenderer->lastStep = $lastPosition;
}
// Do not draw axis label for last step
if ( abs( $position - 1 ) <= .001 )
{
$axis->label = null;
}
$this->renderer->drawAxis(
$boundings,
clone $center,
$dest = new ezcGraphCoordinate(
$center->x + sin( $angle ) * ( $boundings->width / 2 ),
$center->y - cos( $angle ) * ( $boundings->height / 2 )
),
clone $axis,
clone $axis->axisLabelRenderer
);
}
/**
* Render the assigned data
*
* Will renderer all charts data in the remaining boundings after drawing
* all other chart elements. The data will be rendered depending on the
* settings in the dataset.
*
* @param ezcGraphRenderer $renderer Renderer
* @param ezcGraphBoundings $boundings Remaining boundings
* @return void
*/
protected function renderData( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings )
{
// Apply axis space
$xAxisSpace = ( $boundings->x1 - $boundings->x0 ) * $this->axis->axisSpace;
$yAxisSpace = ( $boundings->y1 - $boundings->y0 ) * $this->axis->axisSpace;
$center = new ezcGraphCoordinate(
( $boundings->width / 2 ),
( $boundings->height / 2 )
);
// We do not differentiate between display types in radar charts.
$nr = $count = count( $this->data );
// Draw axis at major steps of virtual axis
$steps = $this->elements['rotationAxis']->getSteps();
$lastStepPosition = null;
$axisColor = $this->elements['axis']->border;
foreach ( $steps as $step )
{
$this->elements['axis']->label = $step->label;
$this->drawRotatedAxis( $this->elements['axis'], $boundings, $center, $step->position, $lastStepPosition );
$lastStepPosition = $step->position;
if ( count( $step->childs ) )
{
foreach ( $step->childs as $childStep )
{
$this->elements['axis']->label = null;
$this->elements['axis']->border = $this->childAxisColor;
$this->drawRotatedAxis( $this->elements['axis'], $boundings, $center, $childStep->position, $lastStepPosition );
$lastStepPosition = $childStep->position;
}
}
$this->elements['axis']->border = $axisColor;
}
// Display data
$this->elements['axis']->position = ezcGraph::TOP;
foreach ( $this->data as $datasetName => $data )
{
--$nr;
// Determine fill color for dataset
if ( $this->options->fillLines !== false )
{
$fillColor = clone $data->color->default;
$fillColor->alpha = (int) round( ( 255 - $fillColor->alpha ) * ( $this->options->fillLines / 255 ) );
}
else
{
$fillColor = null;
}
// Draw lines for dataset
$lastPoint = false;
foreach ( $data as $key => $value )
{
$point = new ezcGraphCoordinate(
$this->elements['rotationAxis']->getCoordinate( $key ),
$this->elements['axis']->getCoordinate( $value )
);
/* Transformation required for 3d like renderers ...
* which axis should transform here?
$point = $this->elements['xAxis']->axisLabelRenderer->modifyChartDataPosition(
$this->elements['yAxis']->axisLabelRenderer->modifyChartDataPosition(
new ezcGraphCoordinate(
$this->elements['xAxis']->getCoordinate( $key ),
$this->elements['yAxis']->getCoordinate( $value )
)
)
);
// */
$renderer->drawRadarDataLine(
$boundings,
new ezcGraphContext( $datasetName, $key, $data->url[$key] ),
$data->color->default,
clone $center,
( $lastPoint === false ? $point : $lastPoint ),
$point,
$nr,
$count,
$data->symbol[$key],
$data->color[$key],
$fillColor,
$this->options->lineThickness
);
$lastPoint = $point;
}
}
}
/**
* Returns the default display type of the current chart type.
*
* @return int Display type
*/
public function getDefaultDisplayType()
{
return ezcGraph::LINE;
}
/**
* Renders the basic elements of this chart type
*
* @param int $width
* @param int $height
* @return void
*/
protected function renderElements( $width, $height )
{
if ( !count( $this->data ) )
{
throw new ezcGraphNoDataException();
}
// Set image properties in driver
$this->driver->options->width = $width;
$this->driver->options->height = $height;
// Calculate axis scaling and labeling
foreach ( $this->data as $dataset )
{
$labels = array();
$values = array();
foreach ( $dataset as $label => $value )
{
$labels[] = $label;
$values[] = $value;
}
$this->elements['axis']->addData( $values );
$this->elements['rotationAxis']->addData( $labels );
}
$this->elements['axis']->calculateAxisBoundings();
$this->elements['rotationAxis']->calculateAxisBoundings();
// Generate legend
$this->elements['legend']->generateFromDataSets( $this->data );
// Get boundings from parameters
$this->options->width = $width;
$this->options->height = $height;
// Render subelements
$boundings = new ezcGraphBoundings();
$boundings->x1 = $this->options->width;
$boundings->y1 = $this->options->height;
// Render subelements
foreach ( $this->elements as $name => $element )
{
// Skip element, if it should not get rendered
if ( $this->renderElement[$name] === false )
{
continue;
}
$this->driver->options->font = $element->font;
$boundings = $element->render( $this->renderer, $boundings );
}
// Render graph
$this->renderData( $this->renderer, $boundings );
}
/**
* Render the line chart
*
* Renders the chart into a file or stream. The width and height are
* needed to specify the dimensions of the resulting image. For direct
* output use 'php://stdout' as output file.
*
* @param int $width Image width
* @param int $height Image height
* @param string $file Output file
* @apichange
* @return void
*/
public function render( $width, $height, $file = null )
{
$this->renderElements( $width, $height );
if ( !empty( $file ) )
{
$this->renderer->render( $file );
}
$this->renderedFile = $file;
}
/**
* 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
* @apichange
* @return void
*/
public function renderToOutput( $width, $height )
{
// @TODO: merge this function with render an deprecate ommit of third
// argument in render() when API break is possible
$this->renderElements( $width, $height );
$this->renderer->render( null );
}
}
?>
@@ -0,0 +1,269 @@
<?php
/**
* File containing the ezcGraphColor 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
*/
/**
* ezcGraphColor
*
* Struct for representing colors in ezcGraph. A color is defined using the
* common RGBA model with integer values between 0 and 255. An alpha value
* of zero means full opacity, while 255 means full transparency.
*
* @property integer $red
* Red RGBA value of color.
* @property integer $green
* Green RGBA value of color.
* @property integer $blue
* Blue RGBA value of color.
* @property integer $alpha
* Alpha RGBA value of color.
*
* @version 1.3
* @package Graph
*/
class ezcGraphColor extends ezcBaseOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['red'] = 0;
$this->properties['green'] = 0;
$this->properties['blue'] = 0;
$this->properties['alpha'] = 0;
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 'red':
case 'green':
case 'blue':
case 'alpha':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 255 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= int <= 255' );
}
$this->properties[$propertyName] = (int) $propertyValue;
break;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
break;
}
}
/**
* Creates an ezcGraphColor object from a hexadecimal color representation
*
* @param mixed $string Hexadecimal color representation
* @return ezcGraphColor
*/
static public function fromHex( $string )
{
// Remove trailing #
if ( $string[0] === '#' )
{
$string = substr( $string, 1 );
}
// Iterate over chunks and convert to integer
$color = new ezcGraphColor();
$keys = array( 'red', 'green', 'blue', 'alpha' );
foreach ( str_split( $string, 2) as $nr => $hexValue )
{
if ( isset( $keys[$nr] ) )
{
$key = $keys[$nr];
$color->$key = hexdec( $hexValue ) % 256;
}
}
// Set missing values to zero
for ( ++$nr; $nr < count( $keys ); ++$nr )
{
$key = $keys[$nr];
$color->$key = 0;
}
return $color;
}
/**
* Creates an ezcGraphColor object from an array of integers
*
* @param array $array Array of integer color values
* @return ezcGraphColor
*/
static public function fromIntegerArray( array $array )
{
// Iterate over array elements
$color = new ezcGraphColor();
$keys = array( 'red', 'green', 'blue', 'alpha' );
$nr = 0;
foreach ( $array as $colorValue )
{
if ( isset( $keys[$nr] ) )
{
$key = $keys[$nr++];
$color->$key = ( (int) $colorValue ) % 256;
}
}
// Set missing values to zero
for ( $nr; $nr < count( $keys ); ++$nr )
{
$key = $keys[$nr];
$color->$key = 0;
}
return $color;
}
/**
* Creates an ezcGraphColor object from an array of floats
*
* @param array $array Array of float color values
* @return ezcGraphColor
*/
static public function fromFloatArray( array $array )
{
// Iterate over array elements
$color = new ezcGraphColor();
$keys = array( 'red', 'green', 'blue', 'alpha' );
$nr = 0;
foreach ( $array as $colorValue )
{
if ( isset( $keys[$nr] ) )
{
$key = $keys[$nr++];
$color->$key = ( (float) $colorValue * 255 ) % 256;
}
}
// Set missing values to zero
for ( $nr; $nr < count( $keys ); ++$nr )
{
$key = $keys[$nr];
$color->$key = 0;
}
return $color;
}
/**
* Tries to detect type of color color definition and returns an
* ezcGraphColor object
*
* @param mixed $color Some kind of color definition
* @return ezcGraphColor
*/
static public function create( $color )
{
if ( $color instanceof ezcGraphColor )
{
return $color;
}
elseif ( is_string( $color ) )
{
return ezcGraphColor::fromHex( $color );
}
elseif ( is_array( $color ) )
{
$testElement = reset( $color );
if ( is_int( $testElement ) )
{
return ezcGraphColor::fromIntegerArray( $color );
}
else
{
return ezcGraphColor::fromFloatArray( $color );
}
}
else
{
throw new ezcGraphUnknownColorDefinitionException( $color );
}
}
/**
* Returns a copy of the current color made more transparent by the given
* factor
*
* @param mixed $value Percent to make color mor transparent
* @return ezcGraphColor New color
*/
public function transparent( $value )
{
$color = clone $this;
$color->alpha = 255 - (int) round( ( 255 - $this->alpha ) * ( 1 - $value ) );
return $color;
}
/**
* Inverts and returns a copy of the current color
*
* @return ezcGraphColor New Color
*/
public function invert()
{
$color = new ezcGraphColor();
$color->red = 255 - $this->red;
$color->green = 255 - $this->green;
$color->blue = 255 - $this->blue;
$color->alpha = $this->alpha;
return $color;
}
/**
* Returns a copy of the current color darkened by the given factor
*
* @param float $value Percent to darken the color
* @return ezcGraphColor New color
*/
public function darken( $value )
{
$color = clone $this;
$value = 1 - $value;
$color->red = min( 255, max( 0, (int) round( $this->red * $value ) ) );
$color->green = min( 255, max( 0, (int) round( $this->green * $value ) ) );
$color->blue = min( 255, max( 0, (int) round( $this->blue * $value ) ) );
return $color;
}
}
?>
@@ -0,0 +1,147 @@
<?php
/**
* File containing the ezcGraphLinearGradient 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 representing linear gradient fills. For drivers which cannot draw
* gradients it falls back to a native {@link ezcGraphColor}. In this case the
* start color of the gradient will be used.
*
* @property ezcGraphCoordinate $startPoint
* Starting point of the gradient.
* @property ezcGraphCoordinate $endPoint
* Ending point of the gradient.
* @property ezcGraphColor $startColor
* Starting color of the gradient.
* @property ezcGraphColor $endColor
* Ending color of the gradient.
*
* @version 1.3
* @package Graph
*/
class ezcGraphLinearGradient extends ezcGraphColor
{
/**
* Constructor
*
* @param ezcGraphCoordinate $startPoint
* @param ezcGraphCoordinate $endPoint
* @param ezcGraphColor $startColor
* @param ezcGraphColor $endColor
* @return void
*/
public function __construct( ezcGraphCoordinate $startPoint, ezcGraphCoordinate $endPoint, ezcGraphColor $startColor, ezcGraphColor $endColor )
{
$this->properties['startColor'] = $startColor;
$this->properties['endColor'] = $endColor;
$this->properties['startPoint'] = $startPoint;
$this->properties['endPoint'] = $endPoint;
}
/**
* __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 'startPoint':
if ( !$propertyValue instanceof ezcGraphCoordinate )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphCoordinate' );
}
else
{
$this->properties['startPoint'] = $propertyValue;
}
break;
case 'endPoint':
if ( !$propertyValue instanceof ezcGraphCoordinate )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphCoordinate' );
}
else
{
$this->properties['endPoint'] = $propertyValue;
}
break;
case 'startColor':
$this->properties['startColor'] = ezcGraphColor::create( $propertyValue );
break;
case 'endColor':
$this->properties['endColor'] = ezcGraphColor::create( $propertyValue );
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 'red':
case 'green':
case 'blue':
case 'alpha':
// Fallback to native color
return $this->properties['startColor']->$propertyName;
default:
if ( isset( $this->properties[$propertyName] ) )
{
return $this->properties[$propertyName];
}
else
{
throw new ezcBasePropertyNotFoundException( $propertyName );
}
}
}
/**
* Returns a unique string representation for the gradient.
*
* @access public
* @return void
*/
public function __toString()
{
return sprintf( 'LinearGradient_%d_%d_%d_%d_%02x%02x%02x%02x_%02x%02x%02x%02x',
$this->properties['startPoint']->x,
$this->properties['startPoint']->y,
$this->properties['endPoint']->x,
$this->properties['endPoint']->y,
$this->properties['startColor']->red,
$this->properties['startColor']->green,
$this->properties['startColor']->blue,
$this->properties['startColor']->alpha,
$this->properties['endColor']->red,
$this->properties['endColor']->green,
$this->properties['endColor']->blue,
$this->properties['endColor']->alpha
);
}
}
?>
@@ -0,0 +1,173 @@
<?php
/**
* File containing the ezcGraphRadialGradient 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 representing radial gradient fills. For drivers which cannot draw
* gradients it falls back to a native ezcGraphColor. In this case the start
* color of the gradient will be used.
*
* @property ezcGraphCoordinate $center
* Center point of the gradient.
* @property int $width
* Width of ellipse
* @property int $height
* Width of ellipse
* @property int $offset
* Offset for starting color
* @property ezcGraphColor $startColor
* Starting color of the gradient.
* @property ezcGraphColor $endColor
* Ending color of the gradient.
*
* @version 1.3
* @package Graph
*/
class ezcGraphRadialGradient extends ezcGraphColor
{
/**
* Constructor
*
* @param ezcGraphCoordinate $center
* @param mixed $width
* @param mixed $height
* @param ezcGraphColor $startColor
* @param ezcGraphColor $endColor
* @return void
*/
public function __construct( ezcGraphCoordinate $center, $width, $height, ezcGraphColor $startColor, ezcGraphColor $endColor )
{
$this->properties['center'] = $center;
$this->properties['width'] = (float) $width;
$this->properties['height'] = (float) $height;
$this->properties['offset'] = 0;
$this->properties['startColor'] = $startColor;
$this->properties['endColor'] = $endColor;
}
/**
* __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 'center':
if ( !$propertyValue instanceof ezcGraphCoordinate )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphCoordinate' );
}
else
{
$this->properties['center'] = $propertyValue;
}
break;
case 'width':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['width'] = (float) $propertyValue;
break;
case 'height':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['height'] = (float) $propertyValue;
break;
case 'offset':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['offset'] = $propertyValue;
break;
case 'startColor':
$this->properties['startColor'] = ezcGraphColor::create( $propertyValue );
break;
case 'endColor':
$this->properties['endColor'] = ezcGraphColor::create( $propertyValue );
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 'red':
case 'green':
case 'blue':
case 'alpha':
// Fallback to native color
return $this->properties['startColor']->$propertyName;
default:
if ( isset( $this->properties[$propertyName] ) )
{
return $this->properties[$propertyName];
}
else
{
throw new ezcBasePropertyNotFoundException( $propertyName );
}
}
}
/**
* Returns a unique string representation for the gradient.
*
* @access public
* @return void
*/
public function __toString()
{
return sprintf( 'RadialGradient_%d_%d_%d_%d_%.2f_%02x%02x%02x%02x_%02x%02x%02x%02x',
$this->properties['center']->x,
$this->properties['center']->y,
$this->properties['width'],
$this->properties['height'],
$this->properties['offset'],
$this->properties['startColor']->red,
$this->properties['startColor']->green,
$this->properties['startColor']->blue,
$this->properties['startColor']->alpha,
$this->properties['endColor']->red,
$this->properties['endColor']->green,
$this->properties['endColor']->blue,
$this->properties['endColor']->alpha
);
}
}
?>
@@ -0,0 +1,225 @@
<?php
/**
* File containing the abstract ezcGraphChartDataContainer 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
*/
/**
* Container class for datasets used by the chart classes. Implements usefull
* interfaces for convenient access to the datasets.
*
* @version 1.3
* @package Graph
*/
class ezcGraphChartDataContainer implements ArrayAccess, Iterator, Countable
{
/**
* Contains the data of a chart
*
* @var array(ezcGraphDataSet)
*/
protected $data = array();
/**
* Chart using this data set storage
*
* @var ezcGraphChart
*/
protected $chart;
/**
* Constructor
*
* @param ezcGraphChart $chart
* @ignore
* @return void
*/
public function __construct( ezcGraphChart $chart )
{
$this->chart = $chart;
}
/**
* Adds a dataset to the charts data
*
* @param string $name Name of dataset
* @param ezcGraphDataSet $dataSet
* @param mixed $values Values to create dataset with
* @throws ezcGraphTooManyDataSetExceptions
* If too many datasets are created
* @return ezcGraphDataSet
*/
protected function addDataSet( $name, ezcGraphDataSet $dataSet )
{
$this->data[$name] = $dataSet;
$this->data[$name]->label = $name;
$this->data[$name]->palette = $this->chart->palette;
$this->data[$name]->displayType = $this->chart->getDefaultDisplayType();
}
/**
* Returns if the given offset exists.
*
* This method is part of the ArrayAccess interface to allow access to the
* data of this object as if it was an array.
*
* @param string $key Identifier of dataset.
* @return bool True when the offset exists, otherwise false.
*/
public function offsetExists( $key )
{
return isset( $this->data[$key] );
}
/**
* Returns the element with the given offset.
*
* This method is part of the ArrayAccess interface to allow access to the
* data of this object as if it was an array.
*
* @param string $key Identifier of dataset.
* @return ezcGraphDataSet
*
* @throws ezcGraphNoSuchDataSetException
* If no dataset with identifier exists
*/
public function offsetGet( $key )
{
if ( !isset( $this->data[$key] ) )
{
throw new ezcGraphNoSuchDataSetException( $key );
}
return $this->data[$key];
}
/**
* Set the element with the given offset.
*
* This method is part of the ArrayAccess interface to allow access to the
* data of this object as if it was an array.
*
* @param string $key
* @param ezcGraphDataSet $value
* @return void
*
* @throws ezcBaseValueException
* If supplied value is not an ezcGraphDataSet
*/
public function offsetSet( $key, $value )
{
if ( !$value instanceof ezcGraphDataSet )
{
throw new ezcBaseValueException( $key, $value, 'ezcGraphDataSet' );
}
return $this->addDataSet( $key, $value );
}
/**
* Unset the element with the given offset.
*
* This method is part of the ArrayAccess interface to allow access to the
* data of this object as if it was an array.
*
* @param string $key
* @return void
*/
public function offsetUnset( $key )
{
if ( !isset( $this->data[$key] ) )
{
throw new ezcGraphNoSuchDataSetException( $key );
}
unset( $this->data[$key] );
}
/**
* Returns the currently selected dataset.
*
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return ezcGraphDataSet The currently selected dataset.
*/
public function current()
{
return current( $this->data );
}
/**
* Returns the next dataset and selects it or false on the last dataset.
*
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return mixed ezcGraphDataSet if the next dataset exists, or false.
*/
public function next()
{
return next( $this->data );
}
/**
* Returns the key of the currently selected dataset.
*
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return int The key of the currently selected dataset.
*/
public function key()
{
return key( $this->data );
}
/**
* Returns if the current dataset is valid.
*
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return bool If the current dataset is valid
*/
public function valid()
{
return ( current( $this->data ) !== false );
}
/**
* Selects the very first dataset and returns it.
* This method is part of the Iterator interface to allow access to the
* datasets of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return ezcGraphDataSet The very first dataset.
*/
public function rewind()
{
return reset( $this->data );
}
/**
* Returns the number of datasets in the row.
*
* This method is part of the Countable interface to allow the usage of
* PHP's count() function to check how many datasets exist.
*
* @return int Number of datasets.
*/
public function count()
{
return count( $this->data );
}
}
?>
@@ -0,0 +1,51 @@
<?php
/**
* File containing the abstract ezcGraphChartSingleDataContainer 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
*/
/**
* Container class for datasets, which ensures, that only one dataset is used.
* Needed for pie charts which can only display one dataset.
*
* @version 1.3
* @package Graph
*/
class ezcGraphChartSingleDataContainer extends ezcGraphChartDataContainer
{
/**
* Adds a dataset to the charts data
*
* @param string $name
* @param ezcGraphDataSet $dataSet
* @throws ezcGraphTooManyDataSetExceptions
* If too many datasets are created
* @return ezcGraphDataSet
*/
protected function addDataSet( $name, ezcGraphDataSet $dataSet )
{
if ( count( $this->data ) >= 1 &&
!isset( $this->data[$name] ) )
{
throw new ezcGraphTooManyDataSetsExceptions( $name );
}
else
{
parent::addDataSet( $name, $dataSet );
// Resette palette color counter
$this->chart->palette->resetColorCounter();
// Colorize each data element
foreach ( $this->data[$name] as $label => $value )
{
$this->data[$name]->color[$label] = $this->chart->palette->dataSetColor;
}
}
}
}
?>
@@ -0,0 +1,71 @@
<?php
/**
* File containing the ezcGraphArrayDataSet 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
*/
/**
* Dataset class which receives arrays and use them as a base for datasets.
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphArrayDataSet extends ezcGraphDataSet
{
/**
* Constructor
*
* @param array|Iterator $data Array or Iterator containing the data
* @return void
*/
public function __construct( $data )
{
$this->createFromArray( $data );
parent::__construct();
}
/**
* setData
*
* Can handle data provided through an array or iterator.
*
* @param array|Iterator $data
* @access public
* @return void
*/
protected function createFromArray( $data = array() )
{
if ( !is_array( $data ) &&
!( $data instanceof Traversable ) )
{
throw new ezcGraphInvalidArrayDataSourceException( $data );
}
$this->data = array();
foreach ( $data as $key => $value )
{
$this->data[$key] = $value;
}
if ( !count( $this->data ) )
{
throw new ezcGraphInvalidDataException( 'Data sets should contain some values.' );
}
}
/**
* Returns the number of elements in this dataset
*
* @return int
*/
public function count()
{
return count( $this->data );
}
}
?>
@@ -0,0 +1,359 @@
<?php
/**
* File containing the ezcGraphDataSetAverage 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
*/
/**
* Extension of basic dataset to represent averation.
* Algorithm: http://en.wikipedia.org/wiki/Least_squares
*
* @property int $polynomOrder
* Maximum order of polygon to interpolate from points
* @property int $resolution
* Resolution used to draw line in graph
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphDataSetAveragePolynom extends ezcGraphDataSet
{
/**
* Source dataset to base averation on.
*
* @var ezcGraphDataSet
*/
protected $source;
/**
* Calculated averation polynom
*
* @var ezcGraphPolynom
*/
protected $polynom = false;
/**
* Minimum key
*
* @var float
*/
protected $min = false;
/**
* Maximum key
*
* @var float
*/
protected $max = false;
/**
* Position of the data iterator. Depends on the configured resolution.
*
* @var int
*/
protected $position = 0;
/**
* Container to hold the properties
*
* @var array(string=>mixed)
*/
protected $properties;
/**
* Constructor
*
* @param ezcGraphDataSet $dataset Dataset to interpolate
* @param int $order Maximum order of interpolating polynom
* @return void
* @ignore
*/
public function __construct( ezcGraphDataSet $dataset, $order = 3 )
{
parent::__construct();
$this->properties['resolution'] = 100;
$this->properties['polynomOrder'] = (int) $order;
$this->source = $dataset;
}
/**
* 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
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName ) {
case 'polynomOrder':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int > 0' );
}
$this->properties['polynomOrder'] = (int) $propertyValue;
$this->polynom = false;
break;
case 'resolution':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int > 1' );
}
$this->properties['resolution'] = (int) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
/**
* Property get access.
* Simply returns a given option.
*
* @param string $propertyName 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
*/
public function __get( $propertyName )
{
if ( array_key_exists( $propertyName, $this->properties ) )
{
return $this->properties[$propertyName];
}
return parent::__get( $propertyName );
}
/**
* Build the polynom based on the given points.
*
* @return void
*/
protected function buildPolynom()
{
$points = array();
foreach ( $this->source as $key => $value )
{
if ( !is_numeric( $key ) )
{
throw new ezcGraphDatasetAverageInvalidKeysException();
}
if ( ( $this->min === false ) || ( $this->min > $key ) )
{
$this->min = (float) $key;
}
if ( ( $this->max === false ) || ( $this->max < $key ) )
{
$this->max = (float) $key;
}
$points[] = new ezcGraphCoordinate( (float) $key, (float) $value );
}
// Build transposed and normal Matrix out of coordiantes
$a = new ezcGraphMatrix( count( $points ), $this->polynomOrder + 1 );
$b = new ezcGraphMatrix( count( $points ), 1 );
for ( $i = 0; $i <= $this->properties['polynomOrder']; ++$i )
{
foreach ( $points as $nr => $point )
{
$a->set( $nr, $i, pow( $point->x, $i ) );
$b->set( $nr, 0, $point->y );
}
}
$at = clone $a;
$at->transpose();
$left = $at->multiply( $a );
$right = $at->multiply( $b );
$this->polynom = $left->solveNonlinearEquatation( $right );
}
/**
* Returns a polynom of the defined order witch matches the datapoints
* using the least squares algorithm.
*
* @return ezcGraphPolynom Polynom
*/
public function getPolynom()
{
if ( $this->polynom === false )
{
$this->buildPolynom();
}
return $this->polynom;
}
/**
* Get the x coordinate for the current position
*
* @param int $position Position
* @return float x coordinate
*/
protected function getKey()
{
$polynom = $this->getPolynom();
return $this->min +
( $this->max - $this->min ) / $this->resolution * $this->position;
}
/**
* Returns true if the given datapoint exists
* Allows isset() using ArrayAccess.
*
* @param string $key The key of the datapoint to get.
* @return bool Wether the key exists.
*/
public function offsetExists( $key )
{
$polynom = $this->getPolynom();
return ( ( $key >= $this->min ) && ( $key <= $this->max ) );
}
/**
* Returns the value for the given datapoint
* Get an datapoint value by ArrayAccess.
*
* @param string $key The key of the datapoint to get.
* @return float The datapoint value.
*/
public function offsetGet( $key )
{
$polynom = $this->getPolynom();
return $polynom->evaluate( $key );
}
/**
* Throws a ezcBasePropertyPermissionException because single datapoints
* cannot be set in average datasets.
*
* @param string $key The kex of a datapoint to set.
* @param float $value The value for the datapoint.
* @throws ezcBasePropertyPermissionException
* Always, because access is readonly.
* @return void
*/
public function offsetSet( $key, $value )
{
throw new ezcBasePropertyPermissionException( $key, ezcBasePropertyPermissionException::READ );
}
/**
* Returns the currently selected datapoint.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return string The currently selected datapoint.
*/
final public function current()
{
$polynom = $this->getPolynom();
return $polynom->evaluate( $this->getKey() );
}
/**
* Returns the next datapoint and selects it or false on the last datapoint.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return float datapoint if it exists, or false.
*/
final public function next()
{
if ( ++$this->position >= $this->resolution )
{
return false;
}
else
{
return $this->current();
}
}
/**
* Returns the key of the currently selected datapoint.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return string The key of the currently selected datapoint.
*/
final public function key()
{
return (string) $this->getKey();
}
/**
* Returns if the current datapoint is valid.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return bool If the current datapoint is valid
*/
final public function valid()
{
$polynom = $this->getPolynom();
if ( $this->min >= $this->max )
{
return false;
}
return ( ( $this->getKey() >= $this->min ) && ( $this->getKey() <= $this->max ) );
}
/**
* Selects the very first datapoint and returns it.
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return float The very first datapoint.
*/
final public function rewind()
{
$this->position = 0;
}
/**
* Returns the number of elements in this dataset
*
* @return int
*/
public function count()
{
return $this->resolution;
}
}
?>
@@ -0,0 +1,295 @@
<?php
/**
* File containing the abstract ezcGraphDataSet 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
* @access private
*/
/**
* Basic class to contain the charts data
*
* @property string $label
* Labels for datapoint and datapoint elements
* @property ezcGraphColor $color
* Colors for datapoint elements
* @property int $symbol
* Symbols for datapoint elements
* @property bool $highlight
* Status if datapoint element is hilighted
* @property int $displayType
* Display type of chart data
* @property string $url
* URL associated with datapoint
* @property ezcGraphChartElementAxis $xAxis
* Associate dataset with a different X axis then the default one
* @property ezcGraphChartElementAxis $yAxis
* Associate dataset with a different Y axis then the default one
*
* @version 1.3
* @package Graph
* @access private
*/
abstract class ezcGraphDataSet implements ArrayAccess, Iterator, Countable
{
/**
* Property array
*
* @var array
*/
protected $properties;
/**
* Array which contains the data of the datapoint
*
* @var array
*/
protected $data;
/**
* Current datapoint element
* needed for iteration over datapoint with ArrayAccess
*
* @var mixed
*/
protected $current;
/**
* Color palette used for datapoint colorization
*
* @var ezcGraphPalette
*/
protected $pallet;
/**
* Constructor
*
* @return void
* @ignore
*/
public function __construct()
{
$this->properties['label'] = new ezcGraphDataSetStringProperty( $this );
$this->properties['color'] = new ezcGraphDataSetColorProperty( $this );
$this->properties['symbol'] = new ezcGraphDataSetIntProperty( $this );
$this->properties['lineThickness'] = new ezcGraphDataSetIntProperty( $this );
$this->properties['highlight'] = new ezcGraphDataSetBooleanProperty( $this );
$this->properties['highlightValue'] = new ezcGraphDataSetStringProperty( $this );
$this->properties['displayType'] = new ezcGraphDataSetIntProperty( $this );
$this->properties['url'] = new ezcGraphDataSetStringProperty( $this );
$this->properties['xAxis'] = new ezcGraphDataSetAxisProperty( $this );
$this->properties['yAxis'] = new ezcGraphDataSetAxisProperty( $this );
$this->properties['highlight']->default = false;
}
/**
* 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 'hilight':
$propertyName = 'highlight';
case 'label':
case 'url':
case 'color':
case 'symbol':
case 'lineThickness':
case 'highlight':
case 'highlightValue':
case 'displayType':
case 'xAxis':
case 'yAxis':
$this->properties[$propertyName]->default = $propertyValue;
break;
case 'palette':
$this->palette = $propertyValue;
$this->color->default = $this->palette->dataSetColor;
$this->symbol->default = $this->palette->dataSetSymbol;
break;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
break;
}
}
/**
* Property get access.
* Simply returns a given option.
*
* @param string $propertyName 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
*/
public function __get( $propertyName )
{
if ( array_key_exists( $propertyName, $this->properties ) )
{
return $this->properties[$propertyName];
}
else
{
throw new ezcBasePropertyNotFoundException( $propertyName );
}
}
/**
* Returns true if the given datapoint exists
* Allows isset() using ArrayAccess.
*
* @param string $key The key of the datapoint to get.
* @return bool Wether the key exists.
*/
public function offsetExists( $key )
{
return isset( $this->data[$key] );
}
/**
* Returns the value for the given datapoint
* Get an datapoint value by ArrayAccess.
*
* @param string $key The key of the datapoint to get.
* @return float The datapoint value.
*/
public function offsetGet( $key )
{
return $this->data[$key];
}
/**
* Sets the value for a datapoint.
* Sets an datapoint using ArrayAccess.
*
* @param string $key The kex of a datapoint to set.
* @param float $value The value for the datapoint.
* @return void
*/
public function offsetSet( $key, $value )
{
$this->data[$key] = (float) $value;
}
/**
* 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.
*/
public function offsetUnset( $key )
{
unset( $this->data[$key] );
}
/**
* Returns the currently selected datapoint.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return string The currently selected datapoint.
*/
public function current()
{
$keys = array_keys( $this->data );
if ( !isset( $this->current ) )
{
$this->current = 0;
}
return $this->data[$keys[$this->current]];
}
/**
* Returns the next datapoint and selects it or false on the last datapoint.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return float datapoint if it exists, or false.
*/
public function next()
{
$keys = array_keys( $this->data );
if ( ++$this->current >= count( $keys ) )
{
return false;
}
else
{
return $this->data[$keys[$this->current]];
}
}
/**
* Returns the key of the currently selected datapoint.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return string The key of the currently selected datapoint.
*/
public function key()
{
$keys = array_keys( $this->data );
return $keys[$this->current];
}
/**
* Returns if the current datapoint is valid.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return bool If the current datapoint is valid
*/
public function valid()
{
$keys = array_keys( $this->data );
return isset( $keys[$this->current] );
}
/**
* Selects the very first datapoint and returns it.
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return float The very first datapoint.
*/
public function rewind()
{
$this->current = 0;
}
}
?>
@@ -0,0 +1,287 @@
<?php
/**
* File containing the ezcGraphNumericDataSet 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
*/
/**
* Dataset for numeric data.
*
* Uses user defined functions for numeric data creation
*
* @property float $start
* Start value for x axis values of function
* @property float $end
* End value for x axis values of function
* @property callback $callback
* Callback function which represents the mathmatical function to
* show
* @property int $resolution
* Steps used to draw line in graph
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphNumericDataSet extends ezcGraphDataSet
{
/**
* Position of the data iterator. Depends on the configured resolution.
*
* @var int
*/
protected $position = 0;
/**
* Container to hold the properties
*
* @var array(string=>mixed)
*/
protected $properties;
/**
* Constructor
*
* @param float $start Start value for x axis values of function
* @param float $end End value for x axis values of function
* @param callback $callback Callback function
* @return void
* @ignore
*/
public function __construct( $start = null, $end = null, $callback = null )
{
parent::__construct();
$this->properties['start'] = null;
$this->properties['end'] = null;
$this->properties['callback'] = null;
if ( $start !== null )
{
$this->start = $start;
}
if ( $end !== null )
{
$this->end = $end;
}
if ( $callback !== null )
{
$this->callback = $callback;
}
$this->properties['resolution'] = 100;
}
/**
* 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
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName ) {
case 'resolution':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int > 1' );
}
$this->properties['resolution'] = (int) $propertyValue;
break;
case 'start':
case 'end':
if ( !is_numeric( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float' );
}
$this->properties[$propertyName] = (float) $propertyValue;
break;
case 'callback':
if ( !is_callable( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'callback' );
}
$this->properties[$propertyName] = $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
/**
* Property get access.
* Simply returns a given option.
*
* @param string $propertyName 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
*/
public function __get( $propertyName )
{
if ( array_key_exists( $propertyName, $this->properties ) )
{
return $this->properties[$propertyName];
}
return parent::__get( $propertyName );
}
/**
* Get the x coordinate for the current position
*
* @param int $position Position
* @return float x coordinate
*/
protected function getKey()
{
return $this->start +
( $this->end - $this->start ) / $this->resolution * $this->position;
}
/**
* Returns true if the given datapoint exists
* Allows isset() using ArrayAccess.
*
* @param string $key The key of the datapoint to get.
* @return bool Wether the key exists.
*/
public function offsetExists( $key )
{
return ( ( $key >= $this->start ) && ( $key <= $this->end ) );
}
/**
* Returns the value for the given datapoint
* Get an datapoint value by ArrayAccess.
*
* @param string $key The key of the datapoint to get.
* @return float The datapoint value.
*/
public function offsetGet( $key )
{
return call_user_func( $this->callback, $key );
}
/**
* Throws a ezcBasePropertyPermissionException because single datapoints
* cannot be set in average datasets.
*
* @param string $key The kex of a datapoint to set.
* @param float $value The value for the datapoint.
* @throws ezcBasePropertyPermissionException
* Always, because access is readonly.
* @return void
*/
public function offsetSet( $key, $value )
{
throw new ezcBasePropertyPermissionException( $key, ezcBasePropertyPermissionException::READ );
}
/**
* Returns the currently selected datapoint.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return string The currently selected datapoint.
*/
final public function current()
{
return call_user_func( $this->callback, $this->getKey() );
}
/**
* Returns the next datapoint and selects it or false on the last datapoint.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return float datapoint if it exists, or false.
*/
final public function next()
{
if ( $this->start === $this->end )
{
throw new ezcGraphDatasetAverageInvalidKeysException();
}
if ( ++$this->position >= $this->resolution )
{
return false;
}
else
{
return $this->current();
}
}
/**
* Returns the key of the currently selected datapoint.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return string The key of the currently selected datapoint.
*/
final public function key()
{
return (string) $this->getKey();
}
/**
* Returns if the current datapoint is valid.
*
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return bool If the current datapoint is valid
*/
final public function valid()
{
return ( ( $this->getKey() >= $this->start ) && ( $this->getKey() <= $this->end ) );
}
/**
* Selects the very first datapoint and returns it.
* This method is part of the Iterator interface to allow access to the
* datapoints of this row by iterating over it like an array (e.g. using
* foreach).
*
* @return float The very first datapoint.
*/
final public function rewind()
{
$this->position = 0;
}
/**
* Returns the number of elements in this dataset
*
* @return int
*/
public function count()
{
return $this->resolution + 1;
}
}
?>
@@ -0,0 +1,56 @@
<?php
/**
* File containing the abstract ezcGraphDataSetIntProperty 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 axis properties of datasets
*
* @version 1.3
* @package Graph
*/
class ezcGraphDataSetAxisProperty extends ezcGraphDataSetProperty
{
/**
* Chacks if value is really an axis
*
* @param ezcGraphChartElementAxis $value
* @return void
*/
protected function checkValue( &$value )
{
if ( ! $value instanceof ezcGraphChartElementAxis )
{
throw new ezcBaseValueException( 'default', $value, 'ezcGraphChartElementAxis' );
}
return true;
}
/**
* Set an option.
*
* Sets an option using ArrayAccess.
*
* This is deaktivated, because you need not set a different axis for some
* data point.
*
* @param string $key The option to set.
* @param mixed $value The value for the option.
* @return void
*
* @throws ezcGraphInvalidAssignementException
* Always
*/
public function offsetSet( $key, $value )
{
throw new ezcGraphInvalidAssignementException();
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the abstract ezcGraphDataSetBooleanProperty 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 integer properties of datasets
*
* @version 1.3
* @package Graph
*/
class ezcGraphDataSetBooleanProperty extends ezcGraphDataSetProperty
{
/**
* Converts value to an {@link ezcGraphColor} object
*
* @param & $value
* @return void
*/
protected function checkValue( &$value )
{
$value = (bool) $value;
return true;
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the abstract ezcGraphDataSetColorProperty 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 color properties of datasets
*
* @version 1.3
* @package Graph
*/
class ezcGraphDataSetColorProperty extends ezcGraphDataSetProperty
{
/**
* Converts value to an {@link ezcGraphColor} object
*
* @param & $value
* @return void
*/
protected function checkValue( &$value )
{
$value = ezcGraphColor::create( $value );
return true;
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the abstract ezcGraphDataSetIntProperty 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 integer properties of datasets
*
* @version 1.3
* @package Graph
*/
class ezcGraphDataSetIntProperty extends ezcGraphDataSetProperty
{
/**
* Converts value to an {@link ezcGraphColor} object
*
* @param & $value
* @return void
*/
protected function checkValue( &$value )
{
$value = (int) $value;
return true;
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the abstract ezcGraphDataSetStringProperty 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 string properties of datasets
*
* @version 1.3
* @package Graph
*/
class ezcGraphDataSetStringProperty extends ezcGraphDataSetProperty
{
/**
* Converts value to an {@link ezcGraphColor} object
*
* @param & $value
* @return void
*/
protected function checkValue( &$value )
{
$value = (string) $value;
return true;
}
}
?>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,972 @@
<?php
/**
* File containing the ezcGraphFlashDriver 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
*/
/**
* Driver to create Flash4 (SWF) files as graph output. The options of this
* class are defined in The options of this class are defined in the option
* class {@link ezcGraphFlashDriverOptions} extending the basic
* {@link ezcGraphDriverOptions}.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->title = 'Access statistics';
* $graph->legend = false;
*
* $graph->driver = new ezcGraphFlashDriver();
* $graph->options->font = 'tutorial_font.fdb';
*
* $graph->driver->options->compression = 7;
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
*
* $graph->render( 400, 200, 'tutorial_driver_flash.swf' );
* </code>
*
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphFlashDriver extends ezcGraphDriver
{
/**
* Flash movie
*
* @var SWFMovie
*/
protected $movie;
/**
* Unique element id
*
* @var int
*/
protected $id = 1;
/**
* Array with strings to draw later
*
* @var array
*/
protected $strings = array();
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
ezcBase::checkDependency( 'Graph', ezcBase::DEP_PHP_EXTENSION, 'ming' );
$this->options = new ezcGraphFlashDriverOptions( $options );
}
/**
* Returns unique movie object as a parent canvas for all swf objects.
*
* @return SWFMovie
*/
public function getDocument()
{
if ( $this->movie === null )
{
ming_setscale( 1.0 );
$this->movie = new SWFMovie();
$this->movie->setDimension( $this->modifyCoordinate( $this->options->width ), $this->modifyCoordinate( $this->options->height ) );
$this->movie->setRate( 1 );
$this->movie->setBackground( 255, 255, 255 );
}
return $this->movie;
}
/**
* Set the fill and line properties for a SWWFShape according to the
* given parameters.
*
* @param SWFShape $shape
* @param ezcGraphColor $color
* @param mixed $thickness
* @param mixed $filled
* @return void
*/
protected function setShapeColor( SWFShape $shape, ezcGraphColor $color, $thickness, $filled )
{
if ( $filled )
{
switch ( true )
{
case ( $color instanceof ezcGraphLinearGradient ):
$gradient = new SWFGradient();
$gradient->addEntry(
0,
$color->startColor->red,
$color->startColor->green,
$color->startColor->blue,
255 - $color->startColor->alpha
);
$gradient->addEntry(
1,
$color->endColor->red,
$color->endColor->green,
$color->endColor->blue,
255 - $color->endColor->alpha
);
$fill = $shape->addFill( $gradient, SWFFILL_LINEAR_GRADIENT );
// Calculate desired length of gradient
$length = sqrt(
pow( $color->endPoint->x - $color->startPoint->x, 2 ) +
pow( $color->endPoint->y - $color->startPoint->y, 2 )
);
$fill->scaleTo( $this->modifyCoordinate( $length ) / 32768 , $this->modifyCoordinate( $length ) / 32768 );
$fill->rotateTo(
rad2deg( asin(
( $color->endPoint->x - $color->startPoint->x ) / $length
) + 180 )
);
$fill->moveTo(
$this->modifyCoordinate(
( $color->startPoint->x + $color->endPoint->x ) / 2
),
$this->modifyCoordinate(
( $color->startPoint->y + $color->endPoint->y ) / 2
)
);
$shape->setLeftFill( $fill );
break;
case ( $color instanceof ezcGraphRadialGradient ):
$gradient = new SWFGradient();
$gradient->addEntry(
0,
$color->startColor->red,
$color->startColor->green,
$color->startColor->blue,
255 - $color->startColor->alpha
);
$gradient->addEntry(
1,
$color->endColor->red,
$color->endColor->green,
$color->endColor->blue,
255 - $color->endColor->alpha
);
$fill = $shape->addFill( $gradient, SWFFILL_RADIAL_GRADIENT );
$fill->scaleTo( $this->modifyCoordinate( $color->width ) / 32768, $this->modifyCoordinate( $color->height ) / 32768 );
$fill->moveTo( $this->modifyCoordinate( $color->center->x ), $this->modifyCoordinate( $color->center->y ) );
$shape->setLeftFill( $fill );
break;
default:
$fill = $shape->addFill( $color->red, $color->green, $color->blue, 255 - $color->alpha );
$shape->setLeftFill( $fill );
break;
}
}
else
{
$shape->setLine( $this->modifyCoordinate( $thickness ), $color->red, $color->green, $color->blue, 255 - $color->alpha );
}
}
/**
* Modifies a coordinate value, as flash usally uses twips instead of
* pixels for a higher solution, as it only accepts integer values.
*
* @param float $pointValue
* @return float
*/
protected function modifyCoordinate( $pointValue )
{
return $pointValue * 10;
}
/**
* Demodifies a coordinate value, as flash usally uses twips instead of
* pixels for a higher solution, as it only accepts integer values.
*
* @param float $pointValue
* @return float
*/
protected function deModifyCoordinate( $pointValue )
{
return $pointValue / 10;
}
/**
* 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
*/
public function drawPolygon( array $points, ezcGraphColor $color, $filled = true, $thickness = 1. )
{
$movie = $this->getDocument();
if ( !$filled )
{
// The middle of the border is on the outline of a polygon in ming,
// fix that:
try
{
$points = $this->reducePolygonSize( $points, $thickness / 2 );
}
catch ( ezcGraphReducementFailedException $e )
{
return false;
}
}
$shape = new SWFShape();
$this->setShapeColor( $shape, $color, $thickness, $filled );
$lastPoint = end( $points );
$shape->movePenTo( $this->modifyCoordinate( $lastPoint->x ), $this->modifyCoordinate( $lastPoint->y ) );
foreach ( $points as $point )
{
$shape->drawLineTo( $this->modifyCoordinate( $point->x ), $this->modifyCoordinate( $point->y ) );
}
$object = $movie->add( $shape );
$object->setName( $id = 'ezcGraphPolygon_' . $this->id++ );
return $id;
}
/**
* 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
*/
public function drawLine( ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphColor $color, $thickness = 1. )
{
$movie = $this->getDocument();
$shape = new SWFShape();
$this->setShapeColor( $shape, $color, $thickness, false );
$shape->movePenTo( $this->modifyCoordinate( $start->x ), $this->modifyCoordinate( $start->y ) );
$shape->drawLineTo( $this->modifyCoordinate( $end->x ), $this->modifyCoordinate( $end->y ) );
$object = $movie->add( $shape );
$object->setName( $id = 'ezcGraphLine_' . $this->id++ );
return $id;
}
/**
* 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
*/
protected function getTextBoundings( $size, ezcGraphFontOptions $font, $text )
{
$t = new SWFText();
$t->setFont( new SWFFont( $font->path ) );
$t->setHeight( $size );
$boundings = new ezcGraphBoundings( 0, 0, $t->getWidth( $text ), $size );
return $boundings;
}
/**
* 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
*/
public function drawTextBox( $string, ezcGraphCoordinate $position, $width, $height, $align, ezcGraphRotation $rotation = null )
{
$padding = $this->options->font->padding + ( $this->options->font->border !== false ? $this->options->font->borderWidth : 0 );
$width = $this->modifyCoordinate( $width - $padding * 2 );
$height = $this->modifyCoordinate( $height - $padding * 2 );
$position = new ezcGraphCoordinate(
$this->modifyCoordinate( $position->x + $padding ),
$this->modifyCoordinate( $position->y + $padding )
);
// Try to get a font size for the text to fit into the box
$maxSize = $this->modifyCoordinate( min( $height, $this->options->font->maxFontSize ) );
$minSize = $this->modifyCoordinate( $this->options->font->minFontSize );
$result = false;
for ( $size = $maxSize; $size >= $minSize; )
{
$result = $this->testFitStringInTextBox( $string, $position, $width, $height, $size );
if ( is_array( $result ) )
{
break;
}
$size = $this->deModifyCoordinate( $size );
$size = $this->modifyCoordinate( floor( ( $newsize = $size * ( $result ) ) >= $size ? $size - 1 : $newsize ) );
}
if ( !is_array( $result ) )
{
if ( ( $height >= $this->options->font->minFontSize ) &&
( $this->options->autoShortenString ) )
{
$result = $this->tryFitShortenedString( $string, $position, $width, $height, $size = $this->modifyCoordinate( $this->options->font->minFontSize ) );
}
else
{
throw new ezcGraphFontRenderingException( $string, $this->options->font->minFontSize, $width, $height );
}
}
$this->options->font->minimalUsedFont = $this->deModifyCoordinate( $size );
$this->strings[] = array(
'text' => $result,
'id' => $id = 'ezcGraphTextBox_' . $this->id++,
'position' => $position,
'width' => $width,
'height' => $height,
'align' => $align,
'font' => $this->options->font,
'rotation' => $rotation,
);
return $id;
}
/**
* Render text depending of font type and available font extensions
*
* @param string $id
* @param string $text
* @param string $chars
* @param int $type
* @param string $path
* @param ezcGraphColor $color
* @param ezcGraphCoordinate $position
* @param float $size
* @param float $rotation
* @return void
*/
protected function renderText( $id, $text, $chars, $type, $path, ezcGraphColor $color, ezcGraphCoordinate $position, $size, $rotation = null )
{
$movie = $this->getDocument();
$tb = new SWFTextField( SWFTEXTFIELD_NOEDIT );
$tb->setFont( new SWFFont( $path ) );
$tb->setHeight( $size );
$tb->setColor( $color->red, $color->green, $color->blue, 255 - $color->alpha );
$tb->addString( $text );
$tb->addChars( $chars );
$object = $movie->add( $tb );
$object->rotate(
( $rotation !== null ? -$rotation->getRotation() : 0 )
);
$object->moveTo(
$position->x +
( $rotation === null ? 0 : $this->modifyCoordinate( $rotation->get( 0, 2 ) ) ),
$position->y -
$size * ( 1 + $this->options->lineSpacing ) +
( $rotation === null ? 0 : $this->modifyCoordinate( $rotation->get( 1, 2 ) ) )
);
$object->setName( $id );
}
/**
* Draw all collected texts
*
* The texts are collected and their maximum possible font size is
* calculated. This function finally draws the texts on the image, this
* delayed drawing has two reasons:
*
* 1) This way the text strings are always on top of the image, what
* results in better readable texts
* 2) The maximum possible font size can be calculated for a set of texts
* with the same font configuration. Strings belonging to one chart
* element normally have the same font configuration, so that all texts
* belonging to one element will have the same font size.
*
* @access protected
* @return void
*/
protected function drawAllTexts()
{
// Iterate over all strings to collect used chars per font
$chars = array();
foreach ( $this->strings as $text )
{
$completeString = '';
foreach ( $text['text'] as $line )
{
$completeString .= implode( ' ', $line );
}
// Collect chars for each font
if ( !isset( $chars[$text['font']->path] ) )
{
$chars[$text['font']->path] = $completeString;
}
else
{
$chars[$text['font']->path] .= $completeString;
}
}
foreach ( $this->strings as $text )
{
$size = $this->modifyCoordinate( $text['font']->minimalUsedFont );
$completeHeight = count( $text['text'] ) * $size + ( count( $text['text'] ) - 1 ) * $this->options->lineSpacing;
// Calculate y offset for vertical alignement
switch ( true )
{
case ( $text['align'] & ezcGraph::BOTTOM ):
$yOffset = $text['height'] - $completeHeight;
break;
case ( $text['align'] & ezcGraph::MIDDLE ):
$yOffset = ( $text['height'] - $completeHeight ) / 2;
break;
case ( $text['align'] & ezcGraph::TOP ):
default:
$yOffset = 0;
break;
}
$padding = $text['font']->padding + $text['font']->borderWidth / 2;
if ( $this->options->font->minimizeBorder === true )
{
// Calculate maximum width of text rows
$width = false;
foreach ( $text['text'] as $line )
{
$string = implode( ' ', $line );
$boundings = $this->getTextBoundings( $size, $text['font'], $string );
if ( ( $width === false) || ( $boundings->width > $width ) )
{
$width = $boundings->width;
}
}
switch ( true )
{
case ( $text['align'] & ezcGraph::LEFT ):
$xOffset = 0;
break;
case ( $text['align'] & ezcGraph::CENTER ):
$xOffset = ( $text['width'] - $width ) / 2;
break;
case ( $text['align'] & ezcGraph::RIGHT ):
$xOffset = $text['width'] - $width;
break;
}
$borderPolygonArray = array(
new ezcGraphCoordinate(
$this->deModifyCoordinate( $text['position']->x - $padding + $xOffset ),
$this->deModifyCoordinate( $text['position']->y - $padding + $yOffset )
),
new ezcGraphCoordinate(
$this->deModifyCoordinate( $text['position']->x + $padding * 2 + $xOffset + $width ),
$this->deModifyCoordinate( $text['position']->y - $padding + $yOffset )
),
new ezcGraphCoordinate(
$this->deModifyCoordinate( $text['position']->x + $padding * 2 + $xOffset + $width ),
$this->deModifyCoordinate( $text['position']->y + $padding * 2 + $yOffset + $completeHeight )
),
new ezcGraphCoordinate(
$this->deModifyCoordinate( $text['position']->x - $padding + $xOffset ),
$this->deModifyCoordinate( $text['position']->y + $padding * 2 + $yOffset + $completeHeight )
),
);
}
else
{
$borderPolygonArray = array(
new ezcGraphCoordinate(
$this->deModifyCoordinate( $text['position']->x - $padding ),
$this->deModifyCoordinate( $text['position']->y - $padding )
),
new ezcGraphCoordinate(
$this->deModifyCoordinate( $text['position']->x + $padding * 2 + $text['width'] ),
$this->deModifyCoordinate( $text['position']->y - $padding )
),
new ezcGraphCoordinate(
$this->deModifyCoordinate( $text['position']->x + $padding * 2 + $text['width'] ),
$this->deModifyCoordinate( $text['position']->y + $padding * 2 + $text['height'] )
),
new ezcGraphCoordinate(
$this->deModifyCoordinate( $text['position']->x - $padding ),
$this->deModifyCoordinate( $text['position']->y + $padding * 2 + $text['height'] )
),
);
}
if ( $text['rotation'] !== null )
{
foreach ( $borderPolygonArray as $nr => $point )
{
$borderPolygonArray[$nr] = $text['rotation']->transformCoordinate( $point );
}
}
if ( $text['font']->background !== false )
{
$this->drawPolygon(
$borderPolygonArray,
$text['font']->background,
true
);
}
if ( $text['font']->border !== false )
{
$this->drawPolygon(
$borderPolygonArray,
$text['font']->border,
false,
$text['font']->borderWidth
);
}
// Render text with evaluated font size
$completeString = '';
foreach ( $text['text'] as $line )
{
$string = implode( ' ', $line );
$completeString .= $string;
$boundings = $this->getTextBoundings( $size, $text['font'], $string );
$text['position']->y += $size;
switch ( true )
{
case ( $text['align'] & ezcGraph::LEFT ):
$position = new ezcGraphCoordinate(
$text['position']->x,
$text['position']->y + $yOffset
);
break;
case ( $text['align'] & ezcGraph::RIGHT ):
$position = new ezcGraphCoordinate(
$text['position']->x + ( $text['width'] - $boundings->width ),
$text['position']->y + $yOffset
);
break;
case ( $text['align'] & ezcGraph::CENTER ):
$position = new ezcGraphCoordinate(
$text['position']->x + ( ( $text['width'] - $boundings->width ) / 2 ),
$text['position']->y + $yOffset
);
break;
}
// Optionally draw text shadow
if ( $text['font']->textShadow === true )
{
$this->renderText(
$text['id'],
$string,
$chars[$text['font']->path],
$text['font']->type,
$text['font']->path,
$text['font']->textShadowColor,
new ezcGraphCoordinate(
$position->x + $this->modifyCoordinate( $text['font']->textShadowOffset ),
$position->y + $this->modifyCoordinate( $text['font']->textShadowOffset )
),
$size,
$text['rotation']
);
}
// Finally draw text
$this->renderText(
$text['id'],
$string,
$chars[$text['font']->path],
$text['font']->type,
$text['font']->path,
$text['font']->color,
$position,
$size,
$text['rotation']
);
$text['position']->y += $size * $this->options->lineSpacing;
}
}
}
/**
* 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
*/
public function drawCircleSector( ezcGraphCoordinate $center, $width, $height, $startAngle, $endAngle, ezcGraphColor $color, $filled = true )
{
if ( $startAngle > $endAngle )
{
$tmp = $startAngle;
$startAngle = $endAngle;
$endAngle = $tmp;
}
$movie = $this->getDocument();
$shape = new SWFShape();
$this->setShapeColor( $shape, $color, 1, $filled );
if ( !$filled )
{
try
{
$reduced = $this->reduceEllipseSize( $center, $width, $height, $startAngle, $endAngle, .5 );
}
catch ( ezcGraphReducementFailedException $e )
{
return false;
}
$startAngle = $reduced['startAngle'];
$endAngle = $reduced['endAngle'];
$width -= 1;
$height -= 1;
}
$shape->movePenTo( $this->modifyCoordinate( $center->x ), $this->modifyCoordinate( $center->y ) );
// @TODO: User SWFShape::curveTo
for(
$angle = $startAngle;
$angle <= $endAngle;
$angle = min( $angle + $this->options->circleResolution, $endAngle ) )
{
$shape->drawLineTo(
$this->modifyCoordinate( $center->x + cos( deg2rad( $angle ) ) * $width / 2 ),
$this->modifyCoordinate( $center->y + sin( deg2rad( $angle ) ) * $height / 2 )
);
if ( $angle === $endAngle )
{
break;
}
}
$shape->drawLineTo(
$this->modifyCoordinate( $center->x ),
$this->modifyCoordinate( $center->y )
);
$object = $movie->add( $shape );
$object->setName( $id = 'ezcGraphCircleSector_' . $this->id++ );
return $id;
}
/**
* Draws a circular arc consisting of several minor steps on the bounding
* lines.
*
* @param ezcGraphCoordinate $center
* @param mixed $width
* @param mixed $height
* @param mixed $size
* @param mixed $startAngle
* @param mixed $endAngle
* @param ezcGraphColor $color
* @param bool $filled
* @return string Element id
*/
protected function simulateCircularArc( ezcGraphCoordinate $center, $width, $height, $size, $startAngle, $endAngle, ezcGraphColor $color, $filled )
{
$movie = $this->getDocument();
$id = 'ezcGraphCircularArc_' . $this->id++;
for (
$tmpAngle = min( ceil ( $startAngle / 180 ) * 180, $endAngle );
$tmpAngle <= $endAngle;
$tmpAngle = min( ceil ( $startAngle / 180 + 1 ) * 180, $endAngle ) )
{
$shape = new SWFShape();
$this->setShapeColor( $shape, $color, 1, $filled );
$shape->movePenTo(
$this->modifyCoordinate( $center->x + cos( deg2rad( $startAngle ) ) * $width / 2 ),
$this->modifyCoordinate( $center->y + sin( deg2rad( $startAngle ) ) * $height / 2 )
);
// @TODO: Use SWFShape::curveTo
for(
$angle = $startAngle;
$angle <= $tmpAngle;
$angle = min( $angle + $this->options->circleResolution, $tmpAngle ) )
{
$shape->drawLineTo(
$this->modifyCoordinate( $center->x + cos( deg2rad( $angle ) ) * $width / 2 ),
$this->modifyCoordinate( $center->y + sin( deg2rad( $angle ) ) * $height / 2 + $size )
);
if ( $angle === $tmpAngle )
{
break;
}
}
for(
$angle = $tmpAngle;
$angle >= $startAngle;
$angle = max( $angle - $this->options->circleResolution, $startAngle ) )
{
$shape->drawLineTo(
$this->modifyCoordinate( $center->x + cos( deg2rad( $angle ) ) * $width / 2 ),
$this->modifyCoordinate( $center->y + sin( deg2rad( $angle ) ) * $height / 2 )
);
if ( $angle === $startAngle )
{
break;
}
}
$object = $movie->add( $shape );
$object->setName( $id );
$startAngle = $tmpAngle;
if ( $tmpAngle === $endAngle )
{
break;
}
}
return $id;
}
/**
* 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
* @return void
*/
public function drawCircularArc( ezcGraphCoordinate $center, $width, $height, $size, $startAngle, $endAngle, ezcGraphColor $color, $filled = true )
{
if ( $startAngle > $endAngle )
{
$tmp = $startAngle;
$startAngle = $endAngle;
$endAngle = $tmp;
}
$id = $this->simulateCircularArc( $center, $width, $height, $size, $startAngle, $endAngle, $color, $filled );
if ( ( $this->options->shadeCircularArc !== false ) &&
$filled )
{
$gradient = new ezcGraphLinearGradient(
new ezcGraphCoordinate(
$center->x - $width,
$center->y
),
new ezcGraphCoordinate(
$center->x + $width,
$center->y
),
ezcGraphColor::fromHex( '#FFFFFF' )->transparent( $this->options->shadeCircularArc * 1.5 ),
ezcGraphColor::fromHex( '#000000' )->transparent( $this->options->shadeCircularArc * 1.5 )
);
$this->simulateCircularArc( $center, $width, $height, $size, $startAngle, $endAngle, $gradient, $filled );
}
return $id;
}
/**
* 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
*/
public function drawCircle( ezcGraphCoordinate $center, $width, $height, ezcGraphColor $color, $filled = true )
{
$movie = $this->getDocument();
$shape = new SWFShape();
$this->setShapeColor( $shape, $color, 1, $filled );
// Reduce size
if ( !$filled )
{
$width -= 1;
$height -= 1;
}
$shape->movePenTo(
$this->modifyCoordinate( $center->x + $width / 2 ),
$this->modifyCoordinate( $center->y )
);
// @TODO: User SWFShape::curveTo
for ( $angle = $this->options->circleResolution; $angle < 360; $angle += $this->options->circleResolution )
{
$shape->drawLineTo(
$this->modifyCoordinate( $center->x + cos( deg2rad( $angle ) ) * $width / 2 ),
$this->modifyCoordinate( $center->y + sin( deg2rad( $angle ) ) * $height / 2 )
);
}
$shape->drawLineTo(
$this->modifyCoordinate( $center->x + $width / 2 ),
$this->modifyCoordinate( $center->y )
);
$object = $movie->add( $shape );
$object->setName( $id = 'ezcGraphCircle_' . $this->id++ );
return $id;
}
/**
* Draw an image
*
* The image will be inlined in the SVG document using data URL scheme. For
* this the mime type and base64 encoded file content will be merged to
* URL.
*
* @param mixed $file Image file
* @param ezcGraphCoordinate $position Top left position
* @param float $width Width of image in destination image
* @param float $height Height of image in destination image
* @return void
*/
public function drawImage( $file, ezcGraphCoordinate $position, $width, $height )
{
$movie = $this->getDocument();
$imageData = getimagesize( $file );
if ( ( $imageData[2] !== IMAGETYPE_JPEG ) && ( $imageData[2] !== IMAGETYPE_PNG ) )
{
throw new ezcGraphFlashBitmapTypeException( $imageData[2] );
}
// Try to create a new SWFBitmap object from provided file
$bitmap = new SWFBitmap( fopen( $file, 'rb' ) );
// Add the image to the movie
$object = $this->movie->add( $bitmap );
// Image size is calculated on the base of a tick size of 20, so
// that we need to transform this, to our tick size.
$factor = $this->modifyCoordinate( 1 ) / 20;
$object->scale( $factor, $factor );
// Scale by ratio of requested and original image size
$object->scale(
$width / $imageData[0],
$height / $imageData[1]
);
// Move object to the right position
$object->moveTo(
$this->modifyCoordinate( $position->x ),
$this->modifyCoordinate( $position->y )
);
// Create, set and return unique ID
$object->setName( $id = 'ezcGraphImage_'. $this->id++ );
return $id;
}
/**
* Return mime type for current image format
*
* @return string
*/
public function getMimeType()
{
return 'application/x-shockwave-flash';
}
/**
* Finally save image
*
* @param string $file Destination filename
* @return void
*/
public function render( $file )
{
$this->drawAllTexts();
$movie = $this->getDocument();
$movie->save( $file, $this->options->compression );
}
/**
* Get resource of rendered result
*
* Return the resource of the rendered result. You should not use this
* method before you called either renderToOutput() or render(), as the
* image may not be completely rendered until then.
*
* @return SWFMovie
*/
public function getResource()
{
return $this->movie;
}
}
?>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,299 @@
<?php
/**
* File containing the ezcGraphSVGDriver class
*
* @package Graph
* @version 1.3
* @copyright Copyright ( C ) 2005-2008 eZ systems as. All rights reserved.
* @author Freddie Witherden
* @license http://ez.no/licenses/new_bsd New BSD License
*/
/**
* Helper class, offering requrired calculation basics and font metrics to use
* SVG fonts with the SVG driver.
*
* You may convert any ttf font into a SVG font using the `ttf2svg` bianry from
* the batik package. Depending on the distribution it may only be available as
* `batik-ttf2svg-<version>`.
*
* Usage:
* <code>
* $font = new ezcGraphSvgFont();
* var_dump(
* $font->calculateStringWidth( '../tests/data/font.svg', 'Just a test string.' ),
* $font->calculateStringWidth( '../tests/data/font2.svg', 'Just a test string.' )
* );
* </code>
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphSvgFont
{
/**
* Units per EM
*
* @var float
*/
protected $unitsPerEm;
/**
* Used glyphs
*
* @var array
*/
protected $usedGlyphs = array();
/**
* Cache for glyph size to save XPath lookups.
*
* @var array
*/
protected $glyphCache = array();
/**
* Used kernings
*
* @var array
*/
protected $usedKerns = array();
/**
* Path to font
*
* @var string
*/
protected $fonts = array();
/**
* Initialize SVG font
*
* Loads the SVG font $filename. This should be the path to the file
* generated by ttf2svg.
*
* Returns the (normlized) name of the initilized font.
*
* @param string $fontPath
* @return string
*/
protected function initializeFont( $fontPath )
{
$fontPath = realpath( $fontPath );
if ( isset( $this->fonts[$fontPath] ) )
{
return $fontPath;
}
// Check for existance of font file
if ( !is_file( $fontPath ) || !is_readable( $fontPath ) )
{
throw new ezcBaseFileNotFoundException( $fontPath );
}
$this->fonts[$fontPath] = simplexml_load_file( $fontPath )->defs->font;
// SimpleXML requires us to register a namespace for XPath to work
$this->fonts[$fontPath]->registerXPathNamespace( 'svg', 'http://www.w3.org/2000/svg' );
// Extract the number of units per Em
$this->unitsPerEm[$fontPath] = (int) $this->fonts[$fontPath]->{'font-face'}['units-per-em'];
return $fontPath;
}
/**
* Get name of font
*
* Get the name of the given font, by extracting its font family from the
* SVG font file.
*
* @param string $fontPath
* @return string
*/
public static function getFontName( $fontPath )
{
$font = simplexml_load_file( $fontPath )->defs->font;
// SimpleXML requires us to register a namespace for XPath to work
$font->registerXPathNamespace( 'svg', 'http://www.w3.org/2000/svg' );
// Extract the font family name
return (string) $font->{'font-face'}['font-family'];
}
/**
* XPath has no standard means of escaping ' and ", with the only solution
* being to delimit your string with the opposite type of quote. ( And if
* your string contains both concat( ) it ).
*
* This method will correctly delimit $char with the appropriate quote type
* so that it can be used in an XPath expression.
*
* @param string $char
* @return string
*/
protected static function xpathEscape( $char )
{
return "'" . str_replace(
array( '\'', '\\' ),
array( '\\\'', '\\\\' ),
$char ) . "'";
}
/**
* Returns the <glyph> associated with $char.
*
* @param string $fontPath
* @param string $char
* @return float
*/
protected function getGlyph( $fontPath, $char )
{
// Check if glyphwidth has already been calculated.
if ( isset( $this->glyphCache[$fontPath][$char] ) )
{
return $this->glyphCache[$fontPath][$char];
}
$matches = $this->fonts[$fontPath]->xpath(
$query = "glyph[@unicode=" . self::xpathEscape( $char ) . "]"
);
if ( count( $matches ) === 0 )
{
// Just ignore missing glyphs. The client will still render them
// using a default font. We try to estimate some width by using a
// common other character.
return $this->glyphCache[$fontPath][$char] =
( $char === 'o' ? false : $this->getGlyph( $fontPath, 'o' ) );
}
$glyph = $matches[0];
if ( !in_array( $glyph, $this->usedGlyphs ) )
{
$this->usedGlyphs[$fontPath][] = $glyph;
}
// There should only ever be one match
return $this->glyphCache[$fontPath][$char] = $glyph;
}
/**
* Returns the amount of kerning to apply for glyphs $g1 and $g2. If no
* valid kerning pair can be found 0 is returned.
*
* @param string $fontPath
* @param SimpleXMLElement $g1
* @param SimpleXMLElement $g2
* @return int
*/
public function getKerning( $fontPath, SimpleXMLElement $glyph1, SimpleXMLElement $glyph2 )
{
// Get the glyph names
$g1Name = self::xpathEscape( ( string ) $glyph1['glyph-name'] );
$g2Name = self::xpathEscape( ( string ) $glyph2['glyph-name'] );
// Get the unicode character names
$g1Uni = self::xpathEscape( ( string ) $glyph1['unicode'] );
$g2Uni = self::xpathEscape( ( string ) $glyph2['unicode'] );
// Search for kerning pairs
$pair = $this->fonts[$fontPath]->xpath(
"svg:hkern[( @g1=$g1Name and @g2=$g2Name )
or
( @u1=$g1Uni and @g2=$g2Uni )]"
);
// If we found anything return it
if ( count( $pair ) )
{
if ( !in_array( $pair[0], $this->usedKerns ) )
{
$this->usedKerns[$fontPath][] = $pair[0];
}
return ( int ) $pair[0]['k'];
}
else
{
return 0;
}
}
/**
* Calculates the width of $string in the current font in Em's.
*
* @param string $fontPath
* @param string $string
* @return float
*/
public function calculateStringWidth( $fontPath, $string )
{
// Ensure font is properly initilized
$fontPath = $this->initializeFont( $fontPath );
$strlen = strlen( $string );
$prevCharInfo = null;
$length = 0;
// @TODO: Add UTF-8 support here - iterating over the bytes does not
// really help.
for ( $i = 0; $i < $strlen; ++$i )
{
// Find the font information for the character
$charInfo = $this->getGlyph( $fontPath, $string[$i] );
// Handle missing glyphs
if ( $charInfo === false )
{
$prevCharInfo = null;
$length .= .5 * $this->unitsPerEm[$fontPath];
continue;
}
// Add the horizontal advance for the character to the length
$length += (float) $charInfo['horiz-adv-x'];
// If we are not the first character, look for kerning pairs
if ( $prevCharInfo !== null )
{
// Apply kerning (if any)
$length -= $this->getKerning( $fontPath, $prevCharInfo, $charInfo );
}
$prevCharInfo = clone $charInfo;
}
// Divide by _unitsPerEm to get the length in Em
return (float) $length / $this->unitsPerEm[$fontPath];
}
/**
* Add font definitions to SVG document
*
* Add the SVG font definition paths for all used glyphs and kernings to
* the given SVG document.
*
* @param DOMDocument $document
* @return void
*/
public function addFontToDocument( DOMDocument $document )
{
$defs = $document->getElementsByTagName( 'defs' )->item( 0 );
$fontNr = 0;
foreach ( $this->fonts as $path => $definition )
{
// Just import complete font for now.
// @TODO: Only import used characters.
$font = dom_import_simplexml( $definition );
$font = $document->importNode( $font, true );
$font->setAttribute( 'id', 'Font' . ++$fontNr );
$defs->appendChild( $font );
}
}
}
?>
@@ -0,0 +1,242 @@
<?php
/**
* File containing the ezcGraphSVGDriver 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
* @access private
*/
/**
* Simple output driver for debuggin purposes. Just outputs shapes as text on
* CLI.
*
* @version 1.3
* @package Graph
* @access private
*/
class ezcGraphVerboseDriver extends ezcGraphDriver
{
/**
* Number of call on driver
*
* @var int
*/
protected $call = 0;
/**
* Constructor
*
* @param array $options
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->options = new ezcGraphSvgDriverOptions( $options );
echo "\n";
}
/**
* Draws a single polygon
*
* @param array $points
* @param ezcGraphColor $color
* @param bool $filled
* @param float $thickness
* @return void
*/
public function drawPolygon( array $points, ezcGraphColor $color, $filled = true, $thickness = 1. )
{
$pointString = '';
foreach ( $points as $point )
{
$pointString .= sprintf( "\t( %.2f, %.2f )\n", $point->x, $point->y );
}
printf( "% 4d: Draw %spolygon:\n%s",
$this->call++,
( $filled ? 'filled ' : '' ),
$pointString
);
}
/**
* Draws a single line
*
* @param ezcGraphCoordinate $start
* @param ezcGraphCoordinate $end
* @param ezcGraphColor $color
* @param float $thickness
* @return void
*/
public function drawLine( ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphColor $color, $thickness = 1. )
{
printf( "% 4d: Draw line from ( %.2f, %.2f ) to ( %.2f, %.2f ) with thickness %d.\n",
$this->call++,
$start->x,
$start->y,
$end->x,
$end->y,
$thickness
);
}
/**
* 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
*/
protected function getTextBoundings( $size, ezcGraphFontOptions $font, $text )
{
return null;
}
/**
* Wrties text in a box of desired size
*
* @param mixed $string
* @param ezcGraphCoordinate $position
* @param mixed $width
* @param mixed $height
* @param int $align
* @param ezcGraphRotation $rotation
* @return void
*/
public function drawTextBox( $string, ezcGraphCoordinate $position, $width, $height, $align, ezcGraphRotation $rotation = null )
{
printf( "% 4d: Draw text '%s' at ( %.2f, %.2f ) with dimensions ( %d, %d ) and alignement %d.\n",
$this->call++,
$string,
$position->x,
$position->y,
$width,
$height,
$align
);
}
/**
* Draws a sector of cirlce
*
* @param ezcGraphCoordinate $center
* @param mixed $width
* @param mixed $height
* @param mixed $startAngle
* @param mixed $endAngle
* @param ezcGraphColor $color
* @param bool $filled
* @return void
*/
public function drawCircleSector( ezcGraphCoordinate $center, $width, $height, $startAngle, $endAngle, ezcGraphColor $color, $filled = true )
{
printf( "% 4d: Draw %scicle sector at ( %.2f, %.2f ) with dimensions ( %d, %d ) from %.2f to %.2f.\n",
$this->call++,
( $filled ? 'filled ' : '' ),
$center->x,
$center->y,
$width,
$height,
$startAngle,
$endAngle
);
}
/**
* 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
* @return void
*/
public function drawCircularArc( ezcGraphCoordinate $center, $width, $height, $size, $startAngle, $endAngle, ezcGraphColor $color, $filled = true )
{
printf( "% 4d: Draw circular arc at ( %.2f, %.2f ) with dimensions ( %d, %d ) and size %.2f from %.2f to %.2f.\n",
$this->call++,
$center->x,
$center->y,
$width,
$height,
$size,
$startAngle,
$endAngle
);
}
/**
* Draws a circle
*
* @param ezcGraphCoordinate $center
* @param mixed $width
* @param mixed $height
* @param ezcGraphColor $color
* @param bool $filled
*
* @return void
*/
public function drawCircle( ezcGraphCoordinate $center, $width, $height, ezcGraphColor $color, $filled = true )
{
printf( "% 4d: Draw %scircle at ( %.2f, %.2f ) with dimensions ( %d, %d ).\n",
$this->call++,
( $filled ? 'filled ' : '' ),
$center->x,
$center->y,
$width,
$height
);
}
/**
* Draws a imagemap of desired size
*
* @param mixed $file
* @param ezcGraphCoordinate $position
* @param mixed $width
* @param mixed $height
* @return void
*/
public function drawImage( $file, ezcGraphCoordinate $position, $width, $height )
{
printf( "% 4d: Draw image '%s' at ( %.2f, %.2f ) with dimensions ( %d, %d ).\n",
$this->call++,
$file,
$position->x,
$position->y,
$width,
$height
);
}
/**
* Return mime type for current image format
*
* @return string
*/
public function getMimeType()
{
return 'text/plain';
}
/**
* Finally save image
*
* @param mixed $file
* @return void
*/
public function render ( $file )
{
printf( "Render image.\n" );
}
}
?>
@@ -0,0 +1,438 @@
<?php
/**
* File containing the abstract ezcGraphChartElementAxis 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
*/
/**
* Basic axis class
*
* @property float $nullPosition
* The position of the null value.
* @property float $axisSpace
* Percent of the chart space used to display axis labels and
* arrowheads instead of data values.
* @property ezcGraphColor $majorGrid
* Color of major majorGrid.
* @property ezcGraphColor $minorGrid
* Color of minor majorGrid.
* @property mixed $majorStep
* Labeled major steps displayed on the axis. @TODO: Should be moved
* to numeric axis.
* @property mixed $minorStep
* Non labeled minor steps on the axis. @TODO: Should be moved to
* numeric axis.
* @property string $formatString
* Formatstring to use for labeling of the axis.
* @property string $label
* Axis label
* @property int $labelSize
* Size of axis label
* @property int $labelMargin
* Distance between label an axis
* @property int $minArrowHeadSize
* Minimum Size used to draw arrow heads.
* @property int $maxArrowHeadSize
* Maximum Size used to draw arrow heads.
* @property ezcGraphAxisLabelRenderer $axisLabelRenderer
* AxisLabelRenderer used to render labels and grid on this axis.
* @property callback $labelCallback
* Callback function to format chart labels.
* Function will receive two parameters and should return a
* reformatted label.
* string function( label, step )
* @property float $chartPosition
* Position of the axis in the chart. Only useful for additional
* axis. The basic chart axis will be automatically positioned.
* @property-read bool $initialized
* Property indicating if some values were associated with axis, or a
* scaling has been set manually.
*
* @version 1.3
* @package Graph
*/
abstract class ezcGraphChartElementAxis extends ezcGraphChartElement
{
/**
* Axis label renderer class
*
* @var ezcGraphAxisLabelRenderer
*/
protected $axisLabelRenderer;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['nullPosition'] = false;
$this->properties['axisSpace'] = .1;
$this->properties['majorGrid'] = false;
$this->properties['minorGrid'] = false;
$this->properties['majorStep'] = null;
$this->properties['minorStep'] = null;
$this->properties['formatString'] = '%s';
$this->properties['label'] = false;
$this->properties['labelSize'] = 14;
$this->properties['labelMargin'] = 2;
$this->properties['minArrowHeadSize'] = 4;
$this->properties['maxArrowHeadSize'] = 8;
$this->properties['labelCallback'] = null;
$this->properties['chartPosition'] = null;
$this->properties['initialized'] = false;
parent::__construct( $options );
if ( !isset( $this->axisLabelRenderer ) )
{
$this->axisLabelRenderer = new ezcGraphAxisExactLabelRenderer();
}
}
/**
* Set colors and border fro this element
*
* @param ezcGraphPalette $palette Palette
* @return void
*/
public function setFromPalette( ezcGraphPalette $palette )
{
$this->border = $palette->axisColor;
$this->padding = $palette->padding;
$this->margin = $palette->margin;
$this->majorGrid = $palette->majorGridColor;
$this->minorGrid = $palette->minorGridColor;
}
/**
* __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
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'nullPosition':
$this->properties['nullPosition'] = (float) $propertyValue;
break;
case 'axisSpace':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['axisSpace'] = (float) $propertyValue;
break;
case 'majorGrid':
$this->properties['majorGrid'] = ezcGraphColor::create( $propertyValue );
break;
case 'minorGrid':
$this->properties['minorGrid'] = ezcGraphColor::create( $propertyValue );
break;
case 'majorStep':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['majorStep'] = (float) $propertyValue;
break;
case 'minorStep':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['minorStep'] = (float) $propertyValue;
break;
case 'formatString':
$this->properties['formatString'] = (string) $propertyValue;
break;
case 'label':
$this->properties['label'] = (string) $propertyValue;
break;
case 'labelSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 6 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 6' );
}
$this->properties['labelSize'] = (int) $propertyValue;
break;
case 'labelMargin':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['labelMargin'] = (int) $propertyValue;
break;
case 'maxArrowHeadSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['maxArrowHeadSize'] = (int) $propertyValue;
break;
case 'minArrowHeadSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['minArrowHeadSize'] = (int) $propertyValue;
break;
case 'axisLabelRenderer':
if ( $propertyValue instanceof ezcGraphAxisLabelRenderer )
{
$this->axisLabelRenderer = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphAxisLabelRenderer' );
}
break;
case 'labelCallback':
if ( is_callable( $propertyValue ) )
{
$this->properties['labelCallback'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'callback function' );
}
break;
case 'chartPosition':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['chartPosition'] = (float) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
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 'axisLabelRenderer':
return $this->axisLabelRenderer;
default:
return parent::__get( $propertyName );
}
}
/**
* Get coordinate for a dedicated value on the chart
*
* @param float $value Value to determine position for
* @return float Position on chart
*/
abstract public function getCoordinate( $value );
/**
* Return count of minor steps
*
* @return integer Count of minor steps
*/
abstract public function getMinorStepCount();
/**
* Return count of major steps
*
* @return integer Count of major steps
*/
abstract public function getMajorStepCount();
/**
* Get label for a dedicated step on the axis
*
* @param integer $step Number of step
* @return string label
*/
abstract public function getLabel( $step );
/**
* Return array of steps on this axis
*
* @return array( ezcGraphAxisStep )
*/
public function getSteps()
{
$majorSteps = $this->getMajorStepCount();
$minorStepsPerMajorStepCount = ( $this->getMinorStepCount() / $majorSteps );
$majorStepSize = 1 / $majorSteps;
$minorStepSize = ( $minorStepsPerMajorStepCount > 0 ? $majorStepSize / $minorStepsPerMajorStepCount : 0 );
$steps = array();
for ( $major = 0; $major <= $majorSteps; ++$major )
{
$majorStep = new ezcGraphAxisStep(
$majorStepSize * $major,
$majorStepSize,
$this->getLabel( $major ),
array(),
$this->isZeroStep( $major ),
( $major === $majorSteps )
);
if ( ( $minorStepsPerMajorStepCount > 0 ) &&
( $major < $majorSteps ) )
{
// Do not add minor steps at major steps positions
for( $minor = 1; $minor < $minorStepsPerMajorStepCount; ++$minor )
{
$majorStep->childs[] = new ezcGraphAxisStep(
( $majorStepSize * $major ) + ( $minorStepSize * $minor ),
$minorStepSize
);
}
}
$steps[] = $majorStep;
}
return $steps;
}
/**
* Is zero step
*
* Returns true if the given step is the one on the initial axis position
*
* @param int $step Number of step
* @return bool Status If given step is initial axis position
*/
abstract public function isZeroStep( $step );
/**
* Add data for this axis
*
* @param array $values
* @return void
*/
abstract public function addData( array $values );
/**
* Calculate axis bounding values on base of the assigned values
*
* @abstract
* @access public
* @return void
*/
abstract public function calculateAxisBoundings();
/**
* Render the axis
*
* @param ezcGraphRenderer $renderer Renderer
* @param ezcGraphBoundings $boundings Boundings for the axis
* @return ezcGraphBoundings Remaining boundings
*/
public function render( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings )
{
switch ( $this->position )
{
case ezcGraph::TOP:
$start = new ezcGraphCoordinate(
( $boundings->x1 - $boundings->x0 ) * $this->axisSpace +
$this->nullPosition * ( $boundings->x1 - $boundings->x0 ) * ( 1 - 2 * $this->axisSpace ),
0
);
$end = new ezcGraphCoordinate(
( $boundings->x1 - $boundings->x0 ) * $this->axisSpace +
$this->nullPosition * ( $boundings->x1 - $boundings->x0 ) * ( 1 - 2 * $this->axisSpace ),
$boundings->y1 - $boundings->y0
);
break;
case ezcGraph::BOTTOM:
$start = new ezcGraphCoordinate(
( $boundings->x1 - $boundings->x0 ) * $this->axisSpace +
$this->nullPosition * ( $boundings->x1 - $boundings->x0 ) * ( 1 - 2 * $this->axisSpace ),
$boundings->y1 - $boundings->y0
);
$end = new ezcGraphCoordinate(
( $boundings->x1 - $boundings->x0 ) * $this->axisSpace +
$this->nullPosition * ( $boundings->x1 - $boundings->x0 ) * ( 1 - 2 * $this->axisSpace ),
0
);
break;
case ezcGraph::LEFT:
$start = new ezcGraphCoordinate(
0,
( $boundings->y1 - $boundings->y0 ) * $this->axisSpace +
$this->nullPosition * ( $boundings->y1 - $boundings->y0 ) * ( 1 - 2 * $this->axisSpace )
);
$end = new ezcGraphCoordinate(
$boundings->x1 - $boundings->x0,
( $boundings->y1 - $boundings->y0 ) * $this->axisSpace +
$this->nullPosition * ( $boundings->y1 - $boundings->y0 ) * ( 1 - 2 * $this->axisSpace )
);
break;
case ezcGraph::RIGHT:
$start = new ezcGraphCoordinate(
$boundings->x1 - $boundings->x0,
( $boundings->y1 - $boundings->y0 ) * $this->axisSpace +
$this->nullPosition * ( $boundings->y1 - $boundings->y0 ) * ( 1 - 2 * $this->axisSpace )
);
$end = new ezcGraphCoordinate(
0,
( $boundings->y1 - $boundings->y0 ) * $this->axisSpace +
$this->nullPosition * ( $boundings->y1 - $boundings->y0 ) * ( 1 - 2 * $this->axisSpace )
);
break;
}
$renderer->drawAxis(
$boundings,
$start,
$end,
$this,
$this->axisLabelRenderer
);
return $boundings;
}
}
?>
@@ -0,0 +1,202 @@
<?php
/**
* File containing the ezcGraphChartElementBackground 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
*/
/**
* Chart element representing the background. In addition to the standard
* background and border for chart elements it can draw an image on the chart
* background, and optionally repeat it. The position will be used for the
* repetition offset.
*
* <code>
* $chart->background->image = 'background.png';
*
* // Image will be repeated horizontal at the top of the background
* $chart->background->repeat = ezcGraph::HORIZONTAL;
* $chart->background->postion = ezcGraph::TOP;
*
* // Image will be placed once in the center
* $chart->background->repeat = ezcGraph::NO_REPEAT; // default;
* $chart->background->position = ezcGraph::CENTER | ezcGraph::MIDDLE;
*
* // Image will be repeated all over
* $chart->background->repeat = ezcGraph::HORIZONTAL | ezcGraph::VERTICAL;
* // The position is not relevant here.
* </code>
*
* @property string $image
* Filename of the file to use for background
* @property int $repeat
* Defines how the background image gets repeated
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphChartElementBackground extends ezcGraphChartElement
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['image'] = false;
$this->properties['repeat'] = ezcGraph::NO_REPEAT;
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 'image':
// Check for existance of file
if ( !is_file( $propertyValue ) || !is_readable( $propertyValue ) )
{
throw new ezcBaseFileNotFoundException( $propertyValue );
}
// Check for beeing an image file
$data = getImageSize( $propertyValue );
if ( $data === false )
{
throw new ezcGraphInvalidImageFileException( $propertyValue );
}
// SWF files are useless..
if ( $data[2] === 4 )
{
throw new ezcGraphInvalidImageFileException( 'We cant use SWF files like <' . $propertyValue . '>.' );
}
$this->properties['image'] = $propertyValue;
break;
case 'repeat':
if ( ( $propertyValue >= 0 ) && ( $propertyValue <= 3 ) )
{
$this->properties['repeat'] = (int) $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= int <= 3' );
}
break;
case 'position':
// Overwrite parent position setter, to be able to use
// combination of positions like
// ezcGraph::TOP | ezcGraph::CENTER
if ( is_int( $propertyValue ) )
{
$this->properties['position'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'integer' );
}
break;
case 'color':
// Use color as an alias to set background color for background
$this->__set( 'background', $propertyValue );
break;
default:
return parent::__set( $propertyName, $propertyValue );
}
}
/**
* __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 'color':
// Use color as an alias to set background color for background
return $this->properties['background'];
default:
return parent::__get( $propertyName );
}
}
/**
* Set colors and border for this element
*
* Method is overwritten because we do not ant to apply the global padding
* and margin here.
*
* @param ezcGraphPalette $palette Palette
* @return void
*/
public function setFromPalette( ezcGraphPalette $palette )
{
$this->border = $palette->chartBorderColor;
$this->borderWidth = $palette->chartBorderWidth;
$this->background = $palette->chartBackground;
$this->padding = 0;
$this->margin = 0;
}
/**
* Render the background
*
* @param ezcGraphRenderer $renderer Renderer
* @param ezcGraphBoundings $boundings Boundings
* @return ezcGraphBoundings Remaining boundings
*/
public function render( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings )
{
$boundings = $renderer->drawBox(
$boundings,
$this->background,
$this->border,
$this->borderWidth,
$this->margin,
$this->padding
);
if ( $this->image === false )
{
return $boundings;
}
$renderer->drawBackgroundImage(
$boundings,
$this->image,
$this->position,
$this->repeat
);
return $boundings;
}
}
?>
@@ -0,0 +1,298 @@
<?php
/**
* File containing the abstract ezcGraphChartElementLegend 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 legend as a chart element
*
* @property float $portraitSize
* Size of a portrait style legend in percent of the size of the
* complete chart.
* @property float $landscapeSize
* Size of a landscape style legend in percent of the size of the
* complete chart.
* @property int $symbolSize
* Standard size of symbols and text in legends.
* @property float $minimumSymbolSize
* Scale symbol size up to to percent of complete legends size for
* very big legends.
* @property int $spacing
* Space between labels elements in pixel.
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphChartElementLegend extends ezcGraphChartElement
{
/**
* Contains data which should be shown in the legend
* array(
* array(
* 'label' => (string) 'Label of data element',
* 'color' => (ezcGraphColor) $color,
* 'symbol' => (integer) ezcGraph::DIAMOND,
* ),
* ...
* )
*
* @var array
*/
protected $labels;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['portraitSize'] = .2;
$this->properties['landscapeSize'] = .1;
$this->properties['symbolSize'] = 14;
$this->properties['padding'] = 1;
$this->properties['minimumSymbolSize'] = .05;
$this->properties['spacing'] = 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 'padding':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['padding'] = (int) $propertyValue;
break;
case 'symbolSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties['symbolSize'] = (int) $propertyValue;
break;
case 'landscapeSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= int <= 1' );
}
$this->properties['landscapeSize'] = (float) $propertyValue;
break;
case 'portraitSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= int <= 1' );
}
$this->properties['portraitSize'] = (float) $propertyValue;
break;
case 'minimumSymbolSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= int <= 1' );
}
$this->properties['minimumSymbolSize'] = (float) $propertyValue;
break;
case 'spacing':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties['spacing'] = (int) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
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 'labels':
return $this->labels;
default:
return parent::__get( $propertyName );
}
}
/**
* Generate legend from several datasets with on entry per dataset
*
* @param ezcGraphChartDataContainer $datasets
* @return void
*/
public function generateFromDataSets( ezcGraphChartDataContainer $datasets )
{
$this->labels = array();
foreach ( $datasets as $dataset )
{
$this->labels[] = array(
'label' => $dataset->label->default,
'url' => $dataset->url->default,
'color' => $dataset->color->default,
'symbol' => ( $dataset->symbol->default === null ?
ezcGraph::NO_SYMBOL :
$dataset->symbol->default ),
);
}
}
/**
* Generate legend from single dataset with on entry per data element
*
* @param ezcGraphDataSet $dataset
* @return void
*/
public function generateFromDataSet( ezcGraphDataSet $dataset )
{
$this->labels = array();
foreach ( $dataset as $label => $data )
{
$this->labels[] = array(
'label' => $label,
'url' => $dataset->url[$label],
'color' => $dataset->color[$label],
'symbol' => ( $dataset->symbol[$label] === null ?
ezcGraph::NO_SYMBOL :
$dataset->symbol[$label] ),
);
}
}
/**
* Calculated boundings needed for the legend.
*
* Uses the position and the configured horizontal or vertical size of a
* legend to calculate the boundings for the legend.
*
* @param ezcGraphBoundings $boundings Avalable boundings
* @return ezcGraphBoundings Remaining boundings
*/
protected function calculateBoundings( ezcGraphBoundings $boundings )
{
$this->properties['boundings'] = clone $boundings;
switch ( $this->position )
{
case ezcGraph::LEFT:
$size = ( $boundings->width ) * $this->portraitSize;
$boundings->x0 += $size;
$this->boundings->x1 = $boundings->x0;
break;
case ezcGraph::RIGHT:
$size = ( $boundings->width ) * $this->portraitSize;
$boundings->x1 -= $size;
$this->boundings->x0 = $boundings->x1;
break;
case ezcGraph::TOP:
$size = ( $boundings->height ) * $this->landscapeSize;
$boundings->y0 += $size;
$this->boundings->y1 = $boundings->y0;
break;
case ezcGraph::BOTTOM:
$size = ( $boundings->height ) * $this->landscapeSize;
$boundings->y1 -= $size;
$this->boundings->y0 = $boundings->y1;
break;
}
return $boundings;
}
/**
* Render a legend
*
* @param ezcGraphRenderer $renderer Renderer
* @param ezcGraphBoundings $boundings Boundings for the axis
* @return ezcGraphBoundings Remaining boundings
*/
public function render( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings )
{
$boundings = $this->calculateBoundings( $boundings );
if ( $this->position === ezcGraph::LEFT || $this->position === ezcGraph::RIGHT )
{
$type = ezcGraph::VERTICAL;
}
else
{
$type = ezcGraph::HORIZONTAL;
}
// Render standard elements
$this->properties['boundings'] = $renderer->drawBox(
$this->properties['boundings'],
$this->properties['background'],
$this->properties['border'],
$this->properties['borderWidth'],
$this->properties['margin'],
$this->properties['padding'],
$this->properties['title'],
$this->getTitleSize( $this->properties['boundings'], $type )
);
// Render legend
$renderer->drawLegend(
$this->boundings,
$this,
$type
);
return $boundings;
}
}
?>
@@ -0,0 +1,122 @@
<?php
/**
* File containing the ezcGraphChartElementText 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
*/
/**
* Chart element to display texts in a chart
*
* @property float $maxHeight
* Maximum percent of bounding used to display the text.
*
* @version 1.3
* @package Graph
* @mainclass
*/
class ezcGraphChartElementText extends ezcGraphChartElement
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['maxHeight'] = .1;
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
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'maxHeight':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['maxHeight'] = (float) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
/**
* Render the text
*
* @param ezcGraphRenderer $renderer Renderer
* @param ezcGraphBoundings $boundings Boundings for the axis
* @return ezcGraphBoundings Remaining boundings
*/
public function render( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings )
{
$height = (int) min(
round( $this->properties['maxHeight'] * ( $boundings->y1 - $boundings->y0 ) ),
$this->properties['font']->maxFontSize + $this->padding * 2 + $this->margin * 2
);
switch ( $this->properties['position'] )
{
case ezcGraph::TOP:
$textBoundings = new ezcGraphBoundings(
$boundings->x0,
$boundings->y0,
$boundings->x1,
$boundings->y0 + $height
);
$boundings->y0 += $height + $this->properties['margin'];
break;
case ezcGraph::BOTTOM:
$textBoundings = new ezcGraphBoundings(
$boundings->x0,
$boundings->y1 - $height,
$boundings->x1,
$boundings->y1
);
$boundings->y1 -= $height + $this->properties['margin'];
break;
}
$textBoundings = $renderer->drawBox(
$textBoundings,
$this->properties['background'],
$this->properties['border'],
$this->properties['borderWidth'],
$this->properties['margin'],
$this->properties['padding']
);
$renderer->drawText(
$textBoundings,
$this->properties['title'],
ezcGraph::CENTER | ezcGraph::MIDDLE
);
return $boundings;
}
}
?>
@@ -0,0 +1,33 @@
<?php
/**
* File containing the ezcGraphErrorParsingDateException 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
*/
/**
* Exception thrown when a date assigned to the
* {@link ezcGraphChartElementDateAxis} could not be parsed.
*
* @package Graph
* @version 1.3
*/
class ezcGraphErrorParsingDateException extends ezcGraphException
{
/**
* Constructor
*
* @param mixed $value
* @return void
* @ignore
*/
public function __construct( $value )
{
$type = gettype( $value );
parent::__construct( "Could not parse date '{$value}' of type '{$type}'." );
}
}
?>
@@ -0,0 +1,20 @@
<?php
/**
* Base exception for the Graph package.
*
* @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
*/
/**
* General exception container for the Graph component.
*
* @package Graph
* @version 1.3
*/
abstract class ezcGraphException extends ezcBaseException
{
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphFlashBitmapTypeException 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
*/
/**
* Flash can only read non interlaced bitmaps. This exception is thrown for
* all other image types.
*
* @package Graph
* @version 1.3
*/
class ezcGraphFlashBitmapTypeException extends ezcGraphException
{
/**
* Constructor
*
* @return void
* @ignore
*/
public function __construct()
{
parent::__construct( "Flash can only read JPEGs and PNGs." );
}
}
?>
@@ -0,0 +1,40 @@
<?php
/**
* File containing the ezcGraphFontRenderingException 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
*/
/**
* Exception thrown when it is not possible to render a string beacause of
* minimum font size in the desinated bounding box.
*
* @package Graph
* @version 1.3
*/
class ezcGraphFontRenderingException extends ezcGraphException
{
/**
* Constructor
*
* @param string $string
* @param float $size
* @param int $width
* @param int $height
* @return void
* @ignore
*/
public function __construct( $string, $size, $width, $height )
{
parent::__construct( "Could not fit string '{$string}' with font size '{$size}' in box '{$width} * {$height}'.
Possible solutions to solve this problem:
- Decrease the amount of steps on the axis.
- Increase the size of the chart.
- Decrease the minimum font size.
- Use a font which consumes less space for each character." );
}
}
?>
@@ -0,0 +1,32 @@
<?php
/**
* File containing the ezcGraphUnknownFontTypeException 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
*/
/**
* Exception thrown if font type is unknown or not supported.
*
* @package Graph
* @version 1.3
*/
class ezcGraphUnknownFontTypeException extends ezcGraphException
{
/**
* Constructor
*
* @param string $file
* @param string $extension
* @return void
* @ignore
*/
public function __construct( $file, $extension )
{
parent::__construct( "Unknown font type '{$extension}' of file '{$file}'." );
}
}
?>
@@ -0,0 +1,34 @@
<?php
/**
* File containing the ezcGraphToolsIncompatibleDriverException 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
*/
/**
* Exception thrown when trying to modify rendered images with incompatible
* graph tools.
*
* @package Graph
* @version 1.3
*/
class ezcGraphToolsIncompatibleDriverException extends ezcGraphException
{
/**
* Constructor
*
* @param mixed $driver
* @param string $accepted
* @return void
* @ignore
*/
public function __construct( $driver, $accepted )
{
$driverClass = get_class( $driver );
parent::__construct( "Incompatible driver used. Driver '{$driverClass}' is not an instance of '{$accepted}'." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphInvalidAssignementException 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
*/
/**
* Exception thrown, when trying a property cannot be set for a data point, but
* only for data sets.
*
* @package Graph
* @version 1.3
*/
class ezcGraphInvalidAssignementException extends ezcGraphException
{
/**
* Constructor
*
* @return void
* @ignore
*/
public function __construct()
{
parent::__construct( "This cannot be set on data points, but only for data sets." );
}
}
?>
@@ -0,0 +1,32 @@
<?php
/**
* File containing the ezcGraphInvalidDataException 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
*/
/**
* Exception thrown when invalid data is provided, which cannot be rendered
* for some reason.
*
* @package Graph
* @version 1.3
*/
class ezcGraphInvalidDataException extends ezcGraphException
{
/**
* Constructor
*
* @param string $message
* @return void
* @ignore
*/
public function __construct( $message )
{
parent::__construct( "You provided unusable data: '$message'." );
}
}
?>
@@ -0,0 +1,33 @@
<?php
/**
* File containing the ezcGraphInvalidArrayDataSourceException 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
*/
/**
* Exception thrown when an invalid data source is provided for an array
* data set.
*
* @package Graph
* @version 1.3
*/
class ezcGraphInvalidArrayDataSourceException extends ezcGraphException
{
/**
* Constructor
*
* @param mixed $value
* @return void
* @ignore
*/
public function __construct( $value )
{
$type = gettype( $value );
parent::__construct( "The array dataset can only use arrays and iterators, but you supplied '{$type}'." );
}
}
?>
@@ -0,0 +1,35 @@
<?php
/**
* File containing the ezcGraphMatrixInvalidDimensionsException 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
*/
/**
* Exception thrown when an operation is not possible because of incompatible
* matrix dimensions.
*
* @package Graph
* @version 1.3
*/
class ezcGraphMatrixInvalidDimensionsException extends ezcGraphException
{
/**
* Constructor
*
* @param int $rows
* @param int $columns
* @param int $dRows
* @param int $dColumns
* @return void
* @ignore
*/
public function __construct( $rows, $columns, $dRows, $dColumns )
{
parent::__construct( "Matrix '{$dRows}, {$dColumns}' is incompatible with matrix '{$rows}, {$columns}' for requested operation." );
}
}
?>
@@ -0,0 +1,46 @@
<?php
/**
* File containing the ezcGraphInvalidDisplayTypeException 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
*/
/**
* Exception thrown when an unsupported data type is set for the current chart.
*
* @package Graph
* @version 1.3
*/
class ezcGraphInvalidDisplayTypeException extends ezcGraphException
{
/**
* Constructor
*
* @param int $type
* @return void
* @ignore
*/
public function __construct( $type )
{
$chartTypeNames = array(
ezcGraph::PIE => 'Pie',
ezcGraph::LINE => 'Line',
ezcGraph::BAR => 'Bar',
);
if ( isset( $chartTypeNames[$type] ) )
{
$chartTypeName = $chartTypeNames[$type];
}
else
{
$chartTypeName = 'Unknown';
}
parent::__construct( "Invalid data set display type '$type' ('$chartTypeName') for current chart." );
}
}
?>
@@ -0,0 +1,32 @@
<?php
/**
* File containing the ezcGraphSvgDriverInvalidIdException 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
*/
/**
* Exception thrown when a id could not be found in a SVG document to insert
* elements in.
*
* @package Graph
* @version 1.3
*/
class ezcGraphSvgDriverInvalidIdException extends ezcGraphException
{
/**
* Constructor
*
* @param string $id
* @return void
* @ignore
*/
public function __construct( $id )
{
parent::__construct( "Could not find element with id '{$id}' in SVG document." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphInvalidImageFileException 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
*/
/**
* Exception thrown when a file can not be used as a image file.
*
* @package Graph
* @version 1.3
*/
class ezcGraphInvalidImageFileException extends ezcGraphException
{
/**
* Constructor
*
* @param string $image
* @return void
* @ignore
*/
public function __construct( $image )
{
parent::__construct( "File '{$image}' is not a valid image." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphDatasetAverageInvalidKeysException 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
*/
/**
* Exception thrown when a dataset with non numeric keys is used with average
* datasets.
*
* @package Graph
* @version 1.3
*/
class ezcGraphDatasetAverageInvalidKeysException extends ezcGraphException
{
/**
* Constructor
*
* @return void
* @ignore
*/
public function __construct()
{
parent::__construct( "You can not use non numeric keys with Average datasets." );
}
}
?>
@@ -0,0 +1,30 @@
<?php
/**
* File containing the ezcGraphNoDataException 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
*/
/**
* Exception shown, when trying to render a chart without assigning any data.
*
* @package Graph
* @version 1.3
*/
class ezcGraphNoDataException extends ezcGraphException
{
/**
* Constructor
*
* @return void
* @ignore
*/
public function __construct()
{
parent::__construct( "No data sets assigned to chart." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphNoSuchDataException 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
*/
/**
* Exception shown, when trying to access not existing data in datasets.
*
* @package Graph
* @version 1.3
*/
class ezcGraphNoSuchDataException extends ezcGraphException
{
/**
* Constructor
*
* @param string $name
* @return void
* @ignore
*/
public function __construct( $name )
{
parent::__construct( "No data with name '{$name}' found." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphNoSuchDataSetException 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
*/
/**
* Exception thrown when trying to access a non exising dataset.
*
* @package Graph
* @version 1.3
*/
class ezcGraphNoSuchDataSetException extends ezcGraphException
{
/**
* Constructor
*
* @param string $name
* @return void
* @ignore
*/
public function __construct( $name )
{
parent::__construct( "No dataset with identifier '{$name}' could be found." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphNoSuchElementException 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
*/
/**
* Exception thrown when trying to access a non existing chart element.
*
* @package Graph
* @version 1.3
*/
class ezcGraphNoSuchElementException extends ezcGraphException
{
/**
* Constructor
*
* @param string $name
* @return void
* @ignore
*/
public function __construct( $name )
{
parent::__construct( "No chart element with name '{$name}' found." );
}
}
?>
@@ -0,0 +1,32 @@
<?php
/**
* File containing the ezcGraphToolsNotRenderedException 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
*/
/**
* Exception thrown when a chart was not rendered yet, but the graph tool
* requires information only available in rendered charts.
*
* @package Graph
* @version 1.3
*/
class ezcGraphToolsNotRenderedException extends ezcGraphException
{
/**
* Constructor
*
* @param ezcGraphChart $chart
* @return void
* @ignore
*/
public function __construct( $chart )
{
parent::__construct( "Chart is not yet rendered." );
}
}
?>
@@ -0,0 +1,35 @@
<?php
/**
* File containing the ezcGraphMatrixOutOfBoundingsException 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
*/
/**
* Exception thrown when a requested matrix value is out of the boundings of
* the matrix.
*
* @package Graph
* @version 1.3
*/
class ezcGraphMatrixOutOfBoundingsException extends ezcGraphException
{
/**
* Constructor
*
* @param int $rows
* @param int $columns
* @param int $rPos
* @param int $cPos
* @return void
* @ignore
*/
public function __construct( $rows, $columns, $rPos, $cPos )
{
parent::__construct( "Position '{$rPos}, {$cPos}' is out of the matrix boundings '{$rows}, {$columns}'." );
}
}
?>
@@ -0,0 +1,32 @@
<?php
/**
* File containing the ezcGraphOutOfLogithmicalBoundingsException 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
*/
/**
* Exception thrown when data exceeds the values which are displayable on an
* logarithmical scaled axis.
*
* @package Graph
* @version 1.3
*/
class ezcGraphOutOfLogithmicalBoundingsException extends ezcGraphException
{
/**
* Constructor
*
* @param int $minimum
* @return void
* @ignore
*/
public function __construct( $minimum )
{
parent::__construct( "Value '$minimum' exceeds displayable values on a logarithmical scaled axis." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphReducementFailedException 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
*/
/**
* Exception thrown when a requested reducement of an ellipse or polygone
* failed because the shape was already too small.
*
* @package Graph
* @version 1.3
*/
class ezcGraphReducementFailedException extends ezcGraphException
{
/**
* Constructor
*
* @return void
* @ignore
*/
public function __construct()
{
parent::__construct( "Reducement of shape failed, because it was already too small." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphTooManyDataSetsExceptions 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
*/
/**
* Exception thrown when trying to insert too many data sets in a data set
* container.
*
* @package Graph
* @version 1.3
*/
class ezcGraphTooManyDataSetsExceptions extends ezcGraphException
{
/**
* Constructor
*
* @return void
* @ignore
*/
public function __construct()
{
parent::__construct( "You tried to insert to many datasets." );
}
}
?>
@@ -0,0 +1,32 @@
<?php
/**
* File containing the ezcGraphUnknownColorDefinitionException 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
*/
/**
* Exception thrown, when a given value could not be interpreted as a color by
* {@link ezcGraphColor}.
*
* @package Graph
* @version 1.3
*/
class ezcGraphUnknownColorDefinitionException extends ezcGraphException
{
/**
* Constructor
*
* @param mixed $definition
* @return void
* @ignore
*/
public function __construct( $definition )
{
parent::__construct( "Unknown color definition '{$definition}'." );
}
}
?>
@@ -0,0 +1,31 @@
<?php
/**
* File containing the ezcGraphUnregularStepsException 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
*/
/**
* Exception thrown when a bar chart shouls be rendered on an axis using
* unregular step sizes.
*
* @package Graph
* @version 1.3
*/
class ezcGraphUnregularStepsException extends ezcGraphException
{
/**
* Constructor
*
* @return void
* @ignore
*/
public function __construct()
{
parent::__construct( "Bar charts do not support axis with unregualr steps sizes." );
}
}
?>
@@ -0,0 +1,61 @@
<?php
/**
* File containing the ezcGraphGdDriverUnsupportedImageTypeException 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
*/
/**
* Exception thrown if the image type is not supported and therefore could not
* be used in the gd driver.
*
* @package Graph
* @version 1.3
*/
class ezcGraphGdDriverUnsupportedImageTypeException extends ezcGraphException
{
/**
* Constructor
*
* @param int $type
* @return void
* @ignore
*/
public function __construct( $type )
{
$typeName = array(
1 => 'GIF',
2 => 'Jpeg',
3 => 'PNG',
4 => 'SWF',
5 => 'PSD',
6 => 'BMP',
7 => 'TIFF (intel)',
8 => 'TIFF (motorola)',
9 => 'JPC',
10 => 'JP2',
11 => 'JPX',
12 => 'JB2',
13 => 'SWC',
14 => 'IFF',
15 => 'WBMP',
16 => 'XBM',
);
if ( isset( $typeName[$type] ) )
{
$type = $typeName[$type];
}
else
{
$type = 'Unknown';
}
parent::__construct( "Unsupported image format '{$type}'." );
}
}
?>
+134
View File
@@ -0,0 +1,134 @@
<?php
/**
* File containing the abstract ezcGraph 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
*/
/**
* Base options class for all eZ components.
*
* @version 1.3
* @package Graph
*/
class ezcGraph
{
/**
* No symbol, will fallback to a rect in the legend
*/
const NO_SYMBOL = 0;
/**
* Rhomb like looking symbol
*/
const DIAMOND = 1;
/**
* Filled circle
*/
const BULLET = 2;
/**
* Non filled circle
*/
const CIRCLE = 3;
/**
* Constant used for background repetition. No repeat.
*/
const NO_REPEAT = 0;
/**
* Constant used for background repetition. Repeat along the x axis. May be
* used as a bitmask together with ezcGraph::VERTICAL.
*/
const HORIZONTAL = 1;
/**
* Constant used for background repetition. Repeat along the y axis. May be
* used as a bitmask together with ezcGraph::HORIZONTAL.
*/
const VERTICAL = 2;
/**
* Constant used for positioning of elements. May be used as a bitmask
* together with other postioning constants.
* Element will be placed at the top of the current boundings.
*/
const TOP = 1;
/**
* Constant used for positioning of elements. May be used as a bitmask
* together with other postioning constants.
* Element will be placed at the bottom of the current boundings.
*/
const BOTTOM = 2;
/**
* Constant used for positioning of elements. May be used as a bitmask
* together with other postioning constants.
* Element will be placed at the left of the current boundings.
*/
const LEFT = 4;
/**
* Constant used for positioning of elements. May be used as a bitmask
* together with other postioning constants.
* Element will be placed at the right of the current boundings.
*/
const RIGHT = 8;
/**
* Constant used for positioning of elements. May be used as a bitmask
* together with other postioning constants.
* Element will be placed at the horizontalcenter of the current boundings.
*/
const CENTER = 16;
/**
* Constant used for positioning of elements. May be used as a bitmask
* together with other postioning constants.
* Element will be placed at the vertical middle of the current boundings.
*/
const MIDDLE = 32;
/**
* Display type for datasets. Pie may only be used with pie charts.
*/
const PIE = 1;
/**
* Display type for datasets. Bar and line charts may contain datasets of
* type ezcGraph::LINE.
*/
const LINE = 2;
/**
* Display type for datasets. Bar and line charts may contain datasets of
* type ezcGraph::BAR.
*/
const BAR = 3;
/**
* @TODO:
*/
const ODOMETER = 4;
/**
* Font type definition. Used for True Type fonts.
*/
const TTF_FONT = 1;
/**
* Font type definition. Used for Postscript Type 1 fonts.
*/
const PS_FONT = 2;
/**
* Font type definition. Used for Palm Format Fonts for Ming driver.
*/
const PALM_FONT = 3;
/**
* Font type definition. Used for SVG fonts vonverted by ttf2svg used in
* the SVG driver.
*/
const SVG_FONT = 4;
/**
* Identifier for keys in complex dataset arrays
*/
const KEY = 0;
/**
* Identifier for values in complex dataset arrays
*/
const VALUE = 1;
}
?>
@@ -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.
);
}
?>
@@ -0,0 +1,105 @@
<?php
/**
* File containing the ezcGraphBoundings 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
* @access private
*/
/**
* Provides a class representing boundings in a cartesian coordinate system.
*
* Currently only works with plane rectangular boundings, should be enhanced by
* rotated rectangular boundings.
*
* @version 1.3
* @package Graph
* @access private
*/
class ezcGraphBoundings
{
/**
* Top left x coordinate
*
* @var float
*/
public $x0 = 0;
/**
* Top left y coordinate
*
* @var float
*/
public $y0 = 0;
/**
* Bottom right x coordinate
*
* @var float
*/
public $x1 = false;
/**
* Bottom right y coordinate
*
* @var float
*/
public $y1 = false;
/**
* Constructor
*
* @param float $x0 Top left x coordinate
* @param float $y0 Top left y coordinate
* @param float $x1 Bottom right x coordinate
* @param float $y1 Bottom right y coordinate
* @return ezcGraphBoundings
*/
public function __construct( $x0 = 0., $y0 = 0., $x1 = null, $y1 = null )
{
$this->x0 = $x0;
$this->y0 = $y0;
$this->x1 = $x1;
$this->y1 = $y1;
// Switch values to ensure correct order
if ( $this->x0 > $this->x1 )
{
$tmp = $this->x0;
$this->x0 = $this->x1;
$this->x1 = $tmp;
}
if ( $this->y0 > $this->y1 )
{
$tmp = $this->y0;
$this->y0 = $this->y1;
$this->y1 = $tmp;
}
}
/**
* Getter for calculated values depending on the boundings.
* - 'width': Width of bounding recangle
* - 'height': Height of bounding recangle
*
* @param string $name Name of property to get
* @return mixed Calculated value
*/
public function __get( $name )
{
switch ( $name )
{
case 'width':
return $this->x1 - $this->x0;
case 'height':
return $this->y1 - $this->y0;
default:
throw new ezcBasePropertyNotFoundException( $name );
}
}
}
?>
@@ -0,0 +1,502 @@
<?php
/**
* File containing the abstract ezcGraphMatrix 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
* @access private
*/
/**
* Provides a genereic matrix class with basic math operations
*
* @version 1.3
* @package Graph
* @access private
*/
class ezcGraphMatrix
{
/**
* Count of matrix rows
*
* @var int
*/
protected $rows;
/**
* Count of matrix columns
*
* @var int
*/
protected $columns;
/**
* Array containing matrix values.
*
* // Matrix
* array(
* // Rows
* array(
* // Column values
* (float)
* )
* )
*
* @var array(array(float))
*/
protected $matrix;
/**
* Constructor
*
* Creates a matrix with given dimensions. Optionally accepts an array to
* define the initial matrix values. If no array is given an identity
* matrix is created.
*
* @param int $rows Number of rows
* @param int $columns Number of columns
* @param array $values Array with values
* @return void
*/
public function __construct( $rows = 3, $columns = 3, array $values = null )
{
$this->rows = max( 1, (int) $rows );
$this->columns = max( 1, (int) $columns );
if ( $values !== null )
{
$this->fromArray( $values );
}
else
{
$this->init();
}
}
/**
* Create matrix from array
*
* Use an array with float values to set matrix values.
*
* @param array $values Array with values
* @return ezcGraphMatrix Modified matrix
*/
public function fromArray( array $values )
{
for ( $i = 0; $i < $this->rows; ++$i )
{
for ( $j = 0; $j < $this->columns; ++$j )
{
$this->matrix[$i][$j] =
( isset( $values[$i][$j] )
? (float) $values[$i][$j]
: 0 );
}
}
return $this;
}
/**
* Init matrix
*
* Sets matrix to identity matrix.
*
* @return ezcGraphMatrix Modified matrix
*/
public function init()
{
for ( $i = 0; $i < $this->rows; ++$i )
{
for ( $j = 0; $j < $this->columns; ++$j )
{
$this->matrix[$i][$j] = ( $i === $j ? 1 : 0 );
}
}
return $this;
}
/**
* Returns number of rows
*
* @return int Number of rows
*/
public function rows()
{
return $this->rows;
}
/**
* Returns number of columns
*
* @return int Number of columns
*/
public function columns()
{
return $this->columns;
}
/**
* Get a single matrix value
*
* Returns the value of the matrix at the given position
*
* @param int $i Column
* @param int $j Row
* @return float Matrix value
*/
public function get( $i, $j )
{
if ( ( $i < 0 ) ||
( $i >= $this->rows ) ||
( $j < 0 ) ||
( $j >= $this->columns ) )
{
throw new ezcGraphMatrixOutOfBoundingsException( $this->rows, $this->columns, $i, $j );
}
return ( !isset( $this->matrix[$i][$j] ) ? .0 : $this->matrix[$i][$j] );
}
/**
* Set a single matrix value
*
* Sets the value of the matrix at the given position.
*
* @param int $i Column
* @param int $j Row
* @param float $value Value
* @return ezcGraphMatrix Updated matrix
*/
public function set( $i, $j, $value )
{
if ( ( $i < 0 ) ||
( $i >= $this->rows ) ||
( $j < 0 ) ||
( $j >= $this->columns ) )
{
throw new ezcGraphMatrixOutOfBoundingsException( $this->rows, $this->columns, $i, $j );
}
$this->matrix[$i][$j] = $value;
return $this;
}
/**
* Adds one matrix to the current one
*
* Calculate the sum of two matrices and returns the resulting matrix.
*
* @param ezcGraphMatrix $matrix Matrix to sum with
* @return ezcGraphMatrix Result matrix
*/
public function add( ezcGraphMatrix $matrix )
{
if ( ( $this->rows !== $matrix->rows() ) ||
( $this->columns !== $matrix->columns() ) )
{
throw new ezcGraphMatrixInvalidDimensionsException( $this->rows, $this->columns, $matrix->rows(), $matrix->columns() );
}
for ( $i = 0; $i < $this->rows; ++$i )
{
for ( $j = 0; $j < $this->columns; ++$j )
{
$this->matrix[$i][$j] += $matrix->get( $i, $j );
}
}
return $this;
}
/**
* Subtracts matrix from current one
*
* Calculate the diffenrence of two matices and returns the result matrix.
*
* @param ezcGraphMatrix $matrix subtrahend
* @return ezcGraphMatrix Result matrix
*/
public function diff( ezcGraphMatrix $matrix )
{
if ( ( $this->rows !== $matrix->rows() ) ||
( $this->columns !== $matrix->columns() ) )
{
throw new ezcGraphMatrixInvalidDimensionsException( $this->rows, $this->columns, $matrix->rows(), $matrix->columns() );
}
for ( $i = 0; $i < $this->rows; ++$i )
{
for ( $j = 0; $j < $this->columns; ++$j )
{
$this->matrix[$i][$j] -= $matrix->get( $i, $j );
}
}
return $this;
}
/**
* Scalar multiplication
*
* Multiplies matrix with the given scalar and returns the result matrix
*
* @param float $scalar Scalar
* @return ezcGraphMatrix Result matrix
*/
public function scalar( $scalar )
{
$scalar = (float) $scalar;
for ( $i = 0; $i < $this->rows; ++$i )
{
for ( $j = 0; $j < $this->columns; ++$j )
{
$this->matrix[$i][$j] *= $scalar;
}
}
}
/**
* Transpose matrix
*
* @return ezcGraphMatrix Transposed matrix
*/
public function transpose()
{
$matrix = clone $this;
$this->rows = $matrix->columns();
$this->columns = $matrix->rows();
$this->matrix = array();
for ( $i = 0; $i < $this->rows; ++$i )
{
for ( $j = 0; $j < $this->columns; ++$j )
{
$this->matrix[$i][$j] = $matrix->get( $j, $i );
}
}
return $this;
}
/**
* Multiplies two matrices
*
* Multiply current matrix with another matrix and returns the result
* matrix.
*
* @param ezcGraphMatrix $matrix Second factor
* @return ezcGraphMatrix Result matrix
*/
public function multiply( ezcGraphMatrix $matrix )
{
$mColumns = $matrix->columns();
if ( $this->columns !== ( $mRows = $matrix->rows() ) )
{
throw new ezcGraphMatrixInvalidDimensionsException( $this->columns, $this->rows, $mColumns, $mRows );
}
$result = new ezcGraphMatrix( $this->rows, $mColumns );
for ( $i = 0; $i < $this->rows; ++$i )
{
for ( $j = 0; $j < $mColumns; ++$j )
{
$sum = 0;
for ( $k = 0; $k < $mRows; ++$k ) {
$sum += $this->matrix[$i][$k] * $matrix->get( $k, $j );
}
$result->set( $i, $j, $sum );
}
}
return $result;
}
/**
* Solve nonlinear equatation
*
* Tries to solve equatation given by two matrices, with assumption, that:
* A * x = B
* where $this is A, and the paramenter B. x is cosnidered as a vector
* x = ( x^n, x^(n-1), ..., x^2, x, 1 )
*
* Will return a polynomial solution for x.
*
* See: http://en.wikipedia.org/wiki/Gauss-Newton_algorithm
*
* @param ezcGraphMatrix $matrix B
* @return ezcGraphPolygon Solution of equatation
*/
public function solveNonlinearEquatation( ezcGraphMatrix $matrix )
{
// Build complete equatation
$equatation = new ezcGraphMatrix( $this->rows, $columns = ( $this->columns + 1 ) );
for ( $i = 0; $i < $this->rows; ++$i )
{
for ( $j = 0; $j < $this->columns; ++$j )
{
$equatation->set( $i, $j, $this->matrix[$i][$j] );
}
$equatation->set( $i, $this->columns, $matrix->get( $i, 0 ) );
}
// Compute upper triangular matrix on left side of equatation
for ( $i = 0; $i < ( $this->rows - 1 ); ++$i )
{
for ( $j = $i + 1; $j < $this->rows; ++$j )
{
if ( $equatation->get( $j, $i ) !== 0 )
{
if ( $equatation->get( $j, $i ) == 0 )
{
continue;
}
else
{
$factor = -( $equatation->get( $i, $i ) / $equatation->get( $j, $i ) );
}
for ( $k = $i; $k < $columns; ++$k )
{
$equatation->set( $j, $k, $equatation->get( $i, $k ) + $factor * $equatation->get( $j, $k ) );
}
}
}
}
// Normalize values on left side matrix diagonale
for ( $i = 0; $i < $this->rows; ++$i )
{
if ( ( ( $value = $equatation->get( $i, $i ) ) != 1 ) &&
( $value != 0 ) )
{
$factor = 1 / $value;
for ( $k = $i; $k < $columns; ++$k )
{
$equatation->set( $i, $k, $equatation->get( $i, $k ) * $factor );
}
}
}
// Build up solving polynom
$polynom = new ezcGraphPolynom();
for ( $i = ( $this->rows - 1 ); $i >= 0; --$i )
{
for ( $j = $i + 1; $j < $this->columns; ++$j )
{
$equatation->set(
$i,
$this->columns,
$equatation->get( $i, $this->columns ) + ( -$equatation->get( $i, $j ) * $polynom->get( $j ) )
);
$equatation->set( $i, $j, 0 );
}
$polynom->set( $i, $equatation->get( $i, $this->columns ) );
}
return $polynom;
}
/**
* Build LR decomposition from matrix
*
* Use Cholesky-Crout algorithm to get LR decomposition of the current
* matrix.
*
* Will return an array with two matrices:
* array(
* 'l' => (ezcGraphMatrix) $left,
* 'r' => (ezcGraphMatrix) $right,
* )
*
* @return array( ezcGraphMatrix )
*/
public function LRdecomposition()
{
/**
* Use Cholesky-Crout algorithm to get LR decomposition
*
* Input: Matrix A ($this)
*
* For i = 1 To n
* For j = i To n
* R(i,j)=A(i,j)
* For k = 1 TO i-1
* R(i,j)-=L(i,k)*R(k,j)
* end
* end
* For j=i+1 To n
* L(j,i)= A(j,i)
* For k = 1 TO i-1
* L(j,i)-=L(j,k)*R(k,i)
* end
* L(j,i)/=R(i,i)
* end
* end
*
* Output: matrices L,R
*/
$l = new ezcGraphMatrix( $this->columns, $this->rows );
$r = new ezcGraphMatrix( $this->columns, $this->rows );
for ( $i = 0; $i < $this->columns; ++$i )
{
for ( $j = $i; $j < $this->rows; ++$j )
{
$r->set( $i, $j, $this->matrix[$i][$j] );
for ( $k = 0; $k <= ( $i - 1 ); ++$k )
{
$r->set( $i, $j, $r->get( $i, $j ) - $l->get( $i, $k ) * $r->get( $k, $j ) );
}
}
for ( $j = $i + 1; $j < $this->rows; ++$j )
{
$l->set( $j, $i, $this->matrix[$j][$i] );
for ( $k = 0; $k <= ( $i - 1 ); ++$k )
{
$l->set( $j, $i, $l->get( $j, $i ) - $l->get( $j, $k ) * $r->get( $k, $i ) );
}
$l->set( $j, $i, $l->get( $j, $i ) / $r->get( $i, $i ) );
}
}
return array(
'l' => $l,
'r' => $r,
);
}
/**
* Returns a string representation of the matrix
*
* @return string
*/
public function __toString()
{
$string = sprintf( "%d x %d matrix:\n", $this->rows, $this->columns );
for ( $i = 0; $i < $this->rows; ++$i )
{
$string .= '| ';
for ( $j = 0; $j < $this->columns; ++$j )
{
$string .= sprintf( '%04.2f ', $this->get( $i, $j ) );
}
$string .= "|\n";
}
return $string;
}
}
?>
@@ -0,0 +1,230 @@
<?php
/**
* File containing the abstract ezcGraphPolynom 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
*/
/**
* Provides a class for generic operations on polynoms
*
* @version 1.3
* @package Graph
*/
class ezcGraphPolynom
{
/**
* Factors of the polynom
*
* An example:
* Polynom:
* 2 * x^3 + .5 * x - 3
* Array:
* array (
* (int) 3 => (float) 2,
* (int) 1 => (float) .5,
* (int) 0 => (float) -3,
* )
*
* @var array
*/
protected $values;
// @TODO: Introduce precision option for string output?
/**
* Constructor
*
* Constructs a polynom object from given array, where the key is the
* exponent and the value the factor.
* An example:
* Polynom:
* 2 * x^3 + .5 * x - 3
* Array:
* array (
* (int) 3 => (float) 2,
* (int) 1 => (float) .5,
* (int) 0 => (float) -3,
* )
*
* @param array $values Array with values
* @return ezcGraphPolynom
*/
public function __construct( array $values = array() )
{
foreach ( $values as $exponent => $factor )
{
$this->values[(int) $exponent] = (float) $factor;
}
}
/**
* Initialise a polygon
*
* Initialise a polygon of the given order. Sets all factors to 0.
*
* @param int $order Order of polygon
* @return ezcGraphPolynom Created polynom
*/
public function init( $order )
{
for ( $i = 0; $i <= $order; ++$i )
{
$this->values[$i] = 0;
}
return $this;
}
/**
* Return factor for one exponent
*
* @param int $exponent Exponent
* @return float Factor
*/
public function get( $exponent )
{
if ( !isset( $this->values[$exponent] ) )
{
return 0;
}
else
{
return $this->values[$exponent];
}
}
/**
* Set the factor for one exponent
*
* @param int $exponent Exponent
* @param float $factor Factor
* @return ezcGraphPolynom Modified polynom
*/
public function set( $exponent, $factor )
{
$this->values[(int) $exponent] = (float) $factor;
return $this;
}
/**
* Returns the order of the polynom
*
* @return int Polynom order
*/
public function getOrder()
{
return max( array_keys( $this->values ) );
}
/**
* Adds polynom to current polynom
*
* @param ezcGraphPolynom $polynom Polynom to add
* @return ezcGraphPolynom Modified polynom
*/
public function add( ezcGraphPolynom $polynom )
{
$order = max(
$this->getOrder(),
$polynom->getOrder()
);
for ( $i = 0; $i <= $order; ++$i )
{
$this->set( $i, $this->get( $i ) + $polynom->get( $i ) );
}
return $this;
}
/**
* Evaluate Polynom with a given value
*
* @param float $x Value
* @return float Result
*/
public function evaluate( $x )
{
$value = 0;
foreach ( $this->values as $exponent => $factor )
{
$value += $factor * pow( $x, $exponent );
}
return $value;
}
/**
* Returns a string represenation of the polynom
*
* @return string String representation of polynom
*/
public function __toString()
{
krsort( $this->values );
$string = '';
foreach ( $this->values as $exponent => $factor )
{
if ( $factor == 0 )
{
continue;
}
$string .= ( $factor < 0 ? ' - ' : ' + ' );
$factor = abs( $factor );
switch ( true )
{
case abs( 1 - $factor ) < .0001:
// No not append, if factor is ~1
break;
case $factor < 1:
case $factor >= 1000:
$string .= sprintf( '%.2e ', $factor );
break;
case $factor >= 100:
$string .= sprintf( '%.0f ', $factor );
break;
case $factor >= 10:
$string .= sprintf( '%.1f ', $factor );
break;
default:
$string .= sprintf( '%.2f ', $factor );
break;
}
switch ( true )
{
case $exponent > 1:
$string .= sprintf( 'x^%d', $exponent );
break;
case $exponent === 1:
$string .= 'x';
break;
case $exponent === 0:
if ( abs( 1 - $factor ) < .0001 )
{
$string .= '1';
}
break;
}
}
if ( substr( $string, 0, 3 ) === ' + ' )
{
$string = substr( $string, 3 );
}
else
{
$string = '-' . substr( $string, 3 );
}
return trim( $string );
}
}
?>
@@ -0,0 +1,90 @@
<?php
/**
* File containing the ezcGraphRotation 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
* @access private
*/
/**
* Class to create rotation matrices from given rotation and center point
*
* @version 1.3
* @package Graph
* @access private
*/
class ezcGraphRotation extends ezcGraphTransformation
{
/**
* Rotation in degrees
*
* @var float
*/
protected $rotation;
/**
* Center point
*
* @var ezcGraphCoordinate
*/
protected $center;
/**
* Construct rotation matrix from rotation (in degrees) and optional
* center point.
*
* @param int $rotation
* @param ezcGraphCoordinate $center
* @return ezcGraphTransformation
*/
public function __construct( $rotation = 0, ezcGraphCoordinate $center = null )
{
$this->rotation = (float) $rotation;
if ( $center === null )
{
$this->center = new ezcGraphCoordinate( 0, 0 );
$clockwiseRotation = deg2rad( $rotation );
$rotationMatrixArray = array(
array( cos( $clockwiseRotation ), -sin( $clockwiseRotation ), 0 ),
array( sin( $clockwiseRotation ), cos( $clockwiseRotation ), 0 ),
array( 0, 0, 1 ),
);
return parent::__construct( $rotationMatrixArray );
}
parent::__construct();
$this->center = $center;
$this->multiply( new ezcGraphTranslation( $center->x, $center->y ) );
$this->multiply( new ezcGraphRotation( $rotation ) );
$this->multiply( new ezcGraphTranslation( -$center->x, -$center->y ) );
}
/**
* Return rotaion angle in degrees
*
* @return float
*/
public function getRotation()
{
return $this->rotation;
}
/**
* Return the center point of the current rotation
*
* @return ezcGraphCoordinate
*/
public function getCenter()
{
return $this->center;
}
}
?>
@@ -0,0 +1,85 @@
<?php
/**
* File containing the ezcGraphTransformation 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
* @access private
*/
/**
* Class defining transformations like scaling and rotation by a
* 3x3 transformation matrix for |R^2
*
* @version 1.3
* @package Graph
* @access private
*/
class ezcGraphTransformation extends ezcGraphMatrix
{
/**
* Constructor
*
* Creates a matrix with 3x3 dimensions. Optionally accepts an array to
* define the initial matrix values. If no array is given an identity
* matrix is created.
*
* @param array $values
* @return void
*/
public function __construct( array $values = null )
{
parent::__construct( 3, 3, $values );
}
/**
* Multiplies two matrices
*
* Multiply current matrix with another matrix and returns the result
* matrix.
*
* @param ezcGraphMatrix $matrix Second factor
* @return ezcGraphMatrix Result matrix
*/
public function multiply( ezcGraphMatrix $matrix )
{
$mColumns = $matrix->columns();
// We want to ensure, that the matrix stays 3x3
if ( ( $this->columns !== $matrix->rows() ) &&
( $this->rows !== $mColumns ) )
{
throw new ezcGraphMatrixInvalidDimensionsException( $this->columns, $this->rows, $mColumns, $matrix->rows() );
}
$result = parent::multiply( $matrix );
// The matrix dimensions stay the same, so that we can modify $this.
for ( $i = 0; $i < $this->rows; ++$i )
{
for ( $j = 0; $j < $mColumns; ++$j )
{
$this->set( $i, $j, $result->get( $i, $j ) );
}
}
return $this;
}
/**
* Transform a coordinate with the current transformation matrix.
*
* @param ezcGraphCoordinate $coordinate
* @return ezcGraphCoordinate
*/
public function transformCoordinate( ezcGraphCoordinate $coordinate )
{
$vector = new ezcGraphMatrix( 3, 1, array( array( $coordinate->x ), array( $coordinate->y ), array( 1 ) ) );
$vector = parent::multiply( $vector );
return new ezcGraphCoordinate( $vector->get( 0, 0 ), $vector->get( 1, 0 ) );
}
}
?>
@@ -0,0 +1,38 @@
<?php
/**
* File containing the ezcGraphTranslation 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
* @access private
*/
/**
* Class creating translation matrices from given movements
*
* @version 1.3
* @package Graph
* @access private
*/
class ezcGraphTranslation extends ezcGraphTransformation
{
/**
* Constructor
*
* @param float $x
* @param float $y
* @return void
* @ignore
*/
public function __construct( $x = 0., $y = 0. )
{
parent::__construct( array(
array( 1, 0, $x ),
array( 0, 1, $y ),
array( 0, 0, 1 ),
) );
}
}
?>
@@ -0,0 +1,187 @@
<?php
/**
* File containing the ezcGraphVector 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
* @access private
*/
/**
* Represents two dimensional vectors
*
* @version 1.3
* @package Graph
* @access private
*/
class ezcGraphVector extends ezcGraphCoordinate
{
/**
* Rotates vector to the left by 90 degrees
*
* @return void
*/
public function rotateCounterClockwise()
{
$tmp = $this->x;
$this->x = $this->y;
$this->y = -$tmp;
return $this;
}
/**
* Rotates vector to the right by 90 degrees
*
* @return void
*/
public function rotateClockwise()
{
$tmp = $this->x;
$this->x = -$this->y;
$this->y = $tmp;
return $this;
}
/**
* Unifies vector length to 1
*
* @return void
*/
public function unify()
{
$length = $this->length();
if ( $length == 0 )
{
return $this;
}
$this->x /= $length;
$this->y /= $length;
return $this;
}
/**
* Returns length of vector
*
* @return float
*/
public function length()
{
return sqrt(
pow( $this->x, 2 ) +
pow( $this->y, 2 )
);
}
/**
* Multiplies vector with a scalar
*
* @param float $value
* @return void
*/
public function scalar( $value )
{
$this->x *= $value;
$this->y *= $value;
return $this;
}
/**
* Calculates scalar product of two vectors
*
* @param ezcGraphCoordinate $vector
* @return void
*/
public function mul( ezcGraphCoordinate $vector )
{
return $this->x * $vector->x + $this->y * $vector->y;
}
/**
* Returns the angle between two vectors in radian
*
* @param ezcGraphCoordinate $vector
* @return float
*/
public function angle( ezcGraphCoordinate $vector )
{
if ( !$vector instanceof ezcGraphVector )
{
// Ensure beeing a vector for calling length()
$vector = ezcGraphVector::fromCoordinate( $vector );
}
$factor = $this->length() * $vector->length();
if ( $factor == 0 )
{
return false;
}
else
{
return acos( $this->mul( $vector ) / $factor );
}
}
/**
* Adds a vector to another vector
*
* @param ezcGraphCoordinate $vector
* @return void
*/
public function add( ezcGraphCoordinate $vector )
{
$this->x += $vector->x;
$this->y += $vector->y;
return $this;
}
/**
* Subtracts a vector from another vector
*
* @param ezcGraphCoordinate $vector
* @return void
*/
public function sub( ezcGraphCoordinate $vector )
{
$this->x -= $vector->x;
$this->y -= $vector->y;
return $this;
}
/**
* Creates a vector from a coordinate object
*
* @param ezcGraphCoordinate $coordinate
* @return ezcGraphVector
*/
public static function fromCoordinate( ezcGraphCoordinate $coordinate )
{
return new ezcGraphVector( $coordinate->x, $coordinate->y );
}
/**
* Transform vector using transformation matrix
*
* @param ezcGraphTransformation $transformation
* @return ezcGraphVector
*/
public function transform( ezcGraphTransformation $transformation )
{
$result = $transformation->transformCoordinate( $this );
$this->x = $result->x;
$this->y = $result->y;
return $this;
}
}
?>
@@ -0,0 +1,100 @@
<?php
/**
* File containing the ezcGraphCairoDriverOption 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 containing the extended options for the SVG driver.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->background->color = '#FFFFFFFF';
* $graph->title = 'Access statistics';
* $graph->legend = false;
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
*
* $graph->driver = new ezcGraphCairoDriver();
*
* // No options yet.
*
* $graph->render( 400, 200, 'tutorial_driver_cairo.png' );
* </code>
*
* @property float $imageMapResolution
* Degree step used to interpolate round image primitives by
* polygons for image maps
* @property float $circleResolution
* Resolution for circles, until I understand how to draw ellipses
* with SWFShape::curveTo()
*
* @version 1.3
* @package Graph
*/
class ezcGraphCairoDriverOptions extends ezcGraphDriverOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['imageMapResolution'] = 10;
$this->properties['circleResolution'] = 2.;
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'imageMapResolution':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties['imageMapResolution'] = (int) $propertyValue;
break;
case 'circleResolution':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['circleResolution'] = (float) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
}
?>
@@ -0,0 +1,107 @@
<?php
/**
* File containing the ezcGraphChartOption 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 containing the basic options for charts.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->palette = new ezcGraphPaletteEzBlue();
* $graph->title = 'Access statistics';
*
* // Global font options
* $graph->options->font->name = 'serif';
*
* // Special font options for sub elements
* $graph->title->background = '#EEEEEC';
* $graph->title->font->name = 'sans-serif';
*
* $graph->options->font->maxFontSize = 8;
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
*
* $graph->render( 400, 150, 'tutorial_chart_title.svg' );
* </code>
*
* @property int $width
* Width of the chart.
* @property int $height
* Height of the chart.
* @property ezcGraphFontOptions $font
* Font used in the graph.
*
* @version 1.3
* @package Graph
*/
class ezcGraphChartOptions extends ezcBaseOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['width'] = null;
$this->properties['height'] = null;
$this->properties['font'] = new ezcGraphFontOptions();
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'width':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties['width'] = (int) $propertyValue;
break;
case 'height':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties['height'] = (int) $propertyValue;
break;
case 'font':
$this->properties['font']->path = $propertyValue;
break;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
break;
}
}
}
?>
@@ -0,0 +1,157 @@
<?php
/**
* File containing the ezcGraphDriverOption 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 containing the basic driver options.
*
* <code>
* require_once 'tutorial_autoload.php';
*
* $graph = new ezcGraphPieChart();
* $graph->palette = new ezcGraphPaletteEzBlue();
* $graph->title = 'Access statistics';
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
*
* $graph->driver->options->autoShortenString = false;
*
* $graph->render( 400, 150, 'tutorial_chart_title.svg' );
* </code>
*
* @property int $width
* Width of the chart.
* @property int $height
* Height of the chart.
* @property float $shadeCircularArc
* Percent to darken circular arcs at the sides
* @property float $lineSpacing
* Percent of font size used for line spacing
* @property int $font
* Font used in the graph.
* @property bool $autoShortenString
* Automatically shorten string if it does not fit into a box
* @property string $autoShortenStringPostFix
* String to append to shortened strings, if there is enough space
*
* @version 1.3
* @package Graph
*/
abstract class ezcGraphDriverOptions extends ezcBaseOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['width'] = null;
$this->properties['height'] = null;
$this->properties['lineSpacing'] = .1;
$this->properties['shadeCircularArc'] = .5;
$this->properties['font'] = new ezcGraphFontOptions();
$this->properties['font']->color = ezcGraphColor::fromHex( '#000000' );
$this->properties['autoShortenString'] = true;
$this->properties['autoShortenStringPostFix'] = '..';
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'width':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties['width'] = (int) $propertyValue;
break;
case 'height':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties['height'] = (int) $propertyValue;
break;
case 'lineSpacing':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['lineSpacing'] = (float) $propertyValue;
break;
case 'shadeCircularArc':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['shadeCircularArc'] = (float) $propertyValue;
break;
case 'font':
if ( $propertyValue instanceof ezcGraphFontOptions )
{
$this->properties['font'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphFontOptions' );
}
break;
case 'autoShortenString':
if ( is_bool( $propertyValue ) )
{
$this->properties['autoShortenString'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'boolean' );
}
break;
case 'autoShortenStringPostFix':
$this->properties['autoShortenStringPostFix'] = (string) $propertyValue;
break;
default:
throw new ezcBasePropertyNotFoundException( $propertyName );
break;
}
}
}
?>
@@ -0,0 +1,103 @@
<?php
/**
* File containing the ezcGraphFlashDriverOption 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 containing the extended configuration options for the flash driver.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->title = 'Access statistics';
* $graph->legend = false;
*
* $graph->driver = new ezcGraphFlashDriver();
* $graph->driver->options->compresion = 0;
*
* $graph->options->font = 'tutorial_font.fdb';
*
* $graph->driver->options->compression = 7;
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
*
* $graph->render( 400, 200, 'tutorial_driver_flash.swf' );
* </code>
*
* @property int $compression
* Compression level used for generated flash file
* @see http://php.net/manual/en/function.swfmovie.save.php
* @property float $circleResolution
* Resolution for circles, until I understand how to draw ellipses
* with SWFShape::curveTo()
*
* @version 1.3
* @package Graph
*/
class ezcGraphFlashDriverOptions extends ezcGraphDriverOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['compression'] = 9;
$this->properties['circleResolution'] = 2.;
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'compression':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 9 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= int <= 9' );
}
$this->properties['compression'] = max( 0, min( 9, (int) $propertyValue ) );
break;
case 'circleResolution':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['circleResolution'] = (float) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
}
?>
@@ -0,0 +1,292 @@
<?php
/**
* File containing the ezcGraphFontOption 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 containing the options for font configuration.
*
* Global font settings will only affect the font settings of chart elements
* until they were modified once. Form then on the font configuration of one
* chart element has been copied and can only be configured independently.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->palette = new ezcGraphPaletteEzBlue();
* $graph->title = 'Access statistics';
*
* $graph->options->font->name = 'serif';
* $graph->options->font->maxFontSize = 12;
*
* $graph->title->background = '#EEEEEC';
* $graph->title->font->name = 'sans-serif';
*
* $graph->options->font->maxFontSize = 8;
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
*
* $graph->render( 400, 150, 'tutorial_chart_title.svg' );
* </code>
*
* @property string $name
* Name of font.
* @property string $path
* Path to font file.
* @property int $type
* Type of used font. May be one of the following:
* - TTF_FONT Native TTF fonts
* - PS_FONT PostScript Type1 fonts
* - FT2_FONT FreeType 2 fonts
* @property float $minFontSize
* Minimum font size for displayed texts.
* @property float $maxFontSize
* Maximum font size for displayed texts.
* @property float $minimalUsedFont
* The minimal used font size for this element.
* @property ezcGraphColor $color
* Font color.
* @property ezcGraphColor $background
* Background color
* @property ezcGraphColor $border
* Border color
* @property int $borderWidth
* Border width
* @property int $padding
* Padding between text and border
* @property bool $minimizeBorder
* Fit the border exactly around the text, or use the complete
* possible space.
* @property bool $textShadow
* Draw shadow for texts
* @property int $textShadowOffset
* Offset for text shadow
* @property ezcGraphColor $textShadowColor
* Color of text shadow. If false the inverse color of the text
* color will be used.
*
* @version 1.3
* @package Graph
*/
class ezcGraphFontOptions extends ezcBaseOptions
{
/**
* Indicates if path already has been checked for correct font
*
* @var bool
*/
protected $pathChecked = false;
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['name'] = 'sans-serif';
// $this->properties['path'] = 'Graph/tests/data/font.ttf';
$this->properties['path'] = '';
$this->properties['type'] = ezcGraph::TTF_FONT;
$this->properties['minFontSize'] = 6;
$this->properties['maxFontSize'] = 96;
$this->properties['minimalUsedFont'] = 96;
$this->properties['color'] = ezcGraphColor::fromHex( '#000000' );
$this->properties['background'] = false;
$this->properties['border'] = false;
$this->properties['borderWidth'] = 1;
$this->properties['padding'] = 0;
$this->properties['minimizeBorder'] = true;
$this->properties['textShadow'] = false;
$this->properties['textShadowOffset'] = 1;
$this->properties['textShadowColor'] = false;
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'minFontSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 1' );
}
// Ensure min font size is smaller or equal max font size.
if ( $propertyValue > $this->properties['maxFontSize'] )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float <= ' . $this->properties['maxFontSize'] );
}
$this->properties[$propertyName] = (float) $propertyValue;
break;
case 'maxFontSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 1' );
}
// Ensure max font size is greater or equal min font size.
if ( $propertyValue < $this->properties['minFontSize'] )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float >= ' . $this->properties['minFontSize'] );
}
$this->properties[$propertyName] = (float) $propertyValue;
break;
case 'minimalUsedFont':
$propertyValue = (float) $propertyValue;
if ( $propertyValue < $this->minimalUsedFont )
{
$this->properties['minimalUsedFont'] = $propertyValue;
}
break;
case 'color':
case 'background':
case 'border':
case 'textShadowColor':
$this->properties[$propertyName] = ezcGraphColor::create( $propertyValue );
break;
case 'borderWidth':
case 'padding':
case 'textShadowOffset':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties[$propertyName] = (int) $propertyValue;
break;
case 'minimizeBorder':
case 'textShadow':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties[$propertyName] = (bool) $propertyValue;
break;
case 'name':
if ( is_string( $propertyValue ) )
{
$this->properties['name'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'string' );
}
break;
case 'path':
if ( is_file( $propertyValue ) && is_readable( $propertyValue ) )
{
$this->properties['path'] = realpath( $propertyValue );
$parts = pathinfo( $this->properties['path'] );
switch ( strtolower( $parts['extension'] ) )
{
case 'fdb':
$this->properties['type'] = ezcGraph::PALM_FONT;
break;
case 'pfb':
$this->properties['type'] = ezcGraph::PS_FONT;
break;
case 'ttf':
$this->properties['type'] = ezcGraph::TTF_FONT;
break;
case 'svg':
$this->properties['type'] = ezcGraph::SVG_FONT;
$this->properties['name'] = ezcGraphSvgFont::getFontName( $propertyValue );
break;
default:
throw new ezcGraphUnknownFontTypeException( $propertyValue, $parts['extension'] );
}
$this->pathChecked = true;
}
else
{
throw new ezcBaseFileNotFoundException( $propertyValue, 'font' );
}
break;
case 'type':
if ( is_int( $propertyValue ) )
{
$this->properties['type'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int' );
}
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 'textShadowColor':
// Use inverted font color if false
if ( $this->properties['textShadowColor'] === false )
{
$this->properties['textShadowColor'] = $this->properties['color']->invert();
}
return $this->properties['textShadowColor'];
case 'path':
if ( $this->pathChecked === false )
{
// Enforce call of path check
$this->__set( 'path', $this->properties['path'] );
}
// No break to use parent return
default:
return parent::__get( $propertyName );
}
}
}
?>
@@ -0,0 +1,181 @@
<?php
/**
* File containing the ezcGraphDriverOption 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 containing the extended driver options for the gd driver.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->palette = new ezcGraphPaletteEzGreen();
* $graph->title = 'Access statistics';
* $graph->legend = false;
*
* $graph->driver = new ezcGraphGdDriver();
* $graph->options->font = 'tutorial_font.ttf';
*
* // Generate a Jpeg with lower quality. The default settings result in a better
* // quality image
* $graph->driver->options->supersampling = 1;
* $graph->driver->options->jpegQuality = 100;
* $graph->driver->options->imageFormat = IMG_JPEG;
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
*
* $graph->render( 400, 200, 'tutorial_dirver_gd.jpg' );
* </code>
*
* @property int $imageFormat
* Type of generated image.
* Should be one of those: IMG_PNG, IMG_JPEG
* @property int $jpegQuality
* Quality of generated jpeg
* @property int $detail
* Count of degrees to render one polygon for in circular arcs
* @property int $supersampling
* Factor of supersampling used to simulate antialiasing
* @property string $background
* Background image to put the graph on
* @property string $resampleFunction
* Function used to resample / resize images
* @property bool $forceNativeTTF
* Force use of native ttf functions instead of free type 2
* @property float $imageMapResolution
* Degree step used to interpolate round image primitives by
* polygons for image maps
*
* @version 1.3
* @package Graph
*/
class ezcGraphGdDriverOptions extends ezcGraphDriverOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['imageFormat'] = IMG_PNG;
$this->properties['jpegQuality'] = 70;
$this->properties['detail'] = 1;
$this->properties['shadeCircularArc'] = .5;
$this->properties['supersampling'] = 2;
$this->properties['background'] = false;
$this->properties['resampleFunction'] = 'imagecopyresampled';
$this->properties['forceNativeTTF'] = false;
$this->properties['imageMapResolution'] = 10;
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'imageFormat':
if ( imagetypes() & $propertyValue )
{
$this->properties['imageFormat'] = (int) $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'Unsupported image type.' );
}
break;
case 'jpegQuality':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 100 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= int <= 100' );
}
$this->properties['jpegQuality'] = (int) $propertyValue;
break;
case 'detail':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties['detail'] = (int) $propertyValue;
break;
case 'supersampling':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties['supersampling'] = (int) $propertyValue;
break;
case 'background':
if ( $propertyValue === false ||
( is_file( $propertyValue ) && is_readable( $propertyValue ) ) )
{
$this->properties['background'] = realpath( $propertyValue );
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'readable file' );
}
break;
case 'resampleFunction':
if ( ezcBaseFeatures::hasFunction( $propertyValue ) )
{
$this->properties['resampleFunction'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'function' );
}
break;
case 'forceNativeTTF':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties['forceNativeTTF'] = (bool) $propertyValue;
break;
case 'imageMapResolution':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties['imageMapResolution'] = (int) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
}
?>
@@ -0,0 +1,189 @@
<?php
/**
* File containing the ezcGraphLineChartOption 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 containing the basic options for line charts.
*
* <code>
* $graph = new ezcGraphLineChart();
* $graph->title = 'Wikipedia articles';
*
* $graph->options->fillLines = 220;
* $graph->options->lineThickness = 3;
*
* // Add data
* foreach ( $wikidata as $language => $data )
* {
* $graph->data[$language] = new ezcGraphArrayDataSet( $data );
* }
*
* $graph->render( 400, 150, 'tutorial_line_chart.svg' );
* </code>
*
* @property float $lineThickness
* Thickness of chart lines
* @property mixed $fillLines
* Status wheather the space between line and axis should get filled.
* - FALSE to not fill the space at all.
* - (int) Opacity used to fill up the space with the lines color.
* @property int $symbolSize
* Size of symbols in line chart.
* @property ezcGraphFontOptions $highlightFont
* Font configuration for highlight tests
* @property int $highlightSize
* Size of highlight blocks
* @property bool $highlightLines
* If true, it adds lines to highlight the values position on the
* axis.
* @property true $stackBars
* Stack bars
*
* @version 1.3
* @package Graph
*/
class ezcGraphLineChartOptions extends ezcGraphChartOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['lineThickness'] = 1;
$this->properties['fillLines'] = false;
$this->properties['symbolSize'] = 8;
$this->properties['highlightFont'] = new ezcGraphFontOptions();
$this->properties['highlightFontCloned'] = false;
$this->properties['highlightSize'] = 14;
$this->properties['highlightLines'] = false;
$this->properties['stackBars'] = false;
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'lineThickness':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties[$propertyName] = (int) $propertyValue;
break;
case 'symbolSize':
case 'highlightSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties[$propertyName] = (int) $propertyValue;
break;
case 'fillLines':
if ( ( $propertyValue !== false ) &&
!is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 255 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'false OR 0 <= int <= 255' );
}
$this->properties[$propertyName] = (
$propertyValue === false
? false
: (int) $propertyValue );
break;
case 'highlightFont':
if ( $propertyValue instanceof ezcGraphFontOptions )
{
$this->properties['highlightFont'] = $propertyValue;
}
elseif ( is_string( $propertyValue ) )
{
if ( !$this->properties['highlightFontCloned'] )
{
$this->properties['highlightFont'] = clone $this->font;
$this->properties['highlightFontCloned'] = true;
}
$this->properties['highlightFont']->path = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphFontOptions' );
}
break;
$this->properties['highlightSize'] = max( 1, (int) $propertyValue );
break;
case 'highlightLines':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties['highlightLines'] = $propertyValue;
break;
case 'stackBars':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties['stackBars'] = $propertyValue;
break;
default:
return parent::__set( $propertyName, $propertyValue );
}
}
/**
* __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 'highlightFont':
// Clone font configuration when requested for this element
if ( !$this->properties['highlightFontCloned'] )
{
$this->properties['highlightFont'] = clone $this->properties['font'];
$this->properties['highlightFontCloned'] = true;
}
return $this->properties['highlightFont'];
default:
return parent::__get( $propertyName );
}
}
}
?>
@@ -0,0 +1,113 @@
<?php
/**
* File containing the ezcGraphOdometerChartOptions 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 containing the options for odometer charts
*
* <code>
* $graph = new ezcGraphOdoMeterChart();
*
* $graph->data['Test'] = new ezcGraphArrayDataSet( array( 0, 1, 23, 30 ) );
*
* $graph->options->odometerHeight = .3;
* $graph->options->borderColor = '#2e3436';
*
* $graph->render( 150, 50, 'odometer.svg' );
* </code>
*
* @property ezcGraphColor $borderColor
* Color of border around odometer chart
* @property int $borderWidth
* Width of border around odometer chart
* @property ezcGraphColor $startColor
* Start color of grdient used as the odometer chart background.
* @property ezcGraphColor $endColor
* End color of grdient used as the odometer chart background.
* @property int $markerWidth
* Width of odometer markers
* @property float $odometerHeight
* Height consumed by odometer chart
*
* @version 1.3
* @package Graph
*/
class ezcGraphOdometerChartOptions extends ezcGraphChartOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['borderColor'] = ezcGraphColor::create( '#000000' );
$this->properties['borderWidth'] = 0;
$this->properties['startColor'] = ezcGraphColor::create( '#4e9a06A0' );
$this->properties['endColor'] = ezcGraphColor::create( '#A40000A0' );
$this->properties['markerWidth'] = 2;
$this->properties['odometerHeight'] = 0.5;
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'borderWidth':
case 'markerWidth':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties[$propertyName] = (int) $propertyValue;
break;
case 'borderColor':
case 'startColor':
case 'endColor':
$this->properties[$propertyName] = ezcGraphColor::create( $propertyValue );
break;
case 'odometerHeight':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties[$propertyName] = (float) $propertyValue;
break;
default:
return parent::__set( $propertyName, $propertyValue );
}
}
}
?>
@@ -0,0 +1,143 @@
<?php
/**
* File containing the ezcGraphPieChartOption 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 containing the basic options for pie charts.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->palette = new ezcGraphPaletteEzRed();
* $graph->title = 'Access statistics';
* $graph->legend = false;
*
* $graph->options->label = '%1$s (%3$.1f)';
* $graph->options->percentThreshold = .05;
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
* $graph->data['Access statistics']->highlight['Explorer'] = true;
*
* $graph->render( 400, 150, 'tutorial_pie_chart_options.svg' );
* </code>
*
* @property string $label
* String used to label pies
* %1$s Name of pie
* %2$d Value of pie
* %3$.1f Percentage
* @property callback $labelCallback
* Callback function to format pie chart labels.
* Function will receive 3 parameters:
* string function( label, value, percent )
* @property float $sum
* Fixed sum of values. This should be used for incomplete pie
* charts.
* @property float $percentThreshold
* Values with a lower percentage value are aggregated.
* @property float $absoluteThreshold
* Values with a lower absolute value are aggregated.
* @property string $summarizeCaption
* Caption for values summarized because they are lower then the
* configured tresh hold.
*
* @version 1.3
* @package Graph
*/
class ezcGraphPieChartOptions extends ezcGraphChartOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['label'] = '%1$s: %2$d (%3$.1f%%)';
$this->properties['labelCallback'] = null;
$this->properties['sum'] = false;
$this->properties['percentThreshold'] = .0;
$this->properties['absoluteThreshold'] = .0;
$this->properties['summarizeCaption'] = 'Misc';
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'label':
$this->properties['label'] = (string) $propertyValue;
break;
case 'labelCallback':
if ( is_callable( $propertyValue ) )
{
$this->properties['labelCallback'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'callback function' );
}
break;
case 'sum':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['sum'] = (float) $propertyValue;
break;
case 'percentThreshold':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['percentThreshold'] = (float) $propertyValue;
break;
case 'absoluteThreshold':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['absoluteThreshold'] = (float) $propertyValue;
break;
case 'summarizeCaption':
$this->properties['summarizeCaption'] = (string) $propertyValue;
break;
default:
return parent::__set( $propertyName, $propertyValue );
}
}
}
?>
@@ -0,0 +1,172 @@
<?php
/**
* File containing the ezcGraphRadarChartOption 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 containing the basic options for radar charts.
*
* <code>
* $wikidata = include 'tutorial_wikipedia_data.php';
*
* $graph = new ezcGraphRadarChart();
* $graph->title = 'Wikipedia articles';
*
* $graph->options->fillLines = 220;
*
* // Add data
* foreach ( $wikidata as $language => $data )
* {
* $graph->data[$language] = new ezcGraphArrayDataSet( $data );
* $graph->data[$language][] = reset( $data );
* }
*
* $graph->render( 400, 150, 'tutorial_radar_chart.svg' );
* </code>
*
* @property float $lineThickness
* Theickness of chart lines
* @property mixed $fillLines
* Status wheather the space between line and axis should get filled.
* - FALSE to not fill the space at all.
* - (int) Opacity used to fill up the space with the lines color.
* @property int $symbolSize
* Size of symbols in line chart.
* @property ezcGraphFontOptions $highlightFont
* Font configuration for highlight tests
* @property int $highlightSize
* Size of highlight blocks
* @property bool $highlightRadars
* If true, it adds lines to highlight the values position on the
* axis.
*
* @version 1.3
* @package Graph
*/
class ezcGraphRadarChartOptions extends ezcGraphChartOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['lineThickness'] = 1;
$this->properties['fillLines'] = false;
$this->properties['symbolSize'] = 8;
$this->properties['highlightFont'] = new ezcGraphFontOptions();
$this->properties['highlightFontCloned'] = false;
$this->properties['highlightSize'] = 14;
$this->properties['highlightRadars'] = false;
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'lineThickness':
case 'symbolSize':
case 'highlightSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 1' );
}
$this->properties[$propertyName] = (int) $propertyValue;
break;
case 'fillLines':
if ( ( $propertyValue !== false ) &&
!is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 255 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'false OR 0 <= int <= 255' );
}
$this->properties[$propertyName] = (
$propertyValue === false
? false
: (int) $propertyValue );
break;
case 'highlightFont':
if ( $propertyValue instanceof ezcGraphFontOptions )
{
$this->properties['highlightFont'] = $propertyValue;
}
elseif ( is_string( $propertyValue ) )
{
if ( !$this->properties['highlightFontCloned'] )
{
$this->properties['highlightFont'] = clone $this->font;
$this->properties['highlightFontCloned'] = true;
}
$this->properties['highlightFont']->path = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphFontOptions' );
}
break;
$this->properties['highlightSize'] = max( 1, (int) $propertyValue );
break;
case 'highlightRadars':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties['highlightRadars'] = $propertyValue;
break;
default:
return parent::__set( $propertyName, $propertyValue );
}
}
/**
* __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 'highlightFont':
// Clone font configuration when requested for this element
if ( !$this->properties['highlightFontCloned'] )
{
$this->properties['highlightFont'] = clone $this->properties['font'];
$this->properties['highlightFontCloned'] = true;
}
return $this->properties['highlightFont'];
default:
return parent::__get( $propertyName );
}
}
}
?>
@@ -0,0 +1,212 @@
<?php
/**
* File containing the ezcGraphRenderer2dOptions 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 containing the basic options for renderers.
*
* <code>
* $wikidata = include 'tutorial_wikipedia_data.php';
*
* $graph = new ezcGraphBarChart();
* $graph->title = 'Wikipedia articles';
*
* // Add data
* foreach ( $wikidata as $language => $data )
* {
* $graph->data[$language] = new ezcGraphArrayDataSet( $data );
* }
*
* // $graph->renderer = new ezcGraphRenderer2d();
*
* $graph->renderer->options->barMargin = .2;
* $graph->renderer->options->barPadding = .2;
*
* $graph->renderer->options->dataBorder = 0;
*
* $graph->render( 400, 150, 'tutorial_bar_chart_options.svg' );
* </code>
*
* @property float $maxLabelHeight
* Percent of chart height used as maximum height for pie chart
* labels.
* @property bool $showSymbol
* Indicates wheather to show the line between pie elements and
* labels.
* @property float $symbolSize
* Size of symbols used to connect a label with a pie.
* @property float $moveOut
* Percent to move pie chart elements out of the middle on highlight.
* @property int $titlePosition
* Position of title in a box.
* @property int $titleAlignement
* Alignement of box titles.
* @property float $dataBorder
* Factor to darken border of data elements, like lines, bars and
* pie segments.
* @property float $barMargin
* Procentual distance between bar blocks.
* @property float $barPadding
* Procentual distance between bars.
* @property float $pieChartOffset
* Offset for starting with first pie chart segment in degrees.
* @property float $legendSymbolGleam
* Opacity of gleam in legend symbols
* @property float $legendSymbolGleamSize
* Size of gleam in legend symbols
* @property float $legendSymbolGleamColor
* Color of gleam in legend symbols
* @property float $pieVerticalSize
* Percent of vertical space used for maximum pie chart size.
* @property float $pieHorizontalSize
* Percent of horizontal space used for maximum pie chart size.
* @property float $pieChartSymbolColor
* Color of pie chart symbols
* @property float $pieChartGleam
* Enhance pie chart with gleam on top.
* @property float $pieChartGleamColor
* Color used for gleam on pie charts.
* @property float $pieChartGleamBorder
* Do not draw gleam on an outer border of this size.
* @property bool $syncAxisFonts
* Synchronize fonts of axis. With the defaut true value, the only
* the fonts of the yAxis will be used.
*
* @version 1.3
* @package Graph
*/
class ezcGraphRendererOptions extends ezcGraphChartOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['maxLabelHeight'] = .10;
$this->properties['showSymbol'] = true;
$this->properties['symbolSize'] = 6;
$this->properties['moveOut'] = .1;
$this->properties['titlePosition'] = ezcGraph::TOP;
$this->properties['titleAlignement'] = ezcGraph::MIDDLE | ezcGraph::CENTER;
$this->properties['dataBorder'] = .5;
$this->properties['barMargin'] = .1;
$this->properties['barPadding'] = .05;
$this->properties['pieChartOffset'] = 0;
$this->properties['pieChartSymbolColor'] = ezcGraphColor::fromHex( '#000000' );
$this->properties['pieChartGleam'] = false;
$this->properties['pieChartGleamColor'] = ezcGraphColor::fromHex( '#FFFFFF' );
$this->properties['pieChartGleamBorder'] = 0;
$this->properties['legendSymbolGleam'] = false;
$this->properties['legendSymbolGleamSize'] = .9;
$this->properties['legendSymbolGleamColor'] = ezcGraphColor::fromHex( '#FFFFFF' );
$this->properties['pieVerticalSize'] = .5;
$this->properties['pieHorizontalSize'] = .25;
$this->properties['syncAxisFonts'] = true;
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'dataBorder':
case 'pieChartGleam':
case 'legendSymbolGleam':
if ( $propertyValue !== false &&
!is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'false OR 0 <= float <= 1' );
}
$this->properties[$propertyName] = (
$propertyValue === false
? false
: (float) $propertyValue );
break;
case 'maxLabelHeight':
case 'moveOut':
case 'barMargin':
case 'barPadding':
case 'legendSymbolGleamSize':
case 'pieVerticalSize':
case 'pieHorizontalSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties[$propertyName] = (float) $propertyValue;
break;
case 'symbolSize':
case 'titlePosition':
case 'titleAlignement':
case 'pieChartGleamBorder':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' );
}
$this->properties[$propertyName] = (int) $propertyValue;
break;
case 'showSymbol':
case 'syncAxisFonts':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties[$propertyName] = (bool) $propertyValue;
break;
case 'pieChartOffset':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 360 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 360' );
}
$this->properties[$propertyName] = (float) $propertyValue;
break;
case 'pieChartSymbolColor':
case 'pieChartGleamColor':
case 'legendSymbolGleamColor':
$this->properties[$propertyName] = ezcGraphColor::create( $propertyValue );
break;
default:
return parent::__set( $propertyName, $propertyValue );
}
}
}
?>
@@ -0,0 +1,120 @@
<?php
/**
* File containing the ezcGraphRenderer2dOptions 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 containing the extended options available in 2d renderer.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->palette = new ezcGraphPaletteBlack();
* $graph->title = 'Access statistics';
* $graph->options->label = '%2$d (%3$.1f%%)';
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
* $graph->data['Access statistics']->highlight['Explorer'] = true;
*
* // $graph->renderer = new ezcGraphRenderer2d();
*
* $graph->renderer->options->moveOut = .2;
*
* $graph->renderer->options->pieChartOffset = 63;
*
* $graph->renderer->options->pieChartGleam = .3;
* $graph->renderer->options->pieChartGleamColor = '#FFFFFF';
* $graph->renderer->options->pieChartGleamBorder = 2;
*
* $graph->renderer->options->pieChartShadowSize = 3;
* $graph->renderer->options->pieChartShadowColor = '#000000';
*
* $graph->renderer->options->legendSymbolGleam = .5;
* $graph->renderer->options->legendSymbolGleamSize = .9;
* $graph->renderer->options->legendSymbolGleamColor = '#FFFFFF';
*
* $graph->renderer->options->pieChartSymbolColor = '#BABDB688';
*
* $graph->render( 400, 150, 'tutorial_pie_chart_pimped.svg' );
* </code>
*
* @property int $pieChartShadowSize
* Size of shadows.
* @property float $pieChartShadowTransparency
* Used transparency for pie chart shadows.
* @property float $pieChartShadowColor
* Color used for pie chart shadows.
*
* @version 1.3
* @package Graph
*/
class ezcGraphRenderer2dOptions extends ezcGraphRendererOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['pieChartShadowSize'] = 0;
$this->properties['pieChartShadowTransparency'] = .3;
$this->properties['pieChartShadowColor'] = ezcGraphColor::fromHex( '#000000' );
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'pieChartShadowSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float >= 0' );
}
$this->properties['pieChartShadowSize'] = (int) $propertyValue;
break;
case 'pieChartShadowTransparency':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties['pieChartShadowTransparency'] = (float) $propertyValue;
break;
case 'pieChartShadowColor':
$this->properties['pieChartShadowColor'] = ezcGraphColor::create( $propertyValue );
break;
default:
return parent::__set( $propertyName, $propertyValue );
}
}
}
?>
@@ -0,0 +1,185 @@
<?php
/**
* File containing the ezcGraphRenderer3dOptions 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 containing the extended options for the three dimensional renderer.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->palette = new ezcGraphPaletteEzRed();
* $graph->title = 'Access statistics';
* $graph->options->label = '%2$d (%3$.1f%%)';
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
* $graph->data['Access statistics']->highlight['Explorer'] = true;
*
* $graph->renderer = new ezcGraphRenderer3d();
*
* $graph->renderer->options->moveOut = .2;
*
* $graph->renderer->options->pieChartOffset = 63;
*
* $graph->renderer->options->pieChartGleam = .3;
* $graph->renderer->options->pieChartGleamColor = '#FFFFFF';
*
* $graph->renderer->options->pieChartShadowSize = 5;
* $graph->renderer->options->pieChartShadowColor = '#000000';
*
* $graph->renderer->options->legendSymbolGleam = .5;
* $graph->renderer->options->legendSymbolGleamSize = .9;
* $graph->renderer->options->legendSymbolGleamColor = '#FFFFFF';
*
* $graph->renderer->options->pieChartSymbolColor = '#55575388';
*
* $graph->renderer->options->pieChartHeight = 5;
* $graph->renderer->options->pieChartRotation = .8;
*
* $graph->render( 400, 150, 'tutorial_pie_chart_3d.svg' );
* </code>
*
* @property bool $seperateLines
* Indicates wheather the full depth should be used for each line in
* the chart, or beeing seperated by the count of lines.
* @property float $fillAxis
* Transparency used to fill the axis polygon.
* @property float $fillGrid
* Transparency used to fill the grid lines.
* @property float $depth
* Part of picture used to simulate depth of three dimensional chart.
* @property float $pieChartHeight
* Height of the pie charts border.
* @property float $pieChartRotation
* Rotation of pie chart. Defines the percent of width used to
* calculate the height of the ellipse.
* @property int $pieChartShadowSize
* Size of shadows.
* @property float $pieChartShadowTransparency
* Used transparency for pie chart shadows.
* @property float $pieChartShadowColor
* Color used for pie chart shadows.
* @property float $barDarkenSide
* Factor to darken the color used for the bars side polygon.
* @property float $barDarkenTop
* Factor to darken the color used for the bars top polygon.
* @property float $barChartGleam
* Transparancy for gleam on bar charts
*
* @version 1.3
* @package Graph
*/
class ezcGraphRenderer3dOptions extends ezcGraphRendererOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['seperateLines'] = true;
$this->properties['fillAxis'] = .8;
$this->properties['fillGrid'] = 0;
$this->properties['depth'] = .1;
$this->properties['pieChartHeight'] = 10.;
$this->properties['pieChartRotation'] = .6;
$this->properties['pieChartShadowSize'] = 0;
$this->properties['pieChartShadowTransparency'] = .3;
$this->properties['pieChartShadowColor'] = ezcGraphColor::fromHex( '#000000' );
$this->properties['pieChartGleam'] = false;
$this->properties['pieChartGleamColor'] = ezcGraphColor::fromHex( '#FFFFFF' );
$this->properties['barDarkenSide'] = .2;
$this->properties['barDarkenTop'] = .4;
$this->properties['barChartGleam'] = false;
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'fillAxis':
case 'fillGrid':
if ( $propertyValue !== false &&
!is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'false OR 0 <= float <= 1' );
}
$this->properties[$propertyName] = (
$propertyValue === false
? false
: (float) $propertyValue );
break;
case 'depth':
case 'pieChartRotation':
case 'pieChartShadowTransparency':
case 'barDarkenSide':
case 'barDarkenTop':
case 'barChartGleam':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) ||
( $propertyValue > 1 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, '0 <= float <= 1' );
}
$this->properties[$propertyName] = (float) $propertyValue;
break;
case 'pieChartHeight':
case 'pieChartShadowSize':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue <= 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties[$propertyName] = (float) $propertyValue;
break;
case 'seperateLines':
if ( !is_bool( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' );
}
$this->properties['seperateLines'] = $propertyValue;
break;
case 'pieChartShadowColor':
$this->properties['pieChartShadowColor'] = ezcGraphColor::create( $propertyValue );
break;
default:
return parent::__set( $propertyName, $propertyValue );
}
}
}
?>
@@ -0,0 +1,272 @@
<?php
/**
* File containing the ezcGraphSvgDriverOption 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 containing the extended options for the SVG driver.
*
* <code>
* $graph = new ezcGraphPieChart();
* $graph->background->color = '#FFFFFFFF';
* $graph->title = 'Access statistics';
* $graph->legend = false;
*
* $graph->data['Access statistics'] = new ezcGraphArrayDataSet( array(
* 'Mozilla' => 19113,
* 'Explorer' => 10917,
* 'Opera' => 1464,
* 'Safari' => 652,
* 'Konqueror' => 474,
* ) );
*
* $graph->driver->options->templateDocument = dirname( __FILE__ ) . '/template.svg';
* $graph->driver->options->graphOffset = new ezcGraphCoordinate( 25, 40 );
* $graph->driver->options->insertIntoGroup = 'ezcGraph';
*
* $graph->render( 400, 200, 'tutorial_driver_svg.svg' );
* </code>
*
* @property string $encoding
* Encoding of the SVG XML document
* @property float $assumedNumericCharacterWidth
* Assumed percentual average width of chars in numeric strings with
* the used font.
* @property float $assumedTextCharacterWidth
* Assumed percentual average width of chars in non numeric strings
* with the used font.
* @property string $strokeLineCap
* This specifies the shape to be used at the end of open subpaths
* when they are stroked.
* @property string $strokeLineJoin
* This specifies the shape to be used at the edges of paths.
* @property string $shapeRendering
* "The creator of SVG content might want to provide a hint to the
* implementation about what tradeoffs to make as it renders vector
* graphics elements such as 'path' elements and basic shapes such as
* circles and rectangles."
* @property string $colorRendering
* "The creator of SVG content might want to provide a hint to the
* implementation about how to make speed vs. quality tradeoffs as it
* performs color interpolation and compositing. The
* 'color-rendering' property provides a hint to the SVG user agent
* about how to optimize its color interpolation and compositing
* operations."
* @property string $textRendering
* "The creator of SVG content might want to provide a hint to the
* implementation about what tradeoffs to make as it renders text."
* @property mixed $templateDocument
* Use existing SVG document as template to insert graph into. If
* insertIntoGroup is not set, a new group will be inserted in the
* svg root node.
* @property mixed $insertIntoGroup
* ID of a SVG group node to insert the graph. Only works with a
* custom template document.
* @property ezcGraphCoordinate $graphOffset
* Offset of the graph in the svg.
* @property string $idPrefix
* Prefix used for the ids in SVG documents.
* @property string $linkCursor
* CSS value for cursor property used for linked SVG elements
*
* @version 1.3
* @package Graph
*/
class ezcGraphSvgDriverOptions extends ezcGraphDriverOptions
{
/**
* Constructor
*
* @param array $options Default option array
* @return void
* @ignore
*/
public function __construct( array $options = array() )
{
$this->properties['encoding'] = null;
$this->properties['assumedNumericCharacterWidth'] = .62;
$this->properties['assumedTextCharacterWidth'] = .53;
$this->properties['strokeLineJoin'] = 'round';
$this->properties['strokeLineCap'] = 'round';
$this->properties['shapeRendering'] = 'geometricPrecision';
$this->properties['colorRendering'] = 'optimizeQuality';
$this->properties['textRendering'] = 'optimizeLegibility';
$this->properties['templateDocument'] = false;
$this->properties['insertIntoGroup'] = false;
$this->properties['graphOffset'] = new ezcGraphCoordinate( 0, 0 );
$this->properties['idPrefix'] = 'ezcGraph';
$this->properties['linkCursor'] = 'pointer';
parent::__construct( $options );
}
/**
* Set an option value
*
* @param string $propertyName
* @param mixed $propertyValue
* @throws ezcBasePropertyNotFoundException
* If a property is not defined in this class
* @return void
* @ignore
*/
public function __set( $propertyName, $propertyValue )
{
switch ( $propertyName )
{
case 'assumedNumericCharacterWidth':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['assumedNumericCharacterWidth'] = (float) $propertyValue;
break;
case 'assumedTextCharacterWidth':
if ( !is_numeric( $propertyValue ) ||
( $propertyValue < 0 ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
}
$this->properties['assumedTextCharacterWidth'] = (float) $propertyValue;
break;
case 'strokeLineJoin':
$values = array(
'round',
'miter',
'bevel',
'inherit',
);
if ( in_array( $propertyValue, $values, true ) )
{
$this->properties['strokeLineJoin'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, implode( $values, ', ' ) );
}
break;
case 'strokeLineCap':
$values = array(
'round',
'butt',
'square',
'inherit',
);
if ( in_array( $propertyValue, $values, true ) )
{
$this->properties['strokeLineCap'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, implode( $values, ', ' ) );
}
break;
case 'shapeRendering':
$values = array(
'auto',
'optimizeSpeed',
'crispEdges',
'geometricPrecision',
'inherit',
);
if ( in_array( $propertyValue, $values, true ) )
{
$this->properties['shapeRendering'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, implode( $values, ', ' ) );
}
break;
case 'colorRendering':
$values = array(
'auto',
'optimizeSpeed',
'optimizeQuality',
'inherit',
);
if ( in_array( $propertyValue, $values, true ) )
{
$this->properties['colorRendering'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, implode( $values, ', ' ) );
}
break;
case 'textRendering':
$values = array(
'auto',
'optimizeSpeed',
'optimizeLegibility',
'geometricPrecision',
'inherit',
);
if ( in_array( $propertyValue, $values, true ) )
{
$this->properties['textRendering'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, implode( $values, ', ' ) );
}
break;
case 'templateDocument':
if ( !is_file( $propertyValue ) || !is_readable( $propertyValue ) )
{
throw new ezcBaseFileNotFoundException( $propertyValue );
}
else
{
$this->properties['templateDocument'] = realpath( $propertyValue );
}
break;
case 'insertIntoGroup':
if ( !is_string( $propertyValue ) )
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'string' );
}
else
{
$this->properties['insertIntoGroup'] = $propertyValue;
}
break;
case 'graphOffset':
if ( $propertyValue instanceof ezcGraphCoordinate )
{
$this->properties['graphOffset'] = $propertyValue;
}
else
{
throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcGraphCoordinate' );
}
break;
case 'idPrefix':
$this->properties['idPrefix'] = (string) $propertyValue;
break;
case 'encoding':
$this->properties['encoding'] = (string) $propertyValue;
break;
case 'linkCursor':
$this->properties['linkCursor'] = (string) $propertyValue;
break;
default:
parent::__set( $propertyName, $propertyValue );
break;
}
}
}
?>
@@ -0,0 +1,114 @@
<?php
/**
* File containing the ezcGraphPaletteBlack 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
*/
/**
* Dark color pallet for ezcGraph based on Tango style guidelines at
* http://tango-project.org/Generic_Icon_Theme_Guidelines
*
* @version 1.3
* @package Graph
*/
class ezcGraphPaletteBlack extends ezcGraphPalette
{
/**
* Axiscolor
*
* @var ezcGraphColor
*/
protected $axisColor = '#EEEEEC';
/**
* Color of grid lines
*
* @var ezcGraphColor
*/
protected $majorGridColor = '#888A85';
/**
* Color of minor grid lines
*
* @var ezcGraphColor
*/
protected $minorGridColor = '#888A8588';
/**
* Array with colors for datasets
*
* @var array
*/
protected $dataSetColor = array(
'#729FCF',
'#EF2929',
'#FCE94F',
'#8AE234',
'#F57900',
'#AD7FA8',
);
/**
* Array with symbols for datasets
*
* @var array
*/
protected $dataSetSymbol = array(
ezcGraph::BULLET,
);
/**
* Name of font to use
*
* @var string
*/
protected $fontName = 'sans-serif';
/**
* Fontcolor
*
* @var ezcGraphColor
*/
protected $fontColor = '#D3D7CF';
/**
* Backgroundcolor
*
* @var ezcGraphColor
*/
protected $chartBackground = '#2E3436';
/**
* Border color for chart elements
*
* @var string
*/
protected $elementBorderColor = '#555753';
/**
* Border width for chart elements
*
* @var integer
*/
protected $elementBorderWidth = 1;
/**
* Padding in elements
*
* @var integer
*/
protected $padding = 1;
/**
* Margin of elements
*
* @var integer
*/
protected $margin = 1;
}
?>
@@ -0,0 +1,97 @@
<?php
/**
* File containing the ezcGraphPaletteEz 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
*/
/**
* Color pallet for ezcGraph based on eZ color scheme
*
* @version 1.3
* @package Graph
*/
class ezcGraphPaletteEz extends ezcGraphPalette
{
/**
* Axiscolor
*
* @var ezcGraphColor
*/
protected $axisColor = '#1E1E1E';
/**
* Color of grid lines
*
* @var ezcGraphColor
*/
protected $majorGridColor = '#D3D7DF';
/**
* Array with colors for datasets
*
* @var array
*/
protected $dataSetColor = array(
'#C60C30',
'#C90062',
'#E05206',
'#F0AB00',
'#D4BA00',
'#9C9A00',
'#3C8A2E',
'#006983',
'#0098C3',
'#21578A',
'#55517B',
'#4E7D5B',
);
/**
* Array with symbols for datasets
*
* @var array
*/
protected $dataSetSymbol = array(
ezcGraph::BULLET,
);
/**
* Name of font to use
*
* @var string
*/
protected $fontName = 'sans-serif';
/**
* Fontcolor
*
* @var ezcGraphColor
*/
protected $fontColor = '#1E1E1E';
/**
* Backgroundcolor for chart
*
* @var ezcGraphColor
*/
protected $chartBackground = '#FFFFFFFF';
/**
* Padding in elements
*
* @var integer
*/
protected $padding = 1;
/**
* Margin of elements
*
* @var integer
*/
protected $margin = 0;
}
?>
@@ -0,0 +1,90 @@
<?php
/**
* File containing the ezcGraphPaletteEzBlue 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
*/
/**
* Light blue color pallet for ezcGraph based on blue eZ colors
*
* @version 1.3
* @package Graph
*/
class ezcGraphPaletteEzBlue extends ezcGraphPalette
{
/**
* Axiscolor
*
* @var ezcGraphColor
*/
protected $axisColor = '#2E3436';
/**
* Color of grid lines
*
* @var ezcGraphColor
*/
protected $majorGridColor = '#D3D7DF';
/**
* Array with colors for datasets
*
* @var array
*/
protected $dataSetColor = array(
'#5489F2',
'#699BFF',
'#85AEFF',
'#A3C2FF',
'#BDD3FF',
);
/**
* Array with symbols for datasets
*
* @var array
*/
protected $dataSetSymbol = array(
ezcGraph::BULLET,
);
/**
* Name of font to use
*
* @var string
*/
protected $fontName = 'sans-serif';
/**
* Fontcolor
*
* @var ezcGraphColor
*/
protected $fontColor = '#2E3436';
/**
* Backgroundcolor for chart
*
* @var ezcGraphColor
*/
protected $chartBackground = '#FFFFFF';
/**
* Padding in elements
*
* @var integer
*/
protected $padding = 1;
/**
* Margin of elements
*
* @var integer
*/
protected $margin = 0;
}
?>
@@ -0,0 +1,90 @@
<?php
/**
* File containing the ezcGraphPaletteEzGreen 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
*/
/**
* Light green color pallet for ezcGraph based on green eZ colors
*
* @version 1.3
* @package Graph
*/
class ezcGraphPaletteEzGreen extends ezcGraphPalette
{
/**
* Axiscolor
*
* @var ezcGraphColor
*/
protected $axisColor = '#2E3436';
/**
* Color of grid lines
*
* @var ezcGraphColor
*/
protected $majorGridColor = '#D3D7DF';
/**
* Array with colors for datasets
*
* @var array
*/
protected $dataSetColor = array(
'#9CAE86',
'#87B06B',
'#5C9A75',
'#467A6E',
'#4F6C57',
);
/**
* Array with symbols for datasets
*
* @var array
*/
protected $dataSetSymbol = array(
ezcGraph::BULLET,
);
/**
* Name of font to use
*
* @var string
*/
protected $fontName = 'sans-serif';
/**
* Fontcolor
*
* @var ezcGraphColor
*/
protected $fontColor = '#2E3436';
/**
* Backgroundcolor for chart
*
* @var ezcGraphColor
*/
protected $chartBackground = '#FFFFFF';
/**
* Padding in elements
*
* @var integer
*/
protected $padding = 1;
/**
* Margin of elements
*
* @var integer
*/
protected $margin = 0;
}
?>
@@ -0,0 +1,90 @@
<?php
/**
* File containing the ezcGraphPaletteEzRed 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
*/
/**
* Light red color pallet for ezcGraph based on red eZ colors
*
* @version 1.3
* @package Graph
*/
class ezcGraphPaletteEzRed extends ezcGraphPalette
{
/**
* Axiscolor
*
* @var ezcGraphColor
*/
protected $axisColor = '#2E3436';
/**
* Color of grid lines
*
* @var ezcGraphColor
*/
protected $majorGridColor = '#D3D7DF';
/**
* Array with colors for datasets
*
* @var array
*/
protected $dataSetColor = array(
'#B50D2C',
'#C42926',
'#C34009',
'#CA3C04',
'#D86300',
);
/**
* Array with symbols for datasets
*
* @var array
*/
protected $dataSetSymbol = array(
ezcGraph::BULLET,
);
/**
* Name of font to use
*
* @var string
*/
protected $fontName = 'sans-serif';
/**
* Fontcolor
*
* @var ezcGraphColor
*/
protected $fontColor = '#2E3436';
/**
* Backgroundcolor for chart
*
* @var ezcGraphColor
*/
protected $chartBackground = '#FFFFFF';
/**
* Padding in elements
*
* @var integer
*/
protected $padding = 1;
/**
* Margin of elements
*
* @var integer
*/
protected $margin = 0;
}
?>
@@ -0,0 +1,87 @@
<?php
/**
* File containing the ezcGraphPaletteTango 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
*/
/**
* Light color pallet for ezcGraph based on Tango style guidelines at
* http://tango-project.org/Generic_Icon_Theme_Guidelines
*
* @version 1.3
* @package Graph
*/
class ezcGraphPaletteTango extends ezcGraphPalette
{
/**
* Axiscolor
*
* @var ezcGraphColor
*/
protected $axisColor = '#2E3436';
/**
* Array with colors for datasets
*
* @var array
*/
protected $dataSetColor = array(
'#3465A4',
'#4E9A06',
'#CC0000',
'#EDD400',
'#75505B',
'#F57900',
'#204A87',
'#C17D11',
);
/**
* Array with symbols for datasets
*
* @var array
*/
protected $dataSetSymbol = array(
ezcGraph::NO_SYMBOL,
);
/**
* Name of font to use
*
* @var string
*/
protected $fontName = 'sans-serif';
/**
* Fontcolor
*
* @var ezcGraphColor
*/
protected $fontColor = '#2E3436';
/**
* Backgroundcolor for chart
*
* @var ezcGraphColor
*/
protected $chartBackground = '#EEEEEC';
/**
* Padding in elements
*
* @var integer
*/
protected $padding = 1;
/**
* Margin of elements
*
* @var integer
*/
protected $margin = 0;
}
?>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More