Source for file Graph.php
Documentation is available at Graph.php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
* Image_Graph - Main class for the graph creation.
* LICENSE: This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version. This library is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this library; if not, write
* to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* @author Jesper Veggerby <pear.nosey@veggerby.dk>
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
* @copyright 2003-2009 The PHP Group
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version SVN: $Id: Graph.php 291756 2009-12-06 02:55:46Z neufeind $
* @link http://pear.php.net/package/Image_Graph
* Include file Image/Graph/Element.php
require_once 'Image/Graph/Element.php';
* Include file Image/Graph/Constants.php
require_once 'Image/Graph/Constants.php';
* Main class for the graph creation.
* This is the main class, it manages the canvas and performs the final output
* by sequentialy making the elements output their results. The final output is
* handled using the {@link Image_Canvas} classes which makes it possible
* to use different engines (fx GD, PDFlib, libswf, etc) for output to several
* formats with a non-intersecting API.
* This class also handles coordinates and the correct managment of setting the
* correct coordinates on child elements.
* @author Jesper Veggerby <pear.nosey@veggerby.dk>
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
* @copyright 2003-2009 The PHP Group
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version Release: 0.8.0
* @link http://pear.php.net/package/Image_Graph
* Show generation time on graph
* Display errors on the canvas
var $_displayErrors = false;
* Image_Graph [Constructor].
* If passing the 3 parameters they are defined as follows:'
* $Graph = new Image_Graph(400, 300);
* or using the factory method:
* $Graph =& Image_Graph::factory('graph', array(400, 300));
* This causes a 'png' canvas to be created by default.
* Otherwise use a single parameter either as an associated array or passing
* the canvas along to the constructor:
* 1) Create a new canvas with the following parameters:
* 'canvas' - The canvas type, can be any of 'gd', 'jpg', 'png' or 'svg'
* (more to come) - if omitted the default is 'gd'
* 'width' - The width of the graph
* 'height' - The height of the graph
* An example of this usage:
* $Graph =& Image_Graph::factory('graph', array(array('width' => 400,
* 'height' => 300, 'canvas' => 'jpg')));
* NB! In th�s case remember the "double" array (see {@link Image_Graph::}
* 2) Use the canvas specified, pass a valid Image_Canvas as
* parameter. Remember to pass by reference, i. e. &$canvas, fx.:
* $Graph = new Image_Graph($Canvas);
* or using the factory method:
* $Graph =& Image_Graph::factory('graph', $Canvas));
* @param mixed $params The width of the graph, an indexed array
* describing a new canvas or a valid {@link Image_Canvas} object
* @param int $height The height of the graph in pixels
* @param bool $createTransparent Specifies whether the graph should be
* created with a transparent background (fx for PNG's - note: transparent
* PNG's is not supported by Internet Explorer!)
function Image_Graph($params, $height = false , $createTransparent = false )
if (defined('IMAGE_GRAPH_DEFAULT_CANVAS_TYPE')) {
$canvasType = IMAGE_GRAPH_DEFAULT_CANVAS_TYPE;
$canvasType = 'png'; // use GD as default, if nothing else is specified
if (isset ($params['canvas'])) {
$canvasType = $params['canvas'];
if (isset ($params['width'])) {
$width = $params['width'];
if (isset ($params['height'])) {
$height = $params['height'];
} elseif (is_a($params, 'Image_Canvas')) {
$this->_canvas = & $params;
$width = $this->_canvas->getWidth ();
$height = $this->_canvas->getHeight ();
if ($this->_canvas == null ) {
include_once 'Image/Canvas.php';
array ('width' => $width, 'height' => $height)
$this->_setCoords (0 , 0 , $width - 1 , $height - 1 );
* Gets the canvas for this graph.
* The canvas is set by either passing it to the constructor {@link }
* Image_Graph::ImageGraph()} or using the {@link Image_Graph::setCanvas()}
* @return Image_Canvas The canvas used by this graph
* Sets the canvas for this graph.
* Calling this method makes this graph use the newly specified canvas for
* handling output. This method should be called whenever multiple
* 'outputs' are required. Invoke this method after calls to {@link }
* Image_Graph:: done()} has been performed, to switch canvass.
* @param Image_Canvas &$canvas The new canvas
* @return Image_Canvas The new canvas
if (!is_a($this->_canvas, 'Image_Canvas')) {
return $this->_error ('The canvas introduced is not an Image_Canvas object');
$this->_canvas = & $canvas;
$this->_canvas->getWidth () - 1 ,
$this->_canvas->getHeight () - 1
* Gets a very precise timestamp
* @return The number of seconds to a lot of decimals
return ((float) $usec + (float) $sec);
* Gets the width of this graph.
* The width is returned as 'defined' by the canvas.
* @return int the width of this graph
return $this->_canvas->getWidth ();
* Gets the height of this graph.
* The height is returned as 'defined' by the canvas.
* @return int the height of this graph
return $this->_canvas->getHeight ();
* Enables displaying of errors on the output.
* Use this method to enforce errors to be displayed on the output. Calling
* this method makes PHP uses this graphs error handler as default {@link }
* Image_Graph::_default_error_handler()}.
$this->_displayErrors = true;
* Sets the log method for this graph.
* Use this method to enable logging. This causes any errors caught
* by either the error handler {@see Image_Graph::displayErrors()}
* or explicitly by calling {@link Image_Graph_Common::_error()} be
* logged using the specified logging method.
* If a filename is specified as log method, a Log object is created (using
* the 'file' handler), with a handle of 'Image_Graph Error Log'.
* Logging requires {@link Log}.
* @param mixed $log The log method, either a Log object or filename to log to
* Factory method to create Image_Graph objects.
* Used for 'lazy including', i.e. loading only what is necessary, when it
* is necessary. If only one parameter is required for the constructor of
* the class simply pass this parameter as the $params parameter, unless the
* parameter is an array or a reference to a value, in that case you must
* 'enclose' the parameter in an array. Similar if the constructor takes
* more than one parameter specify the parameters in an array, i.e
* Image_Graph::factory('MyClass', array($param1, $param2, &$param3));
* Variables that need to be passed by reference *must* have the &
* before the variable, i.e:
* Image_Graph::factory('line', &$Dataset);
* Image_graph::factory('bar', array(array(&$Dataset1, &$Dataset2),
* Class name can be either of the following:
* 1 The 'real' Image_Graph class name, i.e. Image_Graph_Plotarea or
* 2 Short class name (leave out Image_Graph) and retain case, i.e.
* Plotarea, Plot_Line *not* plot_line
* 3 Class name 'alias', the following are supported:
* 'plotarea' = Image_Graph_Plotarea
* 'line' = Image_Graph_Plot_Line
* 'area' = Image_Graph_Plot_Area
* 'bar' = Image_Graph_Plot_Bar
* 'pie' = Image_Graph_Plot_Pie
* 'radar' = Image_Graph_Plot_Radar
* 'step' = Image_Graph_Plot_Step
* 'impulse' = Image_Graph_Plot_Impulse
* 'dot' or 'scatter' = Image_Graph_Plot_Dot
* 'smooth_line' = Image_Graph_Plot_Smoothed_Line
* 'smooth_area' = Image_Graph_Plot_Smoothed_Area
* 'dataset' = Image_Graph_Dataset_Trivial
* 'random' = Image_Graph_Dataset_Random
* 'function' = Image_Graph_Dataset_Function
* 'vector' = Image_Graph_Dataset_VectorFunction
* 'category' = Image_Graph_Axis_Category
* 'axis' = Image_Graph_Axis
* 'axis_log' = Image_Graph_Axis_Logarithmic
* 'title' = Image_Graph_Title
* 'line_grid' = Image_Graph_Grid_Lines
* 'bar_grid' = Image_Graph_Grid_Bars
* 'polar_grid' = Image_Graph_Grid_Polar
* 'legend' = Image_Graph_Legend
* 'font' = Image_Graph_Font
* 'ttf_font' = Image_Graph_Font
* 'Image_Graph_Font_TTF' = Image_Graph_Font (to maintain BC with Image_Graph_Font_TTF)
* 'gradient' = Image_Graph_Fill_Gradient
* 'icon_marker' = Image_Graph_Marker_Icon
* 'value_marker' = Image_Graph_Marker_Value
* @param string $class The class for the new object
* @param mixed $params The paramaters to pass to the constructor
* @return object A new object for the class
function &factory($class, $params = null )
static $Image_Graph_classAliases = array (
'graph' => 'Image_Graph',
'plotarea' => 'Image_Graph_Plotarea',
'line' => 'Image_Graph_Plot_Line',
'area' => 'Image_Graph_Plot_Area',
'bar' => 'Image_Graph_Plot_Bar',
'smooth_line' => 'Image_Graph_Plot_Smoothed_Line',
'smooth_area' => 'Image_Graph_Plot_Smoothed_Area',
'pie' => 'Image_Graph_Plot_Pie',
'radar' => 'Image_Graph_Plot_Radar',
'step' => 'Image_Graph_Plot_Step',
'impulse' => 'Image_Graph_Plot_Impulse',
'dot' => 'Image_Graph_Plot_Dot',
'scatter' => 'Image_Graph_Plot_Dot',
'dataset' => 'Image_Graph_Dataset_Trivial',
'random' => 'Image_Graph_Dataset_Random',
'function' => 'Image_Graph_Dataset_Function',
'vector' => 'Image_Graph_Dataset_VectorFunction',
'category' => 'Image_Graph_Axis_Category',
'axis' => 'Image_Graph_Axis',
'axis_log' => 'Image_Graph_Axis_Logarithmic',
'title' => 'Image_Graph_Title',
'line_grid' => 'Image_Graph_Grid_Lines',
'bar_grid' => 'Image_Graph_Grid_Bars',
'polar_grid' => 'Image_Graph_Grid_Polar',
'legend' => 'Image_Graph_Legend',
'font' => 'Image_Graph_Font',
'ttf_font' => 'Image_Graph_Font',
'Image_Graph_Font_TTF' => 'Image_Graph_Font', // BC with Image_Graph_Font_TTF
'gradient' => 'Image_Graph_Fill_Gradient',
'icon_marker' => 'Image_Graph_Marker_Icon',
'value_marker' => 'Image_Graph_Marker_Value'
if (substr ($class, 0 , 11 ) != 'Image_Graph') {
if (isset ($Image_Graph_classAliases[$class])) {
$class = $Image_Graph_classAliases[$class];
$class = 'Image_Graph_' . $class;
include_once str_replace ('_', '/', $class) . '.php';
switch (count($params)) {
$obj = new $class($params);
* Factory method to create layouts.
* This method is used for easy creation, since using {@link Image_Graph::}
* factory()} does not work with passing newly created objects from
* Image_Graph::factory() as reference, this is something that is
* fortunately fixed in PHP5. Also used for 'lazy including', i.e. loading
* only what is necessary, when it is necessary.
* Use {@link Image_Graph::horizontal()} or {@link Image_Graph::vertical()}
* instead for easier access.
* @param mixed $layout The type of layout, can be either 'Vertical'
* or 'Horizontal' (case sensitive)
* @param Image_Graph_Element &$part1 The 1st part of the layout
* @param Image_Graph_Element &$part2 The 2nd part of the layout
* @param int $percentage The percentage of the layout to split at
* @return Image_Graph_Layout The newly created layout object
function &layoutFactory($layout, &$part1, &$part2, $percentage = 50 )
if (($layout != 'Vertical') && ($layout != 'Horizontal')) {
return $this->_error ('Layouts must be either \'Horizontal\' or \'Vertical\'');
if (!(is_a($part1, 'Image_Graph_Element'))) {
return $this->_error ('Part 1 is not a valid Image_Graph element');
if (!(is_a($part2, 'Image_Graph_Element'))) {
return $this->_error ('Part 2 is not a valid Image_Graph element');
if ((!is_numeric($percentage)) || ($percentage < 0 ) || ($percentage > 100 )) {
return $this->_error ('Percentage has to be a number between 0 and 100');
include_once " Image/Graph/Layout/$layout.php";
$class = " Image_Graph_Layout_$layout";
$obj = new $class($part1, $part2, $percentage);
* Factory method to create horizontal layout.
* See {@link Image_Graph::layoutFactory()}
* @param Image_Graph_Element &$part1 The 1st (left) part of the layout
* @param Image_Graph_Element &$part2 The 2nd (right) part of the layout
* @param int $percentage The percentage of the layout to split at
* (percentage of total height from the left side)
* @return Image_Graph_Layout The newly created layout object
function &horizontal(&$part1, &$part2, $percentage = 50 )
* Factory method to create vertical layout.
* See {@link Image_Graph::layoutFactory()}
* @param Image_Graph_Element &$part1 The 1st (top) part of the layout
* @param Image_Graph_Element &$part2 The 2nd (bottom) part of the layout
* @param int $percentage The percentage of the layout to split at
* (percentage of total width from the top edge)
* @return Image_Graph_Layout The newly created layout object
function &vertical(&$part1, &$part2, $percentage = 50 )
* The error handling routine set by set_error_handler().
* This method is used internaly by Image_Graph and PHP as a proxy for {@link }
* Image_Graph::_error()}.
* @param string $error_type The type of error being handled.
* @param string $error_msg The error message being handled.
* @param string $error_file The file in which the error occurred.
* @param integer $error_line The line in which the error occurred.
* @param string $error_context The context in which the error occurred.
function _default_error_handler ($error_type, $error_msg, $error_file, $error_line, $error_context)
" PHP $level: $error_msg" ,
'context' => $error_context
* Displays the errors on the error stack.
* Invoking this method cause all errors on the error stack to be displayed
* on the graph-output, by calling the {@link Image_Graph::_displayError()}
function _displayErrors ()
* Display an error from the error stack.
* This method writes error messages caught from the {@link Image_Graph::}
* _default_error_handler()} if {@Image_Graph::displayErrors()} was invoked,
* and the error explicitly set by the system using {@link }
* Image_Graph_Common::_error()}.
* @param int $x The horizontal position of the error message
* @param int $y The vertical position of the error message
* @param array $error The error context
function _displayError ($x, $y, $error)
* Outputs this graph using the canvas.
* This causes the graph to make all elements perform their output. Their
* result is 'written' to the output using the canvas, which also performs
* the actual output, fx. it being to a file or directly to the browser
* (in the latter case, the canvas will also make sure the correct HTTP
* headers are sent, making the browser handle the output correctly, if
* Parameters are the ones supported by the canvas, common ones are:
* 'filename' To output to a file instead of browser
* 'tohtml' Return a HTML string that encompasses the current graph/canvas - this
* implies an implicit save using the following parameters: 'filename' The "temporary"
* filename of the graph, 'filepath' A path in the file system where Image_Graph can
* store the output (this file must be in DOCUMENT_ROOT scope), 'urlpath' The URL that the
* 'filepath' corresponds to (i.e. filepath + filename must be reachable from a browser using
* 'output' = 'none' Forces the graph to be drawn, but no output is sent to
* the browser. This allows working with an existing canvas after graphs has
* @param mixed $param The output parameters to pass to the canvas
* @return bool Was the output 'good' (true) or 'bad' (false).
function done($param = false )
$result = $this->_reset ();
if (PEAR ::isError ($result)) {
return $this->_done ($param);
* Outputs this graph using the canvas.
* This causes the graph to make all elements perform their output. Their
* result is 'written' to the output using the canvas, which also performs
* the actual output, fx. it being to a file or directly to the browser
* (in the latter case, the canvas will also make sure the correct HTTP
* headers are sent, making the browser handle the output correctly, if
* @param mixed $param The output parameters to pass to the canvas
* @return bool Was the output 'good' (true) or 'bad' (false).
function _done ($param = false )
$timeStart = $this->_getMicroTime ();
$result = $this->_updateCoords ();
if (PEAR ::isError ($result)) {
if ($this->_getBackground ()) {
$this->_canvas->rectangle (
$result = parent ::_done ();
if (PEAR ::isError ($result)) {
if ($this->_displayErrors) {
$timeEnd = $this->_getMicroTime ();
|| ((isset ($param['showtime'])) && ($param['showtime'] === true ))
$text = 'Generated in ' .
sprintf('%0.3f', $timeEnd - $timeStart) . ' sec';
if ((!isset ($param['output'])) || ($param['output'] !== 'none')) {
if (isset ($param['filename'])) {
if ((isset ($param['tohtml'])) && ($param['tohtml'])) {
return $this->_canvas->toHtml ($param);
return $this->_canvas->save ($param);
return $this->_canvas->show ($param);
Documentation generated on Tue, 05 Oct 2010 16:00:35 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.
|