diff --git a/pandora_console/ChangeLog b/pandora_console/ChangeLog index b1bf9add4a..bfc4d0fb4e 100644 --- a/pandora_console/ChangeLog +++ b/pandora_console/ChangeLog @@ -1,3 +1,20 @@ +2007-06-02 Raul Mateos + + * include/styles/pandora.css: Updated. + + * include/styles/pandora_minimal.css: New file for install and graphs. + + * include/config.inc.php: Updated build. Updated attachment directory. + + * install.php: Added some text to clarify use of config directory in + step 3. Now we use the pandora_mininmal.css file. Updated logo. Closed + some HTML tags. + + * reporting/stat_win.php: Now we use the pandora_minimal.css file. Closed + some HTML tags. Added title. + + * reporting/Image/*.php: Converted end-line Windows format to Unix. + 2007-05-31 Sancho Lerena * fgraph.php: Small improvements in combined graphs. diff --git a/pandora_console/include/config.inc.php b/pandora_console/include/config.inc.php index 6f3286ef50..2f78f5f168 100644 --- a/pandora_console/include/config.inc.php +++ b/pandora_console/include/config.inc.php @@ -21,7 +21,7 @@ //Pandora Version if (!isset($build_version)) - $build_version="PC070529"; + $build_version="PC070602"; if (!isset($pandora_version)) $pandora_version="v1.3 devel"; @@ -43,7 +43,7 @@ error_reporting(E_ALL); //This is directory where placed "attachment" directory, to upload files stores. // This MUST be writtable by http server user, and should be in pandora root. // Please append "/" to the end. -$attachment_store=$config_homedir; +$attachment_store=$config_homedir."attachment/"; // Default font used for graphics (a Free TrueType font included with Pandora FMS) $config_fontpath = $config_homedir."reporting/FreeSans.ttf"; diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index 470b361f17..044d76d0ff 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -315,7 +315,7 @@ td.datos_jus, td.datos2_jus { text-align: center; } .f9, .f9i, .f9b, td.f9, td.f9i, td.datosf9, td.datos2f9 { - font-size: 6pt; + font-size: 6.5pt; } .f9i, .redi { font-style: italic; diff --git a/pandora_console/install.php b/pandora_console/install.php index 5fdb4eb5d8..d586a25afc 100644 --- a/pandora_console/install.php +++ b/pandora_console/install.php @@ -33,7 +33,7 @@ - + @@ -165,7 +165,7 @@ function install_step1() { echo "
-

+
@@ -200,7 +200,7 @@ function install_step2() { echo "
-

+
"; @@ -232,12 +232,14 @@ function install_step3() {

Environment and database setup

- This wizard will create your Pandora FMS database, and populate it with all the data needed to run for the first time. - You need a privileged user to create database schema, this is usually root user. - Information about root user will not be used or stored anymore. + This wizard will create your Pandora FMS database, and populate it with all the data needed to run for the first time.

- Now, please, complete all details to configure your database and enviroment setup. + You need a privileged user to create database schema, this is usually root user. + Information about root user will not be used or stored anymore. +

+

+ Now, please, complete all details to configure your database and enviroment setup.

NOTICE that database will be destroyed if it already exists! @@ -255,12 +257,12 @@ function install_step3() {

DB Name (pandora by default)
-
Full path to HTTP publication directory.
- For example /var/www/pandora_console/ +
Full path to HTTP publication directory
+ For example /var/www/pandora_console/. Needed for graphs and attachments.
-
Full local URL to Pandora FMS Console.
+
Full local URL to Pandora FMS Console
For example http://localhost/pandora_console
@@ -269,7 +271,7 @@ function install_step3() {
-

+
@@ -368,7 +370,7 @@ $BASE_URL="'.$url.'"; // Base URL } echo "
-

+
@@ -408,7 +410,7 @@ function install_step5() {

Click here to access to your Pandora FMS console

-

+

@@ -441,3 +443,5 @@ if (! isset($_GET["step"])){ } ?> + + diff --git a/pandora_console/reporting/Image/Canvas.php b/pandora_console/reporting/Image/Canvas.php index 5c424f8b46..cd88e9699f 100644 --- a/pandora_console/reporting/Image/Canvas.php +++ b/pandora_console/reporting/Image/Canvas.php @@ -1,711 +1,711 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Canvas.php,v 1.5 2005/09/30 18:59:35 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Specfies the path to the system location of font files. - * - * Remember trailing slash! - * - * This is set by default on Windows systems to %SystemRoot%\Fonts\ - */ -if (!defined('IMAGE_CANVAS_SYSTEM_FONT_PATH')) { - if (isset($_SERVER['SystemRoot'])) { - define('IMAGE_CANVAS_SYSTEM_FONT_PATH', $_SERVER['SystemRoot'] . '/Fonts/'); - } else { - /** - * @ignore - */ - define('IMAGE_CANVAS_SYSTEM_FONT_PATH', ''); - } -} - -/** - * Class for handling different output formats - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @abstract - */ -class Image_Canvas -{ - - /** - * The leftmost pixel of the element on the canvas - * @var int - * @access private - */ - var $_left = 0; - - /** - * The topmost pixel of the element on the canvas - * @var int - * @access private - */ - var $_top = 0; - - /** - * The width of the graph - * @var int - * @access private - */ - var $_width = 0; - - /** - * The height of the graph - * @var int - * @access private - */ - var $_height = 0; - - /** - * Polygon vertex placeholder - * @var array - * @access private - */ - var $_polygon = array(); - - /** - * The thickness of the line(s) - * @var int - * @access private - */ - var $_thickness = 1; - - /** - * The line style - * @var mixed - * @access private - */ - var $_lineStyle = 'transparent'; - - /** - * The fill style - * @var mixed - * @access private - */ - var $_fillStyle = 'transparent'; - - /** - * The font options - * @var array - * @access private - */ - var $_font = array(); - - /** - * The default font - * @var array - * @access private - */ - var $_defaultFont = array('name' => 'Courier New', 'color' => 'black', 'size' => 9); - - /** - * Create the canvas. - * - * Parameters available: - * - * 'width' The width of the graph on the canvas - * - * 'height' The height of the graph on the canvas - * - * 'left' The left offset of the graph on the canvas - * - * 'top' The top offset of the graph on the canvas - * - * @param array $params Parameter array - * @abstract - */ - function Image_Canvas($params) - { - if (isset($params['left'])) { - $this->_left = $params['left']; - } - - if (isset($params['top'])) { - $this->_top = $params['top']; - } - - if (isset($params['width'])) { - $this->_width = $params['width']; - } - - if (isset($params['height'])) { - $this->_height = $params['height']; - } - - $this->setDefaultFont($this->_defaultFont); - } - - /** - * Get the x-point from the relative to absolute coordinates - * - * @param float $x The relative x-coordinate (in percentage of total width) - * @return float The x-coordinate as applied to the canvas - * @access private - */ - function _getX($x) - { - return floor($this->_left + $x); - } - - /** - * Get the y-point from the relative to absolute coordinates - * - * @param float $y The relative y-coordinate (in percentage of total width) - * @return float The y-coordinate as applied to the canvas - * @access private - */ - function _getY($y) - { - return floor($this->_top + $y); - } - - /** - * Get the width of the canvas - * - * @return int The width - */ - function getWidth() - { - return $this->_width; - } - - /** - * Get the height of the canvas - * - * @return int The height - */ - function getHeight() - { - return $this->_height; - } - - /** - * Sets the thickness of the line(s) to be drawn - * - * @param int $thickness The actual thickness (in pixels) - */ - function setLineThickness($thickness) - { - $this->_thickness = $thickness; - } - - /** - * Sets the color of the line(s) to be drawn - * - * @param mixed $color The color of the line - */ - function setLineColor($color) - { - $this->_lineStyle = $color; - } - - /** - * Sets the style of the filling of drawn objects. - * - * This method gives simple access to setFillColor(), setFillImage() and - * setGradientFill() - * - * @param mixed $fill The fill style - */ - function setFill($fill) - { - if (is_array($fill)) { - $this->setGradientFill($fill); - } elseif (file_exists($fill)) { - $this->setFillImage($fill); - } else { - $this->setFillColor($fill); - } - } - - /** - * Sets the color of the filling of drawn objects - * - * @param mixed $color The fill color - */ - function setFillColor($color) - { - $this->_fillStyle = $color; - } - - /** - * Sets an image that should be used for filling - * - * @param string $filename The filename of the image to fill with - */ - function setFillImage($filename) - { - } - - /** - * Sets a gradient fill - * - * @param array $gradient Gradient fill options - */ - function setGradientFill($gradient) - { - $this->_fillStyle = $gradient; - } - - /** - * Sets the font options. - * - * The $font array may have the following entries: - * - * 'name' The name of the font. This name must either be supported - * natively by the canvas or mapped to a font using the font-mapping scheme - * - * 'size' Size in pixels - * - * 'angle' The angle with which to write the text - * - * @param array $fontOptions The font options. - */ - function setFont($fontOptions) - { - $this->_font = $fontOptions; - - if (!isset($this->_font['color'])) { - $this->_font['color'] = 'black'; - } - - if (!(isset($this->_font['angle'])) || ($this->_font['angle'] === false)) { - $this->_font['angle'] = 0; - } - - if (isset($this->_font['angle'])) { - if ((($this->_font['angle'] > 45) && ($this->_font['angle'] < 135)) || - (($this->_font['angle'] > 225) && ($this->_font['angle'] < 315)) - ) { - $this->_font['vertical'] = true; - } - } - - if ((!isset($this->_font['file'])) && (isset($this->_font['name']))) { - include_once 'Image/Canvas/Tool.php'; - $this->_font['file'] = Image_Canvas_Tool::fontMap($this->_font['name']); - } - } - function setClipping($params = false) - { - } - /** - * Sets the default font options. - * - * The $font array may have the following entries: - * - * 'name' The name of the font. This name must either be supported - * natively by the canvas or mapped to a font using the font-mapping scheme - * - * 'size' Size in pixels - * - * 'angle' The angle with which to write the text - * - * @param array $fontOptions The font options. - */ - function setDefaultFont($fontOptions) - { - $this->setFont($fontOptions); - $this->_defaultFont = $this->_font; - } - - /** - * Resets the canvas. - * - * Includes fillstyle, linestyle, thickness and polygon - * - * @access private - */ - function _reset() - { - $this->_lineStyle = false; - $this->_fillStyle = false; - $this->_thickness = 1; - $this->_polygon = array(); - $this->_font = $this->_defaultFont; - } - - /** - * Draw a line end - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * 'end': string The end type of the end - * 'angle': int [optional] The angle with which to draw the end - * @param array $params Parameter array - */ - function drawEnd($params) - { - } - - /** - * Draw a line - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'end0': string [optional] The end type of end0 (the start) - * 'end1': string [optional] The end type of end1 (the end) - * 'size0': int [optional] The size of end0 - * 'size1': int [optional] The size of end1 - * 'color': mixed [optional] The line color - * @param array $params Parameter array - */ - function line($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - if (isset($params['end0'])) { - $angle = Image_Canvas_Tool::getAngle($x1, $y1, $x0, $y0); - $this->drawEnd( - array( - 'end' => $params['end0'], - 'x' => $params['x0'], - 'y' => $params['y0'], - 'angle' => $angle, - 'color' => (isset($params['color0']) ? $params['color0'] : false), - 'size' => $params['size0'] - ) - ); - } - if (isset($params['end1'])) { - $angle = Image_Canvas_Tool::getAngle($x0, $y0, $x1, $y1); - //print "
"; var_dump($params, $angle); print "
"; - $this->drawEnd( - array( - 'end' => $params['end1'], - 'x' => $params['x1'], - 'y' => $params['y1'], - 'angle' => $angle, - 'color' => (isset($params['color1']) ? $params['color1'] : false), - 'size' => $params['size1'] - ) - ); - } - $this->_reset(); - } - - /** - * Adds vertex to a polygon - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * @param array $params Parameter array - */ - function addVertex($params) - { - $params['X'] = $this->_getX($params['x']); - $params['Y'] = $this->_getY($params['y']); - $this->_polygon[] = $params; - } - - /** - * Adds "splined" vertex to a polygon - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * 'p1x': int X Control point 1 - * 'p1y': int Y Control point 1 - * 'p2x': int X Control point 2 - * 'p2y': int Y Control point 2 - * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * @param array $params Parameter array - */ - function addSpline($params) - { - $params['X'] = $this->_getX($params['x']); - $params['Y'] = $this->_getY($params['y']); - $params['P1X'] = $this->_getX($params['p1x']); - $params['P1Y'] = $this->_getY($params['p1y']); - $params['P2X'] = $this->_getX($params['p2x']); - $params['P2Y'] = $this->_getY($params['p2y']); - $this->_polygon[] = $params; - } - - /** - * Draws a polygon - * - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params) - { - $this->_reset(); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - $this->_reset(); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - $this->_reset(); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - $this->_reset(); - } - - /** - * Get the width of a text, - * - * @param string $text The text to get the width of - * @return int The width of the text - */ - function textWidth($text) - { - } - - /** - * Get the height of a text, - * - * @param string $text The text to get the height of - * @return int The height of the text - */ - function textHeight($text) - { - } - - /** - * Writes text - * - * Parameter array: - * 'x': int X-point of text - * 'y': int Y-point of text - * 'text': string The text to add - * 'alignment': array [optional] Alignment - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - $this->_reset(); - } - - /** - * Overlay image - * - * Parameter array: - * 'x': int X-point of overlayed image - * 'y': int Y-point of overlayed image - * 'filename': string The filename of the image to overlay - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * 'alignment': array [optional] Alignment - */ - function image($params) - { - } - - /** - * Start a group. - * - * What this does, depends on the canvas/format. - * - * @param string $name The name of the group - */ - function startGroup($name = false) - { - } - - /** - * End the "current" group. - * - * What this does, depends on the canvas/format. - */ - function endGroup() - { - } - - /** - * Output the result of the canvas to the browser - * - * @param array $params Parameter array, the contents and meaning depends on the actual Canvas - * @abstract - */ - function show($params = false) - { - if ($params === false) { - header('Expires: Tue, 2 Jul 1974 17:41:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // always modified - header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1 - header('Pragma: no-cache'); - } - } - - /** - * Save the result of the canvas to a file - * - * Parameter array: - * 'filename': string The file to output to - * @param array $params Parameter array, the contents and meaning depends on the actual Canvas - * @abstract - */ - function save($params = false) - { - } - - /** - * Get a canvas specific HTML tag. - * - * This method implicitly saves the canvas to the filename in the - * filesystem path specified and parses it as URL specified by URL path - * - * Parameter array: - * 'filename': string - * 'filepath': string Path to the file on the file system. Remember the final slash - * 'urlpath': string Path to the file available through an URL. Remember the final slash - */ - function toHtml($params) - { - $this->save(array('filename' => $params['filepath'] . $params['filename'])); - } - - /** - * Canvas factory method. - * - * Supported canvass are: - * - * 'png': output in PNG format (using GD) - * - * 'jpg': output in JPEG format (using GD) - * - * 'pdf': output in PDF format (using PDFlib) - * - * 'svg': output in SVG format - * - * 'imagemap': output as a html image map - * - * An example of usage: - * - * - * 800, 'height' => 600, 'antialias' => 'native') - * ); - * ?> - * - * - * @param string $canvas The canvas type - * @param array $params The parameters for the canvas constructor - * @return Image_Canvas The newly created canvas - * @static - */ - function &factory($canvas, $params) - { - $canvas = strtoupper($canvas); - - if (($canvas == 'PNG') || ($canvas == 'GD')) { - $canvas = 'GD_PNG'; - } - if (($canvas == 'JPG') || ($canvas == 'JPEG')) { - $canvas = 'GD_JPG'; - } - - if ($canvas == 'IMAGEMAP') { - $canvas = 'ImageMap'; - } - - $class = 'Image_Canvas_'. $canvas; - include_once 'Image/Canvas/'. str_replace('_', '/', $canvas) . '.php'; - - $obj =& new $class($params); - return $obj; - } - -} - -?> + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Canvas.php,v 1.5 2005/09/30 18:59:35 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Specfies the path to the system location of font files. + * + * Remember trailing slash! + * + * This is set by default on Windows systems to %SystemRoot%\Fonts\ + */ +if (!defined('IMAGE_CANVAS_SYSTEM_FONT_PATH')) { + if (isset($_SERVER['SystemRoot'])) { + define('IMAGE_CANVAS_SYSTEM_FONT_PATH', $_SERVER['SystemRoot'] . '/Fonts/'); + } else { + /** + * @ignore + */ + define('IMAGE_CANVAS_SYSTEM_FONT_PATH', ''); + } +} + +/** + * Class for handling different output formats + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @abstract + */ +class Image_Canvas +{ + + /** + * The leftmost pixel of the element on the canvas + * @var int + * @access private + */ + var $_left = 0; + + /** + * The topmost pixel of the element on the canvas + * @var int + * @access private + */ + var $_top = 0; + + /** + * The width of the graph + * @var int + * @access private + */ + var $_width = 0; + + /** + * The height of the graph + * @var int + * @access private + */ + var $_height = 0; + + /** + * Polygon vertex placeholder + * @var array + * @access private + */ + var $_polygon = array(); + + /** + * The thickness of the line(s) + * @var int + * @access private + */ + var $_thickness = 1; + + /** + * The line style + * @var mixed + * @access private + */ + var $_lineStyle = 'transparent'; + + /** + * The fill style + * @var mixed + * @access private + */ + var $_fillStyle = 'transparent'; + + /** + * The font options + * @var array + * @access private + */ + var $_font = array(); + + /** + * The default font + * @var array + * @access private + */ + var $_defaultFont = array('name' => 'Courier New', 'color' => 'black', 'size' => 9); + + /** + * Create the canvas. + * + * Parameters available: + * + * 'width' The width of the graph on the canvas + * + * 'height' The height of the graph on the canvas + * + * 'left' The left offset of the graph on the canvas + * + * 'top' The top offset of the graph on the canvas + * + * @param array $params Parameter array + * @abstract + */ + function Image_Canvas($params) + { + if (isset($params['left'])) { + $this->_left = $params['left']; + } + + if (isset($params['top'])) { + $this->_top = $params['top']; + } + + if (isset($params['width'])) { + $this->_width = $params['width']; + } + + if (isset($params['height'])) { + $this->_height = $params['height']; + } + + $this->setDefaultFont($this->_defaultFont); + } + + /** + * Get the x-point from the relative to absolute coordinates + * + * @param float $x The relative x-coordinate (in percentage of total width) + * @return float The x-coordinate as applied to the canvas + * @access private + */ + function _getX($x) + { + return floor($this->_left + $x); + } + + /** + * Get the y-point from the relative to absolute coordinates + * + * @param float $y The relative y-coordinate (in percentage of total width) + * @return float The y-coordinate as applied to the canvas + * @access private + */ + function _getY($y) + { + return floor($this->_top + $y); + } + + /** + * Get the width of the canvas + * + * @return int The width + */ + function getWidth() + { + return $this->_width; + } + + /** + * Get the height of the canvas + * + * @return int The height + */ + function getHeight() + { + return $this->_height; + } + + /** + * Sets the thickness of the line(s) to be drawn + * + * @param int $thickness The actual thickness (in pixels) + */ + function setLineThickness($thickness) + { + $this->_thickness = $thickness; + } + + /** + * Sets the color of the line(s) to be drawn + * + * @param mixed $color The color of the line + */ + function setLineColor($color) + { + $this->_lineStyle = $color; + } + + /** + * Sets the style of the filling of drawn objects. + * + * This method gives simple access to setFillColor(), setFillImage() and + * setGradientFill() + * + * @param mixed $fill The fill style + */ + function setFill($fill) + { + if (is_array($fill)) { + $this->setGradientFill($fill); + } elseif (file_exists($fill)) { + $this->setFillImage($fill); + } else { + $this->setFillColor($fill); + } + } + + /** + * Sets the color of the filling of drawn objects + * + * @param mixed $color The fill color + */ + function setFillColor($color) + { + $this->_fillStyle = $color; + } + + /** + * Sets an image that should be used for filling + * + * @param string $filename The filename of the image to fill with + */ + function setFillImage($filename) + { + } + + /** + * Sets a gradient fill + * + * @param array $gradient Gradient fill options + */ + function setGradientFill($gradient) + { + $this->_fillStyle = $gradient; + } + + /** + * Sets the font options. + * + * The $font array may have the following entries: + * + * 'name' The name of the font. This name must either be supported + * natively by the canvas or mapped to a font using the font-mapping scheme + * + * 'size' Size in pixels + * + * 'angle' The angle with which to write the text + * + * @param array $fontOptions The font options. + */ + function setFont($fontOptions) + { + $this->_font = $fontOptions; + + if (!isset($this->_font['color'])) { + $this->_font['color'] = 'black'; + } + + if (!(isset($this->_font['angle'])) || ($this->_font['angle'] === false)) { + $this->_font['angle'] = 0; + } + + if (isset($this->_font['angle'])) { + if ((($this->_font['angle'] > 45) && ($this->_font['angle'] < 135)) || + (($this->_font['angle'] > 225) && ($this->_font['angle'] < 315)) + ) { + $this->_font['vertical'] = true; + } + } + + if ((!isset($this->_font['file'])) && (isset($this->_font['name']))) { + include_once 'Image/Canvas/Tool.php'; + $this->_font['file'] = Image_Canvas_Tool::fontMap($this->_font['name']); + } + } + function setClipping($params = false) + { + } + /** + * Sets the default font options. + * + * The $font array may have the following entries: + * + * 'name' The name of the font. This name must either be supported + * natively by the canvas or mapped to a font using the font-mapping scheme + * + * 'size' Size in pixels + * + * 'angle' The angle with which to write the text + * + * @param array $fontOptions The font options. + */ + function setDefaultFont($fontOptions) + { + $this->setFont($fontOptions); + $this->_defaultFont = $this->_font; + } + + /** + * Resets the canvas. + * + * Includes fillstyle, linestyle, thickness and polygon + * + * @access private + */ + function _reset() + { + $this->_lineStyle = false; + $this->_fillStyle = false; + $this->_thickness = 1; + $this->_polygon = array(); + $this->_font = $this->_defaultFont; + } + + /** + * Draw a line end + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * 'end': string The end type of the end + * 'angle': int [optional] The angle with which to draw the end + * @param array $params Parameter array + */ + function drawEnd($params) + { + } + + /** + * Draw a line + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'end0': string [optional] The end type of end0 (the start) + * 'end1': string [optional] The end type of end1 (the end) + * 'size0': int [optional] The size of end0 + * 'size1': int [optional] The size of end1 + * 'color': mixed [optional] The line color + * @param array $params Parameter array + */ + function line($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + if (isset($params['end0'])) { + $angle = Image_Canvas_Tool::getAngle($x1, $y1, $x0, $y0); + $this->drawEnd( + array( + 'end' => $params['end0'], + 'x' => $params['x0'], + 'y' => $params['y0'], + 'angle' => $angle, + 'color' => (isset($params['color0']) ? $params['color0'] : false), + 'size' => $params['size0'] + ) + ); + } + if (isset($params['end1'])) { + $angle = Image_Canvas_Tool::getAngle($x0, $y0, $x1, $y1); + //print "
"; var_dump($params, $angle); print "
"; + $this->drawEnd( + array( + 'end' => $params['end1'], + 'x' => $params['x1'], + 'y' => $params['y1'], + 'angle' => $angle, + 'color' => (isset($params['color1']) ? $params['color1'] : false), + 'size' => $params['size1'] + ) + ); + } + $this->_reset(); + } + + /** + * Adds vertex to a polygon + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * @param array $params Parameter array + */ + function addVertex($params) + { + $params['X'] = $this->_getX($params['x']); + $params['Y'] = $this->_getY($params['y']); + $this->_polygon[] = $params; + } + + /** + * Adds "splined" vertex to a polygon + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * 'p1x': int X Control point 1 + * 'p1y': int Y Control point 1 + * 'p2x': int X Control point 2 + * 'p2y': int Y Control point 2 + * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * @param array $params Parameter array + */ + function addSpline($params) + { + $params['X'] = $this->_getX($params['x']); + $params['Y'] = $this->_getY($params['y']); + $params['P1X'] = $this->_getX($params['p1x']); + $params['P1Y'] = $this->_getY($params['p1y']); + $params['P2X'] = $this->_getX($params['p2x']); + $params['P2Y'] = $this->_getY($params['p2y']); + $this->_polygon[] = $params; + } + + /** + * Draws a polygon + * + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params) + { + $this->_reset(); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + $this->_reset(); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + $this->_reset(); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + $this->_reset(); + } + + /** + * Get the width of a text, + * + * @param string $text The text to get the width of + * @return int The width of the text + */ + function textWidth($text) + { + } + + /** + * Get the height of a text, + * + * @param string $text The text to get the height of + * @return int The height of the text + */ + function textHeight($text) + { + } + + /** + * Writes text + * + * Parameter array: + * 'x': int X-point of text + * 'y': int Y-point of text + * 'text': string The text to add + * 'alignment': array [optional] Alignment + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + $this->_reset(); + } + + /** + * Overlay image + * + * Parameter array: + * 'x': int X-point of overlayed image + * 'y': int Y-point of overlayed image + * 'filename': string The filename of the image to overlay + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * 'alignment': array [optional] Alignment + */ + function image($params) + { + } + + /** + * Start a group. + * + * What this does, depends on the canvas/format. + * + * @param string $name The name of the group + */ + function startGroup($name = false) + { + } + + /** + * End the "current" group. + * + * What this does, depends on the canvas/format. + */ + function endGroup() + { + } + + /** + * Output the result of the canvas to the browser + * + * @param array $params Parameter array, the contents and meaning depends on the actual Canvas + * @abstract + */ + function show($params = false) + { + if ($params === false) { + header('Expires: Tue, 2 Jul 1974 17:41:00 GMT'); // Date in the past + header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // always modified + header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1 + header('Pragma: no-cache'); + } + } + + /** + * Save the result of the canvas to a file + * + * Parameter array: + * 'filename': string The file to output to + * @param array $params Parameter array, the contents and meaning depends on the actual Canvas + * @abstract + */ + function save($params = false) + { + } + + /** + * Get a canvas specific HTML tag. + * + * This method implicitly saves the canvas to the filename in the + * filesystem path specified and parses it as URL specified by URL path + * + * Parameter array: + * 'filename': string + * 'filepath': string Path to the file on the file system. Remember the final slash + * 'urlpath': string Path to the file available through an URL. Remember the final slash + */ + function toHtml($params) + { + $this->save(array('filename' => $params['filepath'] . $params['filename'])); + } + + /** + * Canvas factory method. + * + * Supported canvass are: + * + * 'png': output in PNG format (using GD) + * + * 'jpg': output in JPEG format (using GD) + * + * 'pdf': output in PDF format (using PDFlib) + * + * 'svg': output in SVG format + * + * 'imagemap': output as a html image map + * + * An example of usage: + * + * + * 800, 'height' => 600, 'antialias' => 'native') + * ); + * ?> + * + * + * @param string $canvas The canvas type + * @param array $params The parameters for the canvas constructor + * @return Image_Canvas The newly created canvas + * @static + */ + function &factory($canvas, $params) + { + $canvas = strtoupper($canvas); + + if (($canvas == 'PNG') || ($canvas == 'GD')) { + $canvas = 'GD_PNG'; + } + if (($canvas == 'JPG') || ($canvas == 'JPEG')) { + $canvas = 'GD_JPG'; + } + + if ($canvas == 'IMAGEMAP') { + $canvas = 'ImageMap'; + } + + $class = 'Image_Canvas_'. $canvas; + include_once 'Image/Canvas/'. str_replace('_', '/', $canvas) . '.php'; + + $obj =& new $class($params); + return $obj; + } + +} + +?> diff --git a/pandora_console/reporting/Image/Canvas/Color.php b/pandora_console/reporting/Image/Canvas/Color.php index c062451efd..0e5bc2ec6e 100644 --- a/pandora_console/reporting/Image/Canvas/Color.php +++ b/pandora_console/reporting/Image/Canvas/Color.php @@ -1,182 +1,182 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: Color.php,v 1.3 2005/09/14 17:25:46 nosey Exp $ - -/** -* Class for color-handling -* -* @author Stefan Neufeind -* @package Image_Canvas -* @category images -* @license The PHP License, version 2.02 -*/ - -/** -* Color class to be extended; from package PEAR::Image_Color -*/ -require_once 'Image/Color.php'; - -/** -* Class for color-handling -* -* This is used to extend the functionality of the current PEAR::Image_Color v0.4. -* I hope to be allowed to incorporate some of the improvements in a new Image_Color release. -* -* @author Stefan Neufeind -* @package Image_Canvas -* @access public -*/ -class Image_Canvas_Color extends Image_Color -{ - /** - * Allocates a color in the given image. - * - * Userdefined color specifications get translated into - * an array of rgb values. - * - * @param resource GD-resource - * @param mixed any color representation supported by color2RGB() - * @return resource Image color handle - * @see color2RGB() - * @access public - * @static - */ - function allocateColor(&$img, $color) - { - $color = Image_Canvas_Color::color2RGB($color); - - if (($color[3] == 255) || (!function_exists("imagecolorallocatealpha"))) { - return imagecolorallocate($img, $color[0], $color[1], $color[2]); - } else { - return imagecolorallocatealpha($img, $color[0], $color[1], $color[2], 127-round(($color[3]*127)/255)); - } - } - - /** - * Convert any color-representation into an array of 4 ints (RGBA). - * - * Userdefined color specifications get translated into - * an array of rgb values. - * - * @param mixed any color representation supported by Image_Canvas_Color::color2RGB() - * @return array Array of 4 ints (RGBA-representation) - * @access public - * @static - */ - function color2RGB($color) - { - if (is_array($color)) { - if (!is_numeric($color[0])) { - return null; // error - } - if (count($color) == 3) { // assume RGB-color - - // 255 = alpha-value; full opaque - return array((int) $color[0], - (int) $color[1], - (int) $color[2], - 255); - } - if (count($color) == 4) { // assume RGBA-color - - // 255 = alpha-value; full opaque - return array((int) $color[0], - (int) $color[1], - (int) $color[2], - (int) $color[3]); - } - return null; // error - } elseif (is_string($color)) { - $alphaPos = strpos($color, '@'); - if ($alphaPos === false) { - $alpha = 255; - } else { - $alphaFloat = (float) substr($color, $alphaPos+1); - // restrict to range 0..1 - $alphaFloat = max(min($alphaFloat, 1), 0); - $alpha = (int) round((float) 255 * $alphaFloat); - $color = substr($color, 0, $alphaPos); - } - if ($color[0] == '#') { // hex-color given, e.g. #FFB4B4 - $tempColor = parent::hex2rgb($color); - return array((int) $tempColor[0], - (int) $tempColor[1], - (int) $tempColor[2], - $alpha); - } - if (strpos($color,'%') !== false) { - $tempColor = parent::percentageColor2RGB($color); - return array((int) $tempColor[0], - (int) $tempColor[1], - (int) $tempColor[2], - $alpha); - } else { - $tempColor = parent::namedColor2RGB($color); - return array((int) $tempColor[0], - (int) $tempColor[1], - (int) $tempColor[2], - $alpha); - } - } else { - return null; // error - } - } - - /** - * getRange - * Given a degree, you can get the range of colors between one color and - * another color. - * - * @access public - * @param string How much each 'step' between the colors we should take. - * @return array Returns an array of all the colors, one element for each color. - */ - function getRange ($degrees) - { - $tempColors = parent::getRange($degrees); - - // now add alpha-channel information - $steps = count($tempColors); - for($counter=0;$counter<$steps;$counter++) { - $tempColors[$counter] = parent::hex2rgb($tempColors[$counter]); - unset($tempColors[$counter]['hex']); - $tempColors[$counter][3] = (int) round( - (((float) $this->color1[3]*($steps-$counter))+ - ((float) $this->color2[3]*($counter)) - ) / $steps - ); - } - - return $tempColors; - } - - /** - * Internal method to correctly set the colors. - * - * @param mixed color 1 - * @param mixed color 2 - * @access private - */ - function _setColors ( $col1, $col2 ) - { - $this->color1 = Image_Canvas_Color::color2RGB($col1); - $this->color2 = Image_Canvas_Color::color2RGB($col2); - } -} + | +// +----------------------------------------------------------------------+ +// +// $Id: Color.php,v 1.3 2005/09/14 17:25:46 nosey Exp $ + +/** +* Class for color-handling +* +* @author Stefan Neufeind +* @package Image_Canvas +* @category images +* @license The PHP License, version 2.02 +*/ + +/** +* Color class to be extended; from package PEAR::Image_Color +*/ +require_once 'Image/Color.php'; + +/** +* Class for color-handling +* +* This is used to extend the functionality of the current PEAR::Image_Color v0.4. +* I hope to be allowed to incorporate some of the improvements in a new Image_Color release. +* +* @author Stefan Neufeind +* @package Image_Canvas +* @access public +*/ +class Image_Canvas_Color extends Image_Color +{ + /** + * Allocates a color in the given image. + * + * Userdefined color specifications get translated into + * an array of rgb values. + * + * @param resource GD-resource + * @param mixed any color representation supported by color2RGB() + * @return resource Image color handle + * @see color2RGB() + * @access public + * @static + */ + function allocateColor(&$img, $color) + { + $color = Image_Canvas_Color::color2RGB($color); + + if (($color[3] == 255) || (!function_exists("imagecolorallocatealpha"))) { + return imagecolorallocate($img, $color[0], $color[1], $color[2]); + } else { + return imagecolorallocatealpha($img, $color[0], $color[1], $color[2], 127-round(($color[3]*127)/255)); + } + } + + /** + * Convert any color-representation into an array of 4 ints (RGBA). + * + * Userdefined color specifications get translated into + * an array of rgb values. + * + * @param mixed any color representation supported by Image_Canvas_Color::color2RGB() + * @return array Array of 4 ints (RGBA-representation) + * @access public + * @static + */ + function color2RGB($color) + { + if (is_array($color)) { + if (!is_numeric($color[0])) { + return null; // error + } + if (count($color) == 3) { // assume RGB-color + + // 255 = alpha-value; full opaque + return array((int) $color[0], + (int) $color[1], + (int) $color[2], + 255); + } + if (count($color) == 4) { // assume RGBA-color + + // 255 = alpha-value; full opaque + return array((int) $color[0], + (int) $color[1], + (int) $color[2], + (int) $color[3]); + } + return null; // error + } elseif (is_string($color)) { + $alphaPos = strpos($color, '@'); + if ($alphaPos === false) { + $alpha = 255; + } else { + $alphaFloat = (float) substr($color, $alphaPos+1); + // restrict to range 0..1 + $alphaFloat = max(min($alphaFloat, 1), 0); + $alpha = (int) round((float) 255 * $alphaFloat); + $color = substr($color, 0, $alphaPos); + } + if ($color[0] == '#') { // hex-color given, e.g. #FFB4B4 + $tempColor = parent::hex2rgb($color); + return array((int) $tempColor[0], + (int) $tempColor[1], + (int) $tempColor[2], + $alpha); + } + if (strpos($color,'%') !== false) { + $tempColor = parent::percentageColor2RGB($color); + return array((int) $tempColor[0], + (int) $tempColor[1], + (int) $tempColor[2], + $alpha); + } else { + $tempColor = parent::namedColor2RGB($color); + return array((int) $tempColor[0], + (int) $tempColor[1], + (int) $tempColor[2], + $alpha); + } + } else { + return null; // error + } + } + + /** + * getRange + * Given a degree, you can get the range of colors between one color and + * another color. + * + * @access public + * @param string How much each 'step' between the colors we should take. + * @return array Returns an array of all the colors, one element for each color. + */ + function getRange ($degrees) + { + $tempColors = parent::getRange($degrees); + + // now add alpha-channel information + $steps = count($tempColors); + for($counter=0;$counter<$steps;$counter++) { + $tempColors[$counter] = parent::hex2rgb($tempColors[$counter]); + unset($tempColors[$counter]['hex']); + $tempColors[$counter][3] = (int) round( + (((float) $this->color1[3]*($steps-$counter))+ + ((float) $this->color2[3]*($counter)) + ) / $steps + ); + } + + return $tempColors; + } + + /** + * Internal method to correctly set the colors. + * + * @param mixed color 1 + * @param mixed color 2 + * @access private + */ + function _setColors ( $col1, $col2 ) + { + $this->color1 = Image_Canvas_Color::color2RGB($col1); + $this->color2 = Image_Canvas_Color::color2RGB($col2); + } +} ?> \ No newline at end of file diff --git a/pandora_console/reporting/Image/Canvas/GD.php b/pandora_console/reporting/Image/Canvas/GD.php index 6c0ee542e0..ef6116898e 100644 --- a/pandora_console/reporting/Image/Canvas/GD.php +++ b/pandora_console/reporting/Image/Canvas/GD.php @@ -1,1635 +1,1635 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: GD.php,v 1.8 2005/09/25 07:41:43 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas.php - */ -require_once 'Image/Canvas/WithMap.php'; - -/** - * Include file Image/Canvas/Color.php - */ -require_once 'Image/Canvas/Color.php'; - -/** - * Canvas class to output using PHP GD support. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @abstract - */ -class Image_Canvas_GD extends Image_Canvas_WithMap -{ - - /** - * The canvas of the graph - * @var resource - * @access private - */ - var $_canvas; - - /** - * The canvas to use for tiled filling - * @var resource - * @access private - */ - var $_tileImage = null; - - /** - * Is version GD2 installed? - * @var bool - * @access private - */ - var $_gd2 = true; - - /** - * Antialiasing? - * - * Possible values 'off', 'driver' and 'native' - * - * @var string - * @access private - */ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: GD.php,v 1.8 2005/09/25 07:41:43 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas.php + */ +require_once 'Image/Canvas/WithMap.php'; + +/** + * Include file Image/Canvas/Color.php + */ +require_once 'Image/Canvas/Color.php'; + +/** + * Canvas class to output using PHP GD support. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @abstract + */ +class Image_Canvas_GD extends Image_Canvas_WithMap +{ + + /** + * The canvas of the graph + * @var resource + * @access private + */ + var $_canvas; + + /** + * The canvas to use for tiled filling + * @var resource + * @access private + */ + var $_tileImage = null; + + /** + * Is version GD2 installed? + * @var bool + * @access private + */ + var $_gd2 = true; + + /** + * Antialiasing? + * + * Possible values 'off', 'driver' and 'native' + * + * @var string + * @access private + */ // Pandora FMS: Beware of this, could be slow on old systems - var $_antialias = 'driver'; - - /** - * Create the GD canvas. - * - * Parameters available: - * - * 'width' The width of the graph on the canvas - * - * 'height' The height of the graph on the canvas - * - * 'left' The left offset of the graph on the canvas - * - * 'top' The top offset of the graph on the canvas - * - * 'antialias' = 'native' enables native GD antialiasing - this - * method has no severe impact on performance (approx +5%). Requires PHP - * 4.3.2 (with bundled GD2) - * - * 'antialias' = {true|'driver'} Image_Graph implemented method. This method - * has a severe impact on performance, drawing an antialiased line this - * way is about XX times slower, with an overall performance impact of - * about +40%. The justification for this method is that if native support - * is not available this can be used, it is also a future feature that this - * method for antialiasing will support line styles. - * - * Use antialiased for best results with a line/area chart having just a few - * datapoints. Native antialiasing does not provide a good appearance with - * short lines, as for example with smoothed charts. Antialiasing does not - * (currently) work with linestyles, neither native nor driver method! - * - * 'noalpha' = true If alpha blending is to be disabled - * - * 'filename' An image to open, on which the graph is created on - * - * 'gd' A GD resource to add the image to, use this option to continue - * working on an already existing GD resource. Make sure this is passed 'by- - * reference' (using &) - * - * 'usemap' Initialize an image map - * - * 'gd' and 'filename' are mutually exclusive with 'gd' as preference - * - * 'width' and 'height' are required unless 'filename' or 'gd' are - * specified, in which case the width and height are taken as the actual - * image width/height. If the latter is the case and 'left' and/or 'top' was - * also specified, the actual 'width'/'height' are altered so that the graph - * fits inside the canvas (i.e 'height' = actual height - top, etc.) - * - * @param array $param Parameter array - */ - function Image_Canvas_GD($param) - { - include_once 'Image/Canvas/Color.php'; - - parent::Image_Canvas_WithMap($param); - - $this->_gd2 = ($this->_version() == 2); - $this->_font = array('font' => 1, 'color' => 'black'); - - if ((isset($param['gd'])) && (is_resource($param['gd']))) { - $this->_canvas =& $param['gd']; - } elseif (isset($param['filename'])) { - $this->_canvas =& $this->_getGD($param['filename']); - } else { - if ($this->_gd2) { - $this->_canvas = ImageCreateTrueColor( - $this->_width, - $this->_height - ); - if ((!isset($param['noalpha'])) || ($param['noalpha'] !== true)) { - ImageAlphaBlending($this->_canvas, true); - } - } else { - $this->_canvas = ImageCreate($this->_width, $this->_height); - } - } - - if (isset($param['antialias'])) { - $this->_antialias = $param['antialias']; - } - - if ($this->_antialias === true) { - $this->_antialias = 'driver'; - } - - if (($this->_gd2) && ($this->_antialias === 'native') && (function_exists('ImageAnt -ialias'))) { - ImageAntialias($this->_canvas, true); - } - } - - /** - * Get an GD image resource from a file - * - * @param string $filename - * @return mixed The GD image resource - * @access private - */ - function &_getGD($filename) - { - $info = getimagesize($filename); - - $result = null; - switch($info[2]) { - case IMG_PNG: - $result =& ImageCreateFromPNG($filename); - break; - - case IMG_JPG: - $result =& ImageCreateFromJPEG($filename); - break; - - case IMG_GIF: - $result =& ImageCreateFromGIF($filename); - break; - } - return $result; - } - - /** - * Get the color index for the RGB color - * - * @param int $color The color - * @return int The GD image index of the color - * @access private - */ - function _color($color = false) - { - if (($color === false) || ($color === 'opague') || ($color === 'transparent')) { - return ImageColorTransparent($this->_canvas); - } else { - return Image_Canvas_Color::allocateColor($this->_canvas, $color); - } - } - - /** - * Get the GD applicable linestyle - * - * @param mixed $lineStyle The line style to return, false if the one - * explicitly set - * @return mixed A GD compatible linestyle - * @access private - */ - function _getLineStyle($lineStyle = false) - { - if ($this->_gd2) { - ImageSetThickness($this->_canvas, $this->_thickness); - } - - if ($lineStyle == 'transparent') { - return false; - } elseif ($lineStyle === false) { - if (is_array($this->_lineStyle)) { - $colors = array(); - foreach ($this->_lineStyle as $color) { - if ($color === 'transparent') { - $color = false; - } - $colors[] = $this->_color($color); - } - ImageSetStyle($this->_canvas, $colors); - return IMG_COLOR_STYLED; - } else { - return $this->_color($this->_lineStyle); - } - } else { - return $this->_color($lineStyle); - } - } - - /** - * Get the GD applicable fillstyle - * - * @param mixed $fillStyle The fillstyle to return, false if the one - * explicitly set - * @return mixed A GD compatible fillstyle - * @access private - */ - function _getFillStyle($fillStyle = false, $x0 = 0, $y0 = 0, $x1 = 0, $y1 = 0) - { - if ($this->_tileImage != null) { - ImageDestroy($this->_tileImage); - $this->_tileImage = null; - } - if ($fillStyle == 'transparent') { - return false; - } elseif ($fillStyle === false) { - if (is_resource($this->_fillStyle)) { - $x = min($x0, $x1); - $y = min($y0, $y1); - $w = abs($x1 - $x0) + 1; - $h = abs($y1 - $y0) + 1; - if ($this->_gd2) { - $this->_tileImage = ImageCreateTrueColor( - $this->getWidth(), - $this->getHeight() - ); - - ImageCopyResampled( - $this->_tileImage, - $this->_fillStyle, - $x, - $y, - 0, - 0, - $w, - $h, - ImageSX($this->_fillStyle), - ImageSY($this->_fillStyle) - ); - } else { - $this->_tileImage = ImageCreate( - $this->getWidth(), - $this->getHeight() - ); - - ImageCopyResized( - $this->_tileImage, - $this->_fillStyle, - $x, - $y, - 0, - 0, - $w, - $h, - ImageSX($this->_fillStyle), - ImageSY($this->_fillStyle) - ); - } - ImageSetTile($this->_canvas, $this->_tileImage); - return IMG_COLOR_TILED; - } elseif ((is_array($this->_fillStyle)) && (isset($this->_fillStyle['direction']))) { - $width = abs($x1 - $x0) + 1; - $height = abs($y1 - $y0) + 1; - - switch ($this->_fillStyle['direction']) { - case 'horizontal': - $count = $width; - break; - - case 'vertical': - $count = $height; - break; - - case 'horizontal_mirror': - $count = $width / 2; - break; - - case 'vertical_mirror': - $count = $height / 2; - break; - - case 'diagonal_tl_br': - case 'diagonal_bl_tr': - $count = sqrt($width * $width + $height * $height); - break; - - case 'radial': - $count = max($width, $height, sqrt($width * $width + $height * $height)) + 1; - break; - - } - - $count = round($count); - - if ($this->_gd2) { - $this->_tileImage = ImageCreateTrueColor( - $this->getWidth(), - $this->getHeight() - ); - } else { - $this->_tileImage = ImageCreate( - $this->getWidth(), - $this->getHeight() - ); - } - - - $startColor = Image_Canvas_Color::color2RGB( - ($this->_fillStyle['direction'] == 'radial' ? - $this->_fillStyle['end'] : - $this->_fillStyle['start'] - ) - ); - $endColor = Image_Canvas_Color::color2RGB( - ($this->_fillStyle['direction'] == 'radial' ? - $this->_fillStyle['start'] : - $this->_fillStyle['end'] - ) - ); - - $redIncrement = ($endColor[0] - $startColor[0]) / $count; - $greenIncrement = ($endColor[1] - $startColor[1]) / $count; - $blueIncrement = ($endColor[2] - $startColor[2]) / $count; - - $color = false; - for ($i = 0; $i < $count; $i ++) { - unset($color); - if ($i == 0) { - $color = $startColor; - unset($color[3]); - } else { - $color[0] = round(($redIncrement * $i) + - $redIncrement + $startColor[0]); - $color[1] = round(($greenIncrement * $i) + - $greenIncrement + $startColor[1]); - $color[2] = round(($blueIncrement * $i) + - $blueIncrement + $startColor[2]); - } - $color = Image_Canvas_Color::allocateColor( - $this->_tileImage, - $color - ); - - switch ($this->_fillStyle['direction']) { - case 'horizontal': - ImageLine($this->_tileImage, - $x0 + $i, - $y0, - $x0 + $i, - $y1, $color); - break; - - case 'vertical': - ImageLine($this->_tileImage, - $x0, - $y1 - $i, - $x1, - $y1 - $i, $color); - break; - - case 'horizontal_mirror': - if (($x0 + $i) <= ($x1 - $i)) { - ImageLine($this->_tileImage, - $x0 + $i, - $y0, - $x0 + $i, - $y1, $color); - - ImageLine($this->_tileImage, - $x1 - $i, - $y0, - $x1 - $i, - $y1, $color); - } - break; - - case 'vertical_mirror': - if (($y0 + $i) <= ($y1 - $i)) { - ImageLine($this->_tileImage, - $x0, - $y0 + $i, - $x1, - $y0 + $i, $color); - ImageLine($this->_tileImage, - $x0, - $y1 - $i, - $x1, - $y1 - $i, $color); - } - break; - - case 'diagonal_tl_br': - if (($i > $width) && ($i > $height)) { - $polygon = array ( - $x1, $y0 + $i - $width - 1, - $x1, $y1, - $x0 + $i - $height - 1, $y1); - } elseif ($i > $width) { - $polygon = array ( - $x0, $y0 + $i, - $x0, $y1, - $x1, $y1, - $x1, $y0 + $i - $width - 1); - } elseif ($i > $height) { - $polygon = array ( - $x0 + $i - $height - 1, $y1, - $x1, $y1, - $x1, $y0, - $x0 + $i, $y0); - } else { - $polygon = array ( - $x0, $y0 + $i, - $x0, $y1, - $x1, $y1, - $x1, $y0, - $x0 + $i, $y0); - } - ImageFilledPolygon( - $this->_tileImage, - $polygon, - count($polygon) / 2, - $color - ); - break; - - case 'diagonal_bl_tr': - if (($i > $width) && ($i > $height)) { - $polygon = array ( - $x1, $y1 - $i + $width - 1, - $x1, $y0, - $x0 + $i - $height - 1, $y0); - } elseif ($i > $width) { - $polygon = array ( - $x0, $y1 - $i, - $x0, $y0, - $x1, $y0, - $x1, $y1 - $i + $width - 1); - } elseif ($i > $height) { - $polygon = array ( - $x0 + $i - $height - 1, $y0, - $x1, $y0, - $x1, $y1, - $x0 + $i, $y1); - } else { - $polygon = array ( - $x0, $y1 - $i, - $x0, $y0, - $x1, $y0, - $x1, $y1, - $x0 + $i, $y1); - } - ImageFilledPolygon( - $this->_tileImage, - $polygon, - count($polygon) / 2, - $color - ); - break; - - case 'radial': - if (($this->_gd2) && ($i < $count)) { - ImageFilledEllipse( - $this->_tileImage, - $x0 + $width / 2, - $y0 + $height / 2, - $count - $i, - $count - $i, - $color - ); - } - break; - } - } - ImageSetTile($this->_canvas, $this->_tileImage); - return IMG_COLOR_TILED; - } else { - return $this->_color($this->_fillStyle); - } - } else { - return $this->_color($fillStyle); - } - } - - /** - * Sets an image that should be used for filling - * - * @param string $filename The filename of the image to fill with - */ - function setFillImage($filename) - { - $this->_fillStyle =& $this->_getGD($filename); - } - - /** - * Sets the font options. - * - * The $font array may have the following entries: - * - * 'ttf' = the .ttf file (either the basename, filename or full path) - * If 'ttf' is specified, then the following can be specified - * - * 'size' = size in pixels - * - * 'angle' = the angle with which to write the text - * - * @param array $font The font options. - */ - function setFont($fontOptions) - { - parent::setFont($fontOptions); - - if (isset($this->_font['ttf'])) { - $this->_font['file'] = str_replace('\\', '/', $this->_mapFont($this->_font['ttf'])); - } elseif (!isset($this->_font['font'])) { - $this->_font['font'] = 1; - } - - if (!isset($this->_font['color'])) { - $this->_font['color'] = 'black'; - } - - if ((isset($this->_font['angle'])) && ($this->_font['angle'] === false)) { - $this->_font['angle'] = 0; - } - } - - /** - * Calculate pixels on a line - * - * @param int $x0 X start point - * @param int $y0 X start point - * @param int $x1 X end point - * @param int $y1 Y end point - * @return array An associated array of x,y points with all pixels on the - * line - * @access private - */ - function &_linePixels($x0, $y0, $x1, $y1) - { - $pixels = array(); - if (abs($x0 - $x1) > abs($y0 - $y1)) { - if ($x1 != $x0) { - $m = ($y1 - $y0) / ($x1 - $x0); - } else { - $m = 0; - } - $b = $y0 - $m * $x0; - $strx = min($x0, $x1); - $endx = max($x0, $x1); - for ($x = $strx; $x <= $endx; $x++) { - $pixels[] = array('X' => $x, 'Y' => ($m * $x + $b)); - } - } else { - if ($y1 != $y0) { - $m = ($x1 - $x0) / ($y1 - $y0); - } else { - $m = 0; - } - $b = $x0 - $m * $y0; - $stry = min($y0, $y1); - $endy = max($y0, $y1); - for ($y = $stry; $y <= $endy; $y++) { - $pixels[] = array('X' => ($m * $y + $b), 'Y' => $y); - } - } - return $pixels; - } - - /** - * Draws an antialiased line - * - * @param int $x0 X start point - * @param int $y0 X start point - * @param int $x1 X end point - * @param int $y1 Y end point - * @param mixed $color The line color, can be omitted - * @access private - */ - function _antialiasedLine($x0, $y0, $x1, $y1, $color = false) - { - if (($line = $this->_getLineStyle($color)) !== false) { - if ($line >= 0) { - $line = ImageColorsForIndex($this->_canvas, $line); - $pixels = &$this->_linePixels($x0, $y0, $x1, $y1); - foreach ($pixels as $point) { - $this->_antialiasedPixel($point['X'], $point['Y'], $line); - } - unset($pixels); - } - } - } - - - /** - * Draws an antialiased pixel - * - * @param int $x X point - * @param int $y Y point - * @param mixed $color The pixel color - * @access private - */ - function _antialiasedPixel($x, $y, $color) - { - $fx = floor($x); - $fy = floor($y); - $cx = ceil($x); - $cy = ceil($y); - $xa = $x - $fx; - $xb = $cx - $x; - $ya = $y - $fy; - $yb = $cy - $y; - if (($cx == $fx) && ($cy == $fy)) { - $this->_antialisedSubPixel($fx, $fy, 0.0, 1.0, $color); - } else { - $this->_antialisedSubPixel($fx, $fy, $xa + $ya, $xb + $yb, $color); - if ($cy != $fy) { - $this->_antialisedSubPixel($fx, $cy, $xa + $yb, $xb + $ya, $color); - } - if ($cx != $fx) { - $this->_antialisedSubPixel($cx, $fy, $xb + $ya, $xa + $yb, $color); - if ($cy != $fy) { - $this->_antialisedSubPixel($cx, $cy, $xb + $yb, $xa + $ya, $color); - } - } - } - } - - /** - * Antialias'es the pixel around x,y with weights a,b - * - * @param int $x X point - * @param int $y Y point - * @param int $a The weight of the current color - * @param int $b The weight of the applied/wanted color - * @param mixed $color The pixel color - * @access private - */ - function _antialisedSubPixel($x, $y, $a, $b, $color) - { - $x = $this->_getX($x); - $y = $this->_getX($y); - if (($x >=0 ) && ($y >= 0) && ($x < $this->getWidth()) && ($y < $this->getHeight())) { - $tempColor = ImageColorsForIndex($this->_canvas, ImageColorAt($this->_canvas, $x, $y)); - - $newColor[0] = min(255, round($tempColor['red'] * $a + $color['red'] * $b)); - $newColor[1] = min(255, round($tempColor['green'] * $a + $color['green'] * $b)); - $newColor[2] = min(255, round($tempColor['blue'] * $a + $color['blue'] * $b)); - //$newColor[3] = 0; - $color = '#'; - foreach ($newColor as $acolor) { - $color .= sprintf('%02s', dechex($acolor)); - } - $newColor = $this->_color($color);//,'rgb(' . $newColor[0] . ',' . $newColor[1] . ',' . $newColor[2] .')'; - - ImageSetPixel($this->_canvas, $x, $y, $newColor); - } - } - - - /** - * Draw a line end - * - * Parameter array: - * - * 'x': int X point - * - * 'y': int Y point - * - * 'end': string The end type of the end - * - * 'size': int The size of the end - * - * 'color': string The color of the end - * - * 'angle': int [optional] The angle with which to draw the end - * - * @param array $params Parameter array - */ - function drawEnd($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $size = $params['size']; - //var_dump($params); - $angle = deg2rad((isset($params['angle']) ? $params['angle'] : 0)); - $pi2 = pi() / 2; - switch ($params['end']) { - case 'lollipop': - case 'circle': - $this->ellipse( - array( - 'x' => $x, - 'y' => $y, - 'rx' => $size / 2, - 'ry' => $size / 2, - 'fill' => $params['color'], - 'line' => $params['color'] - ) - ); - break; - case 'diamond': - $x0 = round($params['x'] + cos($angle) * $size * 0.65); - $y0 = round($params['y'] - sin($angle) * $size * 0.65); - $shape = array( - $x0 + round(cos($angle) * $size * 0.65), - $y0 - round(sin($angle) * $size * 0.65), - $x0 + round(cos($angle + $pi2) * $size * 0.65), - $y0 - round(sin($angle + $pi2) * $size * 0.65), - $x0 + round(cos($angle + pi()) * $size * 0.65), - $y0 - round(sin($angle + pi()) * $size * 0.65), - $x0 + round(cos($angle + 3 * $pi2) * $size * 0.65), - $y0 - round(sin($angle + 3 * $pi2) * $size * 0.65) - ); - break; - case 'line': - $this->line( - array( - 'x0' => $x + round(cos($angle + $pi2) * $size / 2), - 'y0' => $y - round(sin($angle + $pi2) * $size / 2), - 'x1' => $x + round(cos($angle + 3 * $pi2) * $size / 2), - 'y1' => $y - round(sin($angle + 3 * $pi2) * $size / 2), - 'color' => $params['color'] - ) - ); - break; - case 'box': - case 'rectangle': - $x0 = round($params['x'] + cos($angle) * $size / 2); - $y0 = round($params['y'] - sin($angle) * $size / 2); - $pi4 = pi() / 4; - $shape = array( - $x0 + round(cos($angle + $pi4) * $size / 2), - $y0 - round(sin($angle + $pi4) * $size / 2), - $x0 + round(cos($angle + $pi2 + $pi4) * $size / 2), - $y0 - round(sin($angle + $pi2 + $pi4) * $size / 2), - $x0 + round(cos($angle + pi() + $pi4) * $size / 2), - $y0 - round(sin($angle + pi() + $pi4) * $size / 2), - $x0 + round(cos($angle + 3 * $pi2 + $pi4) * $size / 2), - $y0 - round(sin($angle + 3 * $pi2 + $pi4) * $size / 2) - ); - break; - case 'arrow': - $shape = array( - $x + cos($angle) * $size, - $y - sin($angle) * $size, - $x + cos($angle + $pi2) * $size * 0.4, - $y - sin($angle + $pi2) * $size * 0.4, - $x + cos($angle + 3 * $pi2) * $size * 0.4, - $y - sin($angle + 3 * $pi2) * $size * 0.4, - ); - break; - case 'arrow2': - $shape = array( - $x + round(cos($angle) * $size), - $y - round(sin($angle) * $size), - $x + round(cos($angle + $pi2 + deg2rad(45)) * $size), - $y - round(sin($angle + $pi2 + deg2rad(45)) * $size), - $x, - $y, - $x + round(cos($angle + 3 * $pi2 - deg2rad(45)) * $size), - $y - round(sin($angle + 3 * $pi2 - deg2rad(45)) * $size), - ); - break; - } - - if (isset($shape)) { - // output the shape - if (($fill = $this->_getFillStyle($params['color'])) !== false) { - ImageFilledPolygon($this->_canvas, $shape, count($shape)/2, $fill); - } - } - parent::drawEnd($params); - } - - /** - * Draw a line - * - * Parameter array: - * - * 'x0': int X start point - * - * 'y0': int Y start point - * - * 'x1': int X end point - * - * 'y1': int Y end point - * - * 'color': mixed [optional] The line color - * - * @param array $params Parameter array - */ - function line($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - $color = (isset($params['color']) ? $params['color'] : false); - - $x0 = $this->_getX($x0); - $y0 = $this->_getY($y0); - $x1 = $this->_getX($x1); - $y1 = $this->_getY($y1); - if (($this->_antialias === 'driver') && ($x0 != $x1) && ($y0 != $y1)) { - $this->_antialiasedLine($x0, $y0, $x1, $y1, $color); - } elseif (($line = $this->_getLineStyle($color)) !== false) { - ImageLine($this->_canvas, $x0, $y0, $x1, $y1, $line); - } - parent::line($params); - } - - /** - * Parameter array: - * - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * - * 'fill': mixed [optional] The fill color - * - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params) - { - include_once 'Image/Canvas/Tool.php'; - - $connectEnds = (isset($params['connect']) ? $params['connect'] : false); - $fillColor = (isset($params['fill']) ? $params['fill'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - if (!$connectEnds) { - $fillColor = 'transparent'; - } - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - - $lastPoint = false; - foreach ($this->_polygon as $point) { - if (($lastPoint) && (isset($lastPoint['P1X'])) && - (isset($lastPoint['P1Y'])) && (isset($lastPoint['P2X'])) && - (isset($lastPoint['P2Y']))) - { - $dx = abs($point['X'] - $lastPoint['X']); - $dy = abs($point['Y'] - $lastPoint['Y']); - $d = sqrt($dx * $dx + $dy * $dy); - if ($d > 0) { - $interval = 1 / $d; - for ($t = 0; $t <= 1; $t = $t + $interval) { - $x = Image_Canvas_Tool::bezier( - $t, - $lastPoint['X'], - $lastPoint['P1X'], - $lastPoint['P2X'], - $point['X'] - ); - - $y = Image_Canvas_Tool::bezier( - $t, - $lastPoint['Y'], - $lastPoint['P1Y'], - $lastPoint['P2Y'], - $point['Y'] - ); - - if (!isset($low['X'])) { - $low['X'] = $x; - } else { - $low['X'] = min($x, $low['X']); - } - if (!isset($high['X'])) { - $high['X'] = $x; - } else { - $high['X'] = max($x, $high['X']); - } - if (!isset($low['Y'])) { - $low['Y'] = $y; - } else { - $low['Y'] = min($y, $low['Y']); - } - if (!isset($high['Y'])) { - $high['Y'] = $y; - } else { - $high['Y'] = max($y, $high['Y']); - } - $polygon[] = $x; - $polygon[] = $y; - } - if (($t - $interval) < 1) { - $x = Image_Canvas_Tool::bezier( - 1, - $lastPoint['X'], - $lastPoint['P1X'], - $lastPoint['P2X'], - $point['X'] - ); - - $y = Image_Canvas_Tool::bezier( - 1, - $lastPoint['Y'], - $lastPoint['P1Y'], - $lastPoint['P2Y'], - $point['Y'] - ); - - $polygon[] = $x; - $polygon[] = $y; - } - } - } else { - if (!isset($low['X'])) { - $low['X'] = $point['X']; - } else { - $low['X'] = min($point['X'], $low['X']); - } - if (!isset($high['X'])) { - $high['X'] = $point['X']; - } else { - $high['X'] = max($point['X'], $high['X']); - } - if (!isset($low['Y'])) { - $low['Y'] = $point['Y']; - } else { - $low['Y'] = min($point['Y'], $low['Y']); - } - if (!isset($high['Y'])) { - $high['Y'] = $point['Y']; - } else { - $high['Y'] = max($point['Y'], $high['Y']); - } - - $polygon[] = $point['X']; - $polygon[] = $point['Y']; - } - $lastPoint = $point; - } - - if ((isset($polygon)) && (is_array($polygon))) { - if ($connectEnds) { - if (($fill = $this->_getFillStyle($fillColor, $low['X'], $low['Y'], $high['X'], $high['Y'])) !== false) { - ImageFilledPolygon($this->_canvas, $polygon, count($polygon)/2, $fill); - } - if ($this->_antialias === 'driver') { - $pfirst = $p0 = false; - reset($polygon); - - while (list(, $x) = each($polygon)) { - list(, $y) = each($polygon); - if ($p0 !== false) { - $this->_antialiasedLine($p0['X'], $p0['Y'], $x, $y, $lineColor); - } - if ($pfirst === false) { - $pfirst = array('X' => $x, 'Y' => $y); - } - $p0 = array('X' => $x, 'Y' => $y);; - } - - $this->_antialiasedLine($p0['X'], $p0['Y'], $pfirst['X'], $pfirst['Y'], $lineColor); - } elseif (($line = $this->_getLineStyle($lineColor)) !== false) { - ImagePolygon($this->_canvas, $polygon, count($polygon)/2, $line); - } - } else { - $prev_point = false; - if ($this->_antialias === 'driver') { - reset($polygon); - while (list(, $x) = each($polygon)) { - list(, $y) = each($polygon); - if ($prev_point) { - $this->_antialiasedLine( - $prev_point['X'], - $prev_point['Y'], - $x, - $y, - $lineColor - ); - } - $prev_point = array('X' => $x, 'Y' => $y);; - } - } elseif (($line = $this->_getLineStyle($lineColor)) !== false) { - reset($polygon); - while (list(, $x) = each($polygon)) { - list(, $y) = each($polygon); - if ($prev_point) { - ImageLine( - $this->_canvas, - $prev_point['X'], - $prev_point['Y'], - $x, - $y, - $line - ); - } - $prev_point = array('X' => $x, 'Y' => $y);; - } - } - } - } - - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * - * 'x0': int X start point - * - * 'y0': int Y start point - * - * 'x1': int X end point - * - * 'y1': int Y end point - * - * 'fill': mixed [optional] The fill color - * - * 'line': mixed [optional] The line color - * - * @param array $params Parameter array - */ - function rectangle($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - $fillColor = (isset($params['fill']) ? $params['fill'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - if (($fill = $this->_getFillStyle($fillColor, $x0, $y0, $x1, $y1)) !== false) { - ImageFilledRectangle($this->_canvas, $x0, $y0, $x1, $y1, $fill); - } - - if (($line = $this->_getLineStyle($lineColor)) !== false) { - ImageRectangle($this->_canvas, $x0, $y0, $x1, $y1, $line); - } - - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * - * 'x': int X center point - * - * 'y': int Y center point - * - * 'rx': int X radius - * - * 'ry': int Y radius - * - * 'fill': mixed [optional] The fill color - * - * 'line': mixed [optional] The line color - * - * @param array $params Parameter array - */ - function ellipse($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $fillColor = (isset($params['fill']) ? $params['fill'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - if (($fill = $this->_getFillStyle($fillColor, $x - $rx, $y - $ry, $x + $rx, $y + $ry)) !== false) { - ImageFilledEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $fill); - } - - if (($line = $this->_getLineStyle($lineColor)) !== false) { - ImageEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $line); - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * - * 'x': int X center point - * - * 'y': int Y center point - * - * 'rx': int X radius - * - * 'ry': int Y radius - * - * 'v1': int The starting angle (in degrees) - * - * 'v2': int The end angle (in degrees) - * - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * - * 'fill': mixed [optional] The fill color - * - * 'line': mixed [optional] The line color - * - * @param array $params Parameter array - */ - function pieslice($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $params['rx']; - $ry = $params['ry']; - $v1 = $params['v1']; - $v2 = $params['v2']; - $srx = (isset($params['srx']) ? $params['srx'] : 0); - $sry = (isset($params['sry']) ? $params['sry'] : 0); - $fillColor = (isset($params['fill']) ? $params['fill'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $dA = 0.1; - - if (($srx !== false) && ($sry !== false)) { - $angle = max($v1, $v2); - while ($angle >= min($v1, $v2)) { - $polygon[] = ($x + $srx * cos(deg2rad($angle % 360))); - $polygon[] = ($y + $sry * sin(deg2rad($angle % 360))); - $angle -= $dA; - } - if (($angle + $dA) > min($v1, $v2)) { - $polygon[] = ($x + $srx * cos(deg2rad(min($v1, $v2) % 360))); - $polygon[] = ($y + $sry * sin(deg2rad(min($v1, $v2) % 360))); - } - } else { - $polygon[] = $x; - $polygon[] = $y; - } - - $angle = min($v1, $v2); - while ($angle <= max($v1, $v2)) { - $polygon[] = ($x + $rx * cos(deg2rad($angle % 360))); - $polygon[] = ($y + $ry * sin(deg2rad($angle % 360))); - $angle += $dA; - } - - if (($angle - $dA) < max($v1, $v2)) { - $polygon[] = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360))); - $polygon[] = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360))); - } - - if (($fill = $this->_getFillStyle($fillColor, $x - $rx - 1, $y - $ry - 1, $x + $rx + 1, $y + $ry + 1)) !== false) { - ImageFilledPolygon($this->_canvas, $polygon, count($polygon) / 2, $fill); - } - - if (($line = $this->_getLineStyle($lineColor)) !== false) { - ImagePolygon($this->_canvas, $polygon, count($polygon) / 2, $line); - } - - parent::pieSlice($params); - } - - /** - * Get the width of a text, - * - * @param string $text The text to get the width of - * @return int The width of the text - */ - function textWidth($text) - { - if (isset($this->_font['file'])) { - $angle = 0; - if (isset($this->_font['angle'])) { - $angle = $this->_font['angle']; - } - - $width = 0; - $lines = explode("\n", $text); - foreach ($lines as $line) { - $bounds = ImageTTFBBox( - $this->_font['size'], - $angle, - $this->_font['file'], - $text - ); - - $x0 = min($bounds[0], $bounds[2], $bounds[4], $bounds[6]); - $x1 = max($bounds[0], $bounds[2], $bounds[4], $bounds[6]); - $width = max(abs($x0 - $x1), $width); - } - return $width; - } else { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1); - } else { - $width = 0; - $lines = explode("\n", $text); - foreach ($lines as $line) { - $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line)); - } - return $width; - } - } - } - - /** - * Get the height of a text. - * - * Note! This method can give some peculiar results, since ImageTTFBBox() returns the total - * bounding box of a text, where ImageTTF() writes the text on the baseline of the text, that - * is 'g', 'p', 'q' and other letters that dig under the baseline will appear to have a larger - * height than they actually do. Have a look at the tests/text.php test case - the first two - * columns, 'left and 'center', both look alright, whereas the last column, 'right', appear - * with a larger space between the first text and the second. This is because the total height - * is actually smaller by exactly the number of pixels that the 'g' digs under the baseline. - * Remove the 'g' from the text and they appear correct. - * - * @param string $text The text to get the height of - * @param bool $force Force the method to calculate the size - * @return int The height of the text - */ - function textHeight($text, $force = false) - { - if (isset($this->_font['file'])) { - $angle = 0; - if (isset($this->_font['angle'])) { - $angle = $this->_font['angle']; - } - - $linebreaks = substr_count($text, "\n"); - if (($angle == 0) && ($linebreaks == 0) && ($force === false)) { - /* - * if the angle is 0 simply return the size, due to different - * heights for example for x-axis labels, making the labels - * _not_ appear as written on the same baseline - */ - return $this->_font['size'] + 2; - } - - $height = 0; - $lines = explode("\n", $text); - foreach ($lines as $line) { - $bounds = ImageTTFBBox( - $this->_font['size'], - $angle, - $this->_font['file'], - $line - ); - - $y0 = min($bounds[1], $bounds[3], $bounds[5], $bounds[7]); - $y1 = max($bounds[1], $bounds[3], $bounds[5], $bounds[7]); - $height += abs($y0 - $y1); - } - return $height + $linebreaks * 2; - } else { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - $width = 0; - $lines = explode("\n", $text); - foreach ($lines as $line) { - $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line)); - } - return $width; - } else { - return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1); - } - } - } - - /** - * Writes text - * - * Parameter array: - * - * 'x': int X-point of text - * - * 'y': int Y-point of text - * - * 'text': string The text to add - * - * 'alignment': array [optional] Alignment - * - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - $x0 = $this->_getX($params['x']); - $y0 = $this->_getY($params['y']); - $text = $params['text']; - $color = (isset($params['color']) ? $params['color'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - $text = str_replace("\r", '', $text); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - if ($alignment['vertical'] == 'bottom') { - $y0 = $y0 - $this->textHeight($text, true); - } elseif ($alignment['vertical'] == 'center') { - $y0 = $y0 - ($this->textHeight($text, true) / 2); - } - - $lines = explode("\n", $text); - foreach ($lines as $line) { - $textWidth = $this->textWidth($line); - $textHeight = $this->textHeight($line, true); - - $x = $x0; - $y = $y0; - - $y0 += $textHeight + 2; - - if ($alignment['horizontal'] == 'right') { - $x = $x - $textWidth; - } elseif ($alignment['horizontal'] == 'center') { - $x = $x - ($textWidth / 2); - } - - if (($color === false) && (isset($this->_font['color']))) { - $color = $this->_font['color']; - } - - if ($color != 'transparent') { - if (isset($this->_font['file'])) { - if (($this->_font['angle'] < 180) && ($this->_font['angle'] >= 0)) { - $y += $textHeight; - } - if (($this->_font['angle'] >= 90) && ($this->_font['angle'] < 270)) { - $x += $textWidth; - } - - ImageTTFText( - $this->_canvas, - $this->_font['size'], - $this->_font['angle'], - $x, - $y, - $this->_color($color), - $this->_font['file'], - $line - ); - - } else { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - ImageStringUp( - $this->_canvas, - $this->_font['font'], - $x, - $y + $this->textHeight($text), - $line, - $this->_color($color) - ); - } else { - ImageString( - $this->_canvas, - $this->_font['font'], - $x, - $y, - $line, - $this->_color($color) - ); - } - } - } - } - parent::addText($params); - } - - /** - * Overlay image - * - * Parameter array: - * - * 'x': int X-point of overlayed image - * - * 'y': int Y-point of overlayed image - * - * 'filename': string The filename of the image to overlay - * - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * - * 'alignment': array [optional] Alignment - */ - function image($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $filename = $params['filename']; - $width = (isset($params['width']) ? $params['width'] : false); - $height = (isset($params['height']) ? $params['height'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - if (file_exists($filename)) { - if (strtolower(substr($filename, -4)) == '.png') { - $image = ImageCreateFromPNG($filename); - } elseif (strtolower(substr($filename, -4)) == '.gif') { - $image = ImageCreateFromGIF($filename); - } else { - $image = ImageCreateFromJPEG($filename); - } - - $imgWidth = ImageSX($image); - $imgHeight = ImageSY($image); - - $outputWidth = ($width !== false ? $width : $imgWidth); - $outputHeight = ($height !== false ? $height : $imgHeight); - - if ($alignment['horizontal'] == 'right') { - $x -= $outputWidth; - } elseif ($alignment['horizontal'] == 'center') { - $x -= $outputWidth / 2; - } - - if ($alignment['vertical'] == 'bottom') { - $y -= $outputHeight; - } elseif ($alignment['vertical'] == 'center') { - $y -= $outputHeight / 2; - } - - if ((($width !== false) && ($width != $imgWidth)) || - (($height !== false) && ($height != $imgHeight))) - { - if ($this->_gd2) { - ImageCopyResampled( - $this->_canvas, - $image, - $x, - $y, - 0, - 0, - $width, - $height, - $imgWidth, - $imgHeight - ); - } else { - ImageCopyResized( - $this->_canvas, - $image, - $x, - $y, - 0, - 0, - $width, - $height, - $imgWidth, - $imgHeight - ); - } - } else { - ImageCopy( - $this->_canvas, - $image, - $x, - $y, - 0, - 0, - $imgWidth, - $imgHeight - ); - } - ImageDestroy($image); - } - parent::image($params); - } - - /** - * Get a canvas specific HTML tag. - * - * This method implicitly saves the canvas to the filename in the - * filesystem path specified and parses it as URL specified by URL path - * - * Parameter array: - * - * 'filename' string - * - * 'filepath': string Path to the file on the file system. Remember the final slash - * - * 'urlpath': string Path to the file available through an URL. Remember the final slash - * - * 'alt': string [optional] Alternative text on image - * - * 'cssclass': string [optional] The CSS Stylesheet class - * - * 'border': int [optional] The border width on the image - */ - function toHtml($params) - { - parent::toHtml($params); - return '' . $params['alt'] . '_imageMap) ? ' usemap="#' . $params['filename'] . '"' : '') . '>' . - (isset($this->_imageMap) ? "\n" . $this->_imageMap->toHtml(array('name' => $params['filename'])) : ''); - } - - /** - * Resets the canvas. - * - * Include fillstyle, linestyle, thickness and polygon - * @access private - */ - function _reset() - { - if ($this->_gd2) { - ImageSetThickness($this->_canvas, 1); - } - if ($this->_tileImage != null) { - ImageDestroy($this->_tileImage); - $this->_tileImage = null; - } - parent::_reset(); - $this->_font = array('font' => 1, 'color' => 'black'); - } - - /** - * Check which version of GD is installed - * - * @return int 0 if GD isn't installed, 1 if GD 1.x is installed and 2 if GD - * 2.x is installed - * @access private - */ - function _version() - { - $result = false; - if (function_exists('gd_info')) { - $info = gd_info(); - $version = $info['GD Version']; - } else { - ob_start(); - phpinfo(8); - $php_info = ob_get_contents(); - ob_end_clean(); - - if (ereg("]*>GD Version *<\/td>]*>([^<]*)<\/td>", - $php_info, $result)) - { - $version = $result[1]; - } - } - - if (ereg('1\.[0-9]{1,2}', $version)) { - return 1; - } elseif (ereg('2\.[0-9]{1,2}', $version)) { - return 2; - } else { - return 0; - } - } - -} - -?> + var $_antialias = 'driver'; + + /** + * Create the GD canvas. + * + * Parameters available: + * + * 'width' The width of the graph on the canvas + * + * 'height' The height of the graph on the canvas + * + * 'left' The left offset of the graph on the canvas + * + * 'top' The top offset of the graph on the canvas + * + * 'antialias' = 'native' enables native GD antialiasing - this + * method has no severe impact on performance (approx +5%). Requires PHP + * 4.3.2 (with bundled GD2) + * + * 'antialias' = {true|'driver'} Image_Graph implemented method. This method + * has a severe impact on performance, drawing an antialiased line this + * way is about XX times slower, with an overall performance impact of + * about +40%. The justification for this method is that if native support + * is not available this can be used, it is also a future feature that this + * method for antialiasing will support line styles. + * + * Use antialiased for best results with a line/area chart having just a few + * datapoints. Native antialiasing does not provide a good appearance with + * short lines, as for example with smoothed charts. Antialiasing does not + * (currently) work with linestyles, neither native nor driver method! + * + * 'noalpha' = true If alpha blending is to be disabled + * + * 'filename' An image to open, on which the graph is created on + * + * 'gd' A GD resource to add the image to, use this option to continue + * working on an already existing GD resource. Make sure this is passed 'by- + * reference' (using &) + * + * 'usemap' Initialize an image map + * + * 'gd' and 'filename' are mutually exclusive with 'gd' as preference + * + * 'width' and 'height' are required unless 'filename' or 'gd' are + * specified, in which case the width and height are taken as the actual + * image width/height. If the latter is the case and 'left' and/or 'top' was + * also specified, the actual 'width'/'height' are altered so that the graph + * fits inside the canvas (i.e 'height' = actual height - top, etc.) + * + * @param array $param Parameter array + */ + function Image_Canvas_GD($param) + { + include_once 'Image/Canvas/Color.php'; + + parent::Image_Canvas_WithMap($param); + + $this->_gd2 = ($this->_version() == 2); + $this->_font = array('font' => 1, 'color' => 'black'); + + if ((isset($param['gd'])) && (is_resource($param['gd']))) { + $this->_canvas =& $param['gd']; + } elseif (isset($param['filename'])) { + $this->_canvas =& $this->_getGD($param['filename']); + } else { + if ($this->_gd2) { + $this->_canvas = ImageCreateTrueColor( + $this->_width, + $this->_height + ); + if ((!isset($param['noalpha'])) || ($param['noalpha'] !== true)) { + ImageAlphaBlending($this->_canvas, true); + } + } else { + $this->_canvas = ImageCreate($this->_width, $this->_height); + } + } + + if (isset($param['antialias'])) { + $this->_antialias = $param['antialias']; + } + + if ($this->_antialias === true) { + $this->_antialias = 'driver'; + } + + if (($this->_gd2) && ($this->_antialias === 'native') && (function_exists('ImageAnt +ialias'))) { + ImageAntialias($this->_canvas, true); + } + } + + /** + * Get an GD image resource from a file + * + * @param string $filename + * @return mixed The GD image resource + * @access private + */ + function &_getGD($filename) + { + $info = getimagesize($filename); + + $result = null; + switch($info[2]) { + case IMG_PNG: + $result =& ImageCreateFromPNG($filename); + break; + + case IMG_JPG: + $result =& ImageCreateFromJPEG($filename); + break; + + case IMG_GIF: + $result =& ImageCreateFromGIF($filename); + break; + } + return $result; + } + + /** + * Get the color index for the RGB color + * + * @param int $color The color + * @return int The GD image index of the color + * @access private + */ + function _color($color = false) + { + if (($color === false) || ($color === 'opague') || ($color === 'transparent')) { + return ImageColorTransparent($this->_canvas); + } else { + return Image_Canvas_Color::allocateColor($this->_canvas, $color); + } + } + + /** + * Get the GD applicable linestyle + * + * @param mixed $lineStyle The line style to return, false if the one + * explicitly set + * @return mixed A GD compatible linestyle + * @access private + */ + function _getLineStyle($lineStyle = false) + { + if ($this->_gd2) { + ImageSetThickness($this->_canvas, $this->_thickness); + } + + if ($lineStyle == 'transparent') { + return false; + } elseif ($lineStyle === false) { + if (is_array($this->_lineStyle)) { + $colors = array(); + foreach ($this->_lineStyle as $color) { + if ($color === 'transparent') { + $color = false; + } + $colors[] = $this->_color($color); + } + ImageSetStyle($this->_canvas, $colors); + return IMG_COLOR_STYLED; + } else { + return $this->_color($this->_lineStyle); + } + } else { + return $this->_color($lineStyle); + } + } + + /** + * Get the GD applicable fillstyle + * + * @param mixed $fillStyle The fillstyle to return, false if the one + * explicitly set + * @return mixed A GD compatible fillstyle + * @access private + */ + function _getFillStyle($fillStyle = false, $x0 = 0, $y0 = 0, $x1 = 0, $y1 = 0) + { + if ($this->_tileImage != null) { + ImageDestroy($this->_tileImage); + $this->_tileImage = null; + } + if ($fillStyle == 'transparent') { + return false; + } elseif ($fillStyle === false) { + if (is_resource($this->_fillStyle)) { + $x = min($x0, $x1); + $y = min($y0, $y1); + $w = abs($x1 - $x0) + 1; + $h = abs($y1 - $y0) + 1; + if ($this->_gd2) { + $this->_tileImage = ImageCreateTrueColor( + $this->getWidth(), + $this->getHeight() + ); + + ImageCopyResampled( + $this->_tileImage, + $this->_fillStyle, + $x, + $y, + 0, + 0, + $w, + $h, + ImageSX($this->_fillStyle), + ImageSY($this->_fillStyle) + ); + } else { + $this->_tileImage = ImageCreate( + $this->getWidth(), + $this->getHeight() + ); + + ImageCopyResized( + $this->_tileImage, + $this->_fillStyle, + $x, + $y, + 0, + 0, + $w, + $h, + ImageSX($this->_fillStyle), + ImageSY($this->_fillStyle) + ); + } + ImageSetTile($this->_canvas, $this->_tileImage); + return IMG_COLOR_TILED; + } elseif ((is_array($this->_fillStyle)) && (isset($this->_fillStyle['direction']))) { + $width = abs($x1 - $x0) + 1; + $height = abs($y1 - $y0) + 1; + + switch ($this->_fillStyle['direction']) { + case 'horizontal': + $count = $width; + break; + + case 'vertical': + $count = $height; + break; + + case 'horizontal_mirror': + $count = $width / 2; + break; + + case 'vertical_mirror': + $count = $height / 2; + break; + + case 'diagonal_tl_br': + case 'diagonal_bl_tr': + $count = sqrt($width * $width + $height * $height); + break; + + case 'radial': + $count = max($width, $height, sqrt($width * $width + $height * $height)) + 1; + break; + + } + + $count = round($count); + + if ($this->_gd2) { + $this->_tileImage = ImageCreateTrueColor( + $this->getWidth(), + $this->getHeight() + ); + } else { + $this->_tileImage = ImageCreate( + $this->getWidth(), + $this->getHeight() + ); + } + + + $startColor = Image_Canvas_Color::color2RGB( + ($this->_fillStyle['direction'] == 'radial' ? + $this->_fillStyle['end'] : + $this->_fillStyle['start'] + ) + ); + $endColor = Image_Canvas_Color::color2RGB( + ($this->_fillStyle['direction'] == 'radial' ? + $this->_fillStyle['start'] : + $this->_fillStyle['end'] + ) + ); + + $redIncrement = ($endColor[0] - $startColor[0]) / $count; + $greenIncrement = ($endColor[1] - $startColor[1]) / $count; + $blueIncrement = ($endColor[2] - $startColor[2]) / $count; + + $color = false; + for ($i = 0; $i < $count; $i ++) { + unset($color); + if ($i == 0) { + $color = $startColor; + unset($color[3]); + } else { + $color[0] = round(($redIncrement * $i) + + $redIncrement + $startColor[0]); + $color[1] = round(($greenIncrement * $i) + + $greenIncrement + $startColor[1]); + $color[2] = round(($blueIncrement * $i) + + $blueIncrement + $startColor[2]); + } + $color = Image_Canvas_Color::allocateColor( + $this->_tileImage, + $color + ); + + switch ($this->_fillStyle['direction']) { + case 'horizontal': + ImageLine($this->_tileImage, + $x0 + $i, + $y0, + $x0 + $i, + $y1, $color); + break; + + case 'vertical': + ImageLine($this->_tileImage, + $x0, + $y1 - $i, + $x1, + $y1 - $i, $color); + break; + + case 'horizontal_mirror': + if (($x0 + $i) <= ($x1 - $i)) { + ImageLine($this->_tileImage, + $x0 + $i, + $y0, + $x0 + $i, + $y1, $color); + + ImageLine($this->_tileImage, + $x1 - $i, + $y0, + $x1 - $i, + $y1, $color); + } + break; + + case 'vertical_mirror': + if (($y0 + $i) <= ($y1 - $i)) { + ImageLine($this->_tileImage, + $x0, + $y0 + $i, + $x1, + $y0 + $i, $color); + ImageLine($this->_tileImage, + $x0, + $y1 - $i, + $x1, + $y1 - $i, $color); + } + break; + + case 'diagonal_tl_br': + if (($i > $width) && ($i > $height)) { + $polygon = array ( + $x1, $y0 + $i - $width - 1, + $x1, $y1, + $x0 + $i - $height - 1, $y1); + } elseif ($i > $width) { + $polygon = array ( + $x0, $y0 + $i, + $x0, $y1, + $x1, $y1, + $x1, $y0 + $i - $width - 1); + } elseif ($i > $height) { + $polygon = array ( + $x0 + $i - $height - 1, $y1, + $x1, $y1, + $x1, $y0, + $x0 + $i, $y0); + } else { + $polygon = array ( + $x0, $y0 + $i, + $x0, $y1, + $x1, $y1, + $x1, $y0, + $x0 + $i, $y0); + } + ImageFilledPolygon( + $this->_tileImage, + $polygon, + count($polygon) / 2, + $color + ); + break; + + case 'diagonal_bl_tr': + if (($i > $width) && ($i > $height)) { + $polygon = array ( + $x1, $y1 - $i + $width - 1, + $x1, $y0, + $x0 + $i - $height - 1, $y0); + } elseif ($i > $width) { + $polygon = array ( + $x0, $y1 - $i, + $x0, $y0, + $x1, $y0, + $x1, $y1 - $i + $width - 1); + } elseif ($i > $height) { + $polygon = array ( + $x0 + $i - $height - 1, $y0, + $x1, $y0, + $x1, $y1, + $x0 + $i, $y1); + } else { + $polygon = array ( + $x0, $y1 - $i, + $x0, $y0, + $x1, $y0, + $x1, $y1, + $x0 + $i, $y1); + } + ImageFilledPolygon( + $this->_tileImage, + $polygon, + count($polygon) / 2, + $color + ); + break; + + case 'radial': + if (($this->_gd2) && ($i < $count)) { + ImageFilledEllipse( + $this->_tileImage, + $x0 + $width / 2, + $y0 + $height / 2, + $count - $i, + $count - $i, + $color + ); + } + break; + } + } + ImageSetTile($this->_canvas, $this->_tileImage); + return IMG_COLOR_TILED; + } else { + return $this->_color($this->_fillStyle); + } + } else { + return $this->_color($fillStyle); + } + } + + /** + * Sets an image that should be used for filling + * + * @param string $filename The filename of the image to fill with + */ + function setFillImage($filename) + { + $this->_fillStyle =& $this->_getGD($filename); + } + + /** + * Sets the font options. + * + * The $font array may have the following entries: + * + * 'ttf' = the .ttf file (either the basename, filename or full path) + * If 'ttf' is specified, then the following can be specified + * + * 'size' = size in pixels + * + * 'angle' = the angle with which to write the text + * + * @param array $font The font options. + */ + function setFont($fontOptions) + { + parent::setFont($fontOptions); + + if (isset($this->_font['ttf'])) { + $this->_font['file'] = str_replace('\\', '/', $this->_mapFont($this->_font['ttf'])); + } elseif (!isset($this->_font['font'])) { + $this->_font['font'] = 1; + } + + if (!isset($this->_font['color'])) { + $this->_font['color'] = 'black'; + } + + if ((isset($this->_font['angle'])) && ($this->_font['angle'] === false)) { + $this->_font['angle'] = 0; + } + } + + /** + * Calculate pixels on a line + * + * @param int $x0 X start point + * @param int $y0 X start point + * @param int $x1 X end point + * @param int $y1 Y end point + * @return array An associated array of x,y points with all pixels on the + * line + * @access private + */ + function &_linePixels($x0, $y0, $x1, $y1) + { + $pixels = array(); + if (abs($x0 - $x1) > abs($y0 - $y1)) { + if ($x1 != $x0) { + $m = ($y1 - $y0) / ($x1 - $x0); + } else { + $m = 0; + } + $b = $y0 - $m * $x0; + $strx = min($x0, $x1); + $endx = max($x0, $x1); + for ($x = $strx; $x <= $endx; $x++) { + $pixels[] = array('X' => $x, 'Y' => ($m * $x + $b)); + } + } else { + if ($y1 != $y0) { + $m = ($x1 - $x0) / ($y1 - $y0); + } else { + $m = 0; + } + $b = $x0 - $m * $y0; + $stry = min($y0, $y1); + $endy = max($y0, $y1); + for ($y = $stry; $y <= $endy; $y++) { + $pixels[] = array('X' => ($m * $y + $b), 'Y' => $y); + } + } + return $pixels; + } + + /** + * Draws an antialiased line + * + * @param int $x0 X start point + * @param int $y0 X start point + * @param int $x1 X end point + * @param int $y1 Y end point + * @param mixed $color The line color, can be omitted + * @access private + */ + function _antialiasedLine($x0, $y0, $x1, $y1, $color = false) + { + if (($line = $this->_getLineStyle($color)) !== false) { + if ($line >= 0) { + $line = ImageColorsForIndex($this->_canvas, $line); + $pixels = &$this->_linePixels($x0, $y0, $x1, $y1); + foreach ($pixels as $point) { + $this->_antialiasedPixel($point['X'], $point['Y'], $line); + } + unset($pixels); + } + } + } + + + /** + * Draws an antialiased pixel + * + * @param int $x X point + * @param int $y Y point + * @param mixed $color The pixel color + * @access private + */ + function _antialiasedPixel($x, $y, $color) + { + $fx = floor($x); + $fy = floor($y); + $cx = ceil($x); + $cy = ceil($y); + $xa = $x - $fx; + $xb = $cx - $x; + $ya = $y - $fy; + $yb = $cy - $y; + if (($cx == $fx) && ($cy == $fy)) { + $this->_antialisedSubPixel($fx, $fy, 0.0, 1.0, $color); + } else { + $this->_antialisedSubPixel($fx, $fy, $xa + $ya, $xb + $yb, $color); + if ($cy != $fy) { + $this->_antialisedSubPixel($fx, $cy, $xa + $yb, $xb + $ya, $color); + } + if ($cx != $fx) { + $this->_antialisedSubPixel($cx, $fy, $xb + $ya, $xa + $yb, $color); + if ($cy != $fy) { + $this->_antialisedSubPixel($cx, $cy, $xb + $yb, $xa + $ya, $color); + } + } + } + } + + /** + * Antialias'es the pixel around x,y with weights a,b + * + * @param int $x X point + * @param int $y Y point + * @param int $a The weight of the current color + * @param int $b The weight of the applied/wanted color + * @param mixed $color The pixel color + * @access private + */ + function _antialisedSubPixel($x, $y, $a, $b, $color) + { + $x = $this->_getX($x); + $y = $this->_getX($y); + if (($x >=0 ) && ($y >= 0) && ($x < $this->getWidth()) && ($y < $this->getHeight())) { + $tempColor = ImageColorsForIndex($this->_canvas, ImageColorAt($this->_canvas, $x, $y)); + + $newColor[0] = min(255, round($tempColor['red'] * $a + $color['red'] * $b)); + $newColor[1] = min(255, round($tempColor['green'] * $a + $color['green'] * $b)); + $newColor[2] = min(255, round($tempColor['blue'] * $a + $color['blue'] * $b)); + //$newColor[3] = 0; + $color = '#'; + foreach ($newColor as $acolor) { + $color .= sprintf('%02s', dechex($acolor)); + } + $newColor = $this->_color($color);//,'rgb(' . $newColor[0] . ',' . $newColor[1] . ',' . $newColor[2] .')'; + + ImageSetPixel($this->_canvas, $x, $y, $newColor); + } + } + + + /** + * Draw a line end + * + * Parameter array: + * + * 'x': int X point + * + * 'y': int Y point + * + * 'end': string The end type of the end + * + * 'size': int The size of the end + * + * 'color': string The color of the end + * + * 'angle': int [optional] The angle with which to draw the end + * + * @param array $params Parameter array + */ + function drawEnd($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $size = $params['size']; + //var_dump($params); + $angle = deg2rad((isset($params['angle']) ? $params['angle'] : 0)); + $pi2 = pi() / 2; + switch ($params['end']) { + case 'lollipop': + case 'circle': + $this->ellipse( + array( + 'x' => $x, + 'y' => $y, + 'rx' => $size / 2, + 'ry' => $size / 2, + 'fill' => $params['color'], + 'line' => $params['color'] + ) + ); + break; + case 'diamond': + $x0 = round($params['x'] + cos($angle) * $size * 0.65); + $y0 = round($params['y'] - sin($angle) * $size * 0.65); + $shape = array( + $x0 + round(cos($angle) * $size * 0.65), + $y0 - round(sin($angle) * $size * 0.65), + $x0 + round(cos($angle + $pi2) * $size * 0.65), + $y0 - round(sin($angle + $pi2) * $size * 0.65), + $x0 + round(cos($angle + pi()) * $size * 0.65), + $y0 - round(sin($angle + pi()) * $size * 0.65), + $x0 + round(cos($angle + 3 * $pi2) * $size * 0.65), + $y0 - round(sin($angle + 3 * $pi2) * $size * 0.65) + ); + break; + case 'line': + $this->line( + array( + 'x0' => $x + round(cos($angle + $pi2) * $size / 2), + 'y0' => $y - round(sin($angle + $pi2) * $size / 2), + 'x1' => $x + round(cos($angle + 3 * $pi2) * $size / 2), + 'y1' => $y - round(sin($angle + 3 * $pi2) * $size / 2), + 'color' => $params['color'] + ) + ); + break; + case 'box': + case 'rectangle': + $x0 = round($params['x'] + cos($angle) * $size / 2); + $y0 = round($params['y'] - sin($angle) * $size / 2); + $pi4 = pi() / 4; + $shape = array( + $x0 + round(cos($angle + $pi4) * $size / 2), + $y0 - round(sin($angle + $pi4) * $size / 2), + $x0 + round(cos($angle + $pi2 + $pi4) * $size / 2), + $y0 - round(sin($angle + $pi2 + $pi4) * $size / 2), + $x0 + round(cos($angle + pi() + $pi4) * $size / 2), + $y0 - round(sin($angle + pi() + $pi4) * $size / 2), + $x0 + round(cos($angle + 3 * $pi2 + $pi4) * $size / 2), + $y0 - round(sin($angle + 3 * $pi2 + $pi4) * $size / 2) + ); + break; + case 'arrow': + $shape = array( + $x + cos($angle) * $size, + $y - sin($angle) * $size, + $x + cos($angle + $pi2) * $size * 0.4, + $y - sin($angle + $pi2) * $size * 0.4, + $x + cos($angle + 3 * $pi2) * $size * 0.4, + $y - sin($angle + 3 * $pi2) * $size * 0.4, + ); + break; + case 'arrow2': + $shape = array( + $x + round(cos($angle) * $size), + $y - round(sin($angle) * $size), + $x + round(cos($angle + $pi2 + deg2rad(45)) * $size), + $y - round(sin($angle + $pi2 + deg2rad(45)) * $size), + $x, + $y, + $x + round(cos($angle + 3 * $pi2 - deg2rad(45)) * $size), + $y - round(sin($angle + 3 * $pi2 - deg2rad(45)) * $size), + ); + break; + } + + if (isset($shape)) { + // output the shape + if (($fill = $this->_getFillStyle($params['color'])) !== false) { + ImageFilledPolygon($this->_canvas, $shape, count($shape)/2, $fill); + } + } + parent::drawEnd($params); + } + + /** + * Draw a line + * + * Parameter array: + * + * 'x0': int X start point + * + * 'y0': int Y start point + * + * 'x1': int X end point + * + * 'y1': int Y end point + * + * 'color': mixed [optional] The line color + * + * @param array $params Parameter array + */ + function line($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + $color = (isset($params['color']) ? $params['color'] : false); + + $x0 = $this->_getX($x0); + $y0 = $this->_getY($y0); + $x1 = $this->_getX($x1); + $y1 = $this->_getY($y1); + if (($this->_antialias === 'driver') && ($x0 != $x1) && ($y0 != $y1)) { + $this->_antialiasedLine($x0, $y0, $x1, $y1, $color); + } elseif (($line = $this->_getLineStyle($color)) !== false) { + ImageLine($this->_canvas, $x0, $y0, $x1, $y1, $line); + } + parent::line($params); + } + + /** + * Parameter array: + * + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * + * 'fill': mixed [optional] The fill color + * + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params) + { + include_once 'Image/Canvas/Tool.php'; + + $connectEnds = (isset($params['connect']) ? $params['connect'] : false); + $fillColor = (isset($params['fill']) ? $params['fill'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + if (!$connectEnds) { + $fillColor = 'transparent'; + } + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + + $lastPoint = false; + foreach ($this->_polygon as $point) { + if (($lastPoint) && (isset($lastPoint['P1X'])) && + (isset($lastPoint['P1Y'])) && (isset($lastPoint['P2X'])) && + (isset($lastPoint['P2Y']))) + { + $dx = abs($point['X'] - $lastPoint['X']); + $dy = abs($point['Y'] - $lastPoint['Y']); + $d = sqrt($dx * $dx + $dy * $dy); + if ($d > 0) { + $interval = 1 / $d; + for ($t = 0; $t <= 1; $t = $t + $interval) { + $x = Image_Canvas_Tool::bezier( + $t, + $lastPoint['X'], + $lastPoint['P1X'], + $lastPoint['P2X'], + $point['X'] + ); + + $y = Image_Canvas_Tool::bezier( + $t, + $lastPoint['Y'], + $lastPoint['P1Y'], + $lastPoint['P2Y'], + $point['Y'] + ); + + if (!isset($low['X'])) { + $low['X'] = $x; + } else { + $low['X'] = min($x, $low['X']); + } + if (!isset($high['X'])) { + $high['X'] = $x; + } else { + $high['X'] = max($x, $high['X']); + } + if (!isset($low['Y'])) { + $low['Y'] = $y; + } else { + $low['Y'] = min($y, $low['Y']); + } + if (!isset($high['Y'])) { + $high['Y'] = $y; + } else { + $high['Y'] = max($y, $high['Y']); + } + $polygon[] = $x; + $polygon[] = $y; + } + if (($t - $interval) < 1) { + $x = Image_Canvas_Tool::bezier( + 1, + $lastPoint['X'], + $lastPoint['P1X'], + $lastPoint['P2X'], + $point['X'] + ); + + $y = Image_Canvas_Tool::bezier( + 1, + $lastPoint['Y'], + $lastPoint['P1Y'], + $lastPoint['P2Y'], + $point['Y'] + ); + + $polygon[] = $x; + $polygon[] = $y; + } + } + } else { + if (!isset($low['X'])) { + $low['X'] = $point['X']; + } else { + $low['X'] = min($point['X'], $low['X']); + } + if (!isset($high['X'])) { + $high['X'] = $point['X']; + } else { + $high['X'] = max($point['X'], $high['X']); + } + if (!isset($low['Y'])) { + $low['Y'] = $point['Y']; + } else { + $low['Y'] = min($point['Y'], $low['Y']); + } + if (!isset($high['Y'])) { + $high['Y'] = $point['Y']; + } else { + $high['Y'] = max($point['Y'], $high['Y']); + } + + $polygon[] = $point['X']; + $polygon[] = $point['Y']; + } + $lastPoint = $point; + } + + if ((isset($polygon)) && (is_array($polygon))) { + if ($connectEnds) { + if (($fill = $this->_getFillStyle($fillColor, $low['X'], $low['Y'], $high['X'], $high['Y'])) !== false) { + ImageFilledPolygon($this->_canvas, $polygon, count($polygon)/2, $fill); + } + if ($this->_antialias === 'driver') { + $pfirst = $p0 = false; + reset($polygon); + + while (list(, $x) = each($polygon)) { + list(, $y) = each($polygon); + if ($p0 !== false) { + $this->_antialiasedLine($p0['X'], $p0['Y'], $x, $y, $lineColor); + } + if ($pfirst === false) { + $pfirst = array('X' => $x, 'Y' => $y); + } + $p0 = array('X' => $x, 'Y' => $y);; + } + + $this->_antialiasedLine($p0['X'], $p0['Y'], $pfirst['X'], $pfirst['Y'], $lineColor); + } elseif (($line = $this->_getLineStyle($lineColor)) !== false) { + ImagePolygon($this->_canvas, $polygon, count($polygon)/2, $line); + } + } else { + $prev_point = false; + if ($this->_antialias === 'driver') { + reset($polygon); + while (list(, $x) = each($polygon)) { + list(, $y) = each($polygon); + if ($prev_point) { + $this->_antialiasedLine( + $prev_point['X'], + $prev_point['Y'], + $x, + $y, + $lineColor + ); + } + $prev_point = array('X' => $x, 'Y' => $y);; + } + } elseif (($line = $this->_getLineStyle($lineColor)) !== false) { + reset($polygon); + while (list(, $x) = each($polygon)) { + list(, $y) = each($polygon); + if ($prev_point) { + ImageLine( + $this->_canvas, + $prev_point['X'], + $prev_point['Y'], + $x, + $y, + $line + ); + } + $prev_point = array('X' => $x, 'Y' => $y);; + } + } + } + } + + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * + * 'x0': int X start point + * + * 'y0': int Y start point + * + * 'x1': int X end point + * + * 'y1': int Y end point + * + * 'fill': mixed [optional] The fill color + * + * 'line': mixed [optional] The line color + * + * @param array $params Parameter array + */ + function rectangle($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + $fillColor = (isset($params['fill']) ? $params['fill'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + if (($fill = $this->_getFillStyle($fillColor, $x0, $y0, $x1, $y1)) !== false) { + ImageFilledRectangle($this->_canvas, $x0, $y0, $x1, $y1, $fill); + } + + if (($line = $this->_getLineStyle($lineColor)) !== false) { + ImageRectangle($this->_canvas, $x0, $y0, $x1, $y1, $line); + } + + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * + * 'x': int X center point + * + * 'y': int Y center point + * + * 'rx': int X radius + * + * 'ry': int Y radius + * + * 'fill': mixed [optional] The fill color + * + * 'line': mixed [optional] The line color + * + * @param array $params Parameter array + */ + function ellipse($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $this->_getX($params['rx']); + $ry = $this->_getY($params['ry']); + $fillColor = (isset($params['fill']) ? $params['fill'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + if (($fill = $this->_getFillStyle($fillColor, $x - $rx, $y - $ry, $x + $rx, $y + $ry)) !== false) { + ImageFilledEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $fill); + } + + if (($line = $this->_getLineStyle($lineColor)) !== false) { + ImageEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $line); + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * + * 'x': int X center point + * + * 'y': int Y center point + * + * 'rx': int X radius + * + * 'ry': int Y radius + * + * 'v1': int The starting angle (in degrees) + * + * 'v2': int The end angle (in degrees) + * + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * + * 'fill': mixed [optional] The fill color + * + * 'line': mixed [optional] The line color + * + * @param array $params Parameter array + */ + function pieslice($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $params['rx']; + $ry = $params['ry']; + $v1 = $params['v1']; + $v2 = $params['v2']; + $srx = (isset($params['srx']) ? $params['srx'] : 0); + $sry = (isset($params['sry']) ? $params['sry'] : 0); + $fillColor = (isset($params['fill']) ? $params['fill'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $dA = 0.1; + + if (($srx !== false) && ($sry !== false)) { + $angle = max($v1, $v2); + while ($angle >= min($v1, $v2)) { + $polygon[] = ($x + $srx * cos(deg2rad($angle % 360))); + $polygon[] = ($y + $sry * sin(deg2rad($angle % 360))); + $angle -= $dA; + } + if (($angle + $dA) > min($v1, $v2)) { + $polygon[] = ($x + $srx * cos(deg2rad(min($v1, $v2) % 360))); + $polygon[] = ($y + $sry * sin(deg2rad(min($v1, $v2) % 360))); + } + } else { + $polygon[] = $x; + $polygon[] = $y; + } + + $angle = min($v1, $v2); + while ($angle <= max($v1, $v2)) { + $polygon[] = ($x + $rx * cos(deg2rad($angle % 360))); + $polygon[] = ($y + $ry * sin(deg2rad($angle % 360))); + $angle += $dA; + } + + if (($angle - $dA) < max($v1, $v2)) { + $polygon[] = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360))); + $polygon[] = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360))); + } + + if (($fill = $this->_getFillStyle($fillColor, $x - $rx - 1, $y - $ry - 1, $x + $rx + 1, $y + $ry + 1)) !== false) { + ImageFilledPolygon($this->_canvas, $polygon, count($polygon) / 2, $fill); + } + + if (($line = $this->_getLineStyle($lineColor)) !== false) { + ImagePolygon($this->_canvas, $polygon, count($polygon) / 2, $line); + } + + parent::pieSlice($params); + } + + /** + * Get the width of a text, + * + * @param string $text The text to get the width of + * @return int The width of the text + */ + function textWidth($text) + { + if (isset($this->_font['file'])) { + $angle = 0; + if (isset($this->_font['angle'])) { + $angle = $this->_font['angle']; + } + + $width = 0; + $lines = explode("\n", $text); + foreach ($lines as $line) { + $bounds = ImageTTFBBox( + $this->_font['size'], + $angle, + $this->_font['file'], + $text + ); + + $x0 = min($bounds[0], $bounds[2], $bounds[4], $bounds[6]); + $x1 = max($bounds[0], $bounds[2], $bounds[4], $bounds[6]); + $width = max(abs($x0 - $x1), $width); + } + return $width; + } else { + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1); + } else { + $width = 0; + $lines = explode("\n", $text); + foreach ($lines as $line) { + $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line)); + } + return $width; + } + } + } + + /** + * Get the height of a text. + * + * Note! This method can give some peculiar results, since ImageTTFBBox() returns the total + * bounding box of a text, where ImageTTF() writes the text on the baseline of the text, that + * is 'g', 'p', 'q' and other letters that dig under the baseline will appear to have a larger + * height than they actually do. Have a look at the tests/text.php test case - the first two + * columns, 'left and 'center', both look alright, whereas the last column, 'right', appear + * with a larger space between the first text and the second. This is because the total height + * is actually smaller by exactly the number of pixels that the 'g' digs under the baseline. + * Remove the 'g' from the text and they appear correct. + * + * @param string $text The text to get the height of + * @param bool $force Force the method to calculate the size + * @return int The height of the text + */ + function textHeight($text, $force = false) + { + if (isset($this->_font['file'])) { + $angle = 0; + if (isset($this->_font['angle'])) { + $angle = $this->_font['angle']; + } + + $linebreaks = substr_count($text, "\n"); + if (($angle == 0) && ($linebreaks == 0) && ($force === false)) { + /* + * if the angle is 0 simply return the size, due to different + * heights for example for x-axis labels, making the labels + * _not_ appear as written on the same baseline + */ + return $this->_font['size'] + 2; + } + + $height = 0; + $lines = explode("\n", $text); + foreach ($lines as $line) { + $bounds = ImageTTFBBox( + $this->_font['size'], + $angle, + $this->_font['file'], + $line + ); + + $y0 = min($bounds[1], $bounds[3], $bounds[5], $bounds[7]); + $y1 = max($bounds[1], $bounds[3], $bounds[5], $bounds[7]); + $height += abs($y0 - $y1); + } + return $height + $linebreaks * 2; + } else { + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + $width = 0; + $lines = explode("\n", $text); + foreach ($lines as $line) { + $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line)); + } + return $width; + } else { + return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1); + } + } + } + + /** + * Writes text + * + * Parameter array: + * + * 'x': int X-point of text + * + * 'y': int Y-point of text + * + * 'text': string The text to add + * + * 'alignment': array [optional] Alignment + * + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + $x0 = $this->_getX($params['x']); + $y0 = $this->_getY($params['y']); + $text = $params['text']; + $color = (isset($params['color']) ? $params['color'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + $text = str_replace("\r", '', $text); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + if ($alignment['vertical'] == 'bottom') { + $y0 = $y0 - $this->textHeight($text, true); + } elseif ($alignment['vertical'] == 'center') { + $y0 = $y0 - ($this->textHeight($text, true) / 2); + } + + $lines = explode("\n", $text); + foreach ($lines as $line) { + $textWidth = $this->textWidth($line); + $textHeight = $this->textHeight($line, true); + + $x = $x0; + $y = $y0; + + $y0 += $textHeight + 2; + + if ($alignment['horizontal'] == 'right') { + $x = $x - $textWidth; + } elseif ($alignment['horizontal'] == 'center') { + $x = $x - ($textWidth / 2); + } + + if (($color === false) && (isset($this->_font['color']))) { + $color = $this->_font['color']; + } + + if ($color != 'transparent') { + if (isset($this->_font['file'])) { + if (($this->_font['angle'] < 180) && ($this->_font['angle'] >= 0)) { + $y += $textHeight; + } + if (($this->_font['angle'] >= 90) && ($this->_font['angle'] < 270)) { + $x += $textWidth; + } + + ImageTTFText( + $this->_canvas, + $this->_font['size'], + $this->_font['angle'], + $x, + $y, + $this->_color($color), + $this->_font['file'], + $line + ); + + } else { + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + ImageStringUp( + $this->_canvas, + $this->_font['font'], + $x, + $y + $this->textHeight($text), + $line, + $this->_color($color) + ); + } else { + ImageString( + $this->_canvas, + $this->_font['font'], + $x, + $y, + $line, + $this->_color($color) + ); + } + } + } + } + parent::addText($params); + } + + /** + * Overlay image + * + * Parameter array: + * + * 'x': int X-point of overlayed image + * + * 'y': int Y-point of overlayed image + * + * 'filename': string The filename of the image to overlay + * + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * + * 'alignment': array [optional] Alignment + */ + function image($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $filename = $params['filename']; + $width = (isset($params['width']) ? $params['width'] : false); + $height = (isset($params['height']) ? $params['height'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + if (file_exists($filename)) { + if (strtolower(substr($filename, -4)) == '.png') { + $image = ImageCreateFromPNG($filename); + } elseif (strtolower(substr($filename, -4)) == '.gif') { + $image = ImageCreateFromGIF($filename); + } else { + $image = ImageCreateFromJPEG($filename); + } + + $imgWidth = ImageSX($image); + $imgHeight = ImageSY($image); + + $outputWidth = ($width !== false ? $width : $imgWidth); + $outputHeight = ($height !== false ? $height : $imgHeight); + + if ($alignment['horizontal'] == 'right') { + $x -= $outputWidth; + } elseif ($alignment['horizontal'] == 'center') { + $x -= $outputWidth / 2; + } + + if ($alignment['vertical'] == 'bottom') { + $y -= $outputHeight; + } elseif ($alignment['vertical'] == 'center') { + $y -= $outputHeight / 2; + } + + if ((($width !== false) && ($width != $imgWidth)) || + (($height !== false) && ($height != $imgHeight))) + { + if ($this->_gd2) { + ImageCopyResampled( + $this->_canvas, + $image, + $x, + $y, + 0, + 0, + $width, + $height, + $imgWidth, + $imgHeight + ); + } else { + ImageCopyResized( + $this->_canvas, + $image, + $x, + $y, + 0, + 0, + $width, + $height, + $imgWidth, + $imgHeight + ); + } + } else { + ImageCopy( + $this->_canvas, + $image, + $x, + $y, + 0, + 0, + $imgWidth, + $imgHeight + ); + } + ImageDestroy($image); + } + parent::image($params); + } + + /** + * Get a canvas specific HTML tag. + * + * This method implicitly saves the canvas to the filename in the + * filesystem path specified and parses it as URL specified by URL path + * + * Parameter array: + * + * 'filename' string + * + * 'filepath': string Path to the file on the file system. Remember the final slash + * + * 'urlpath': string Path to the file available through an URL. Remember the final slash + * + * 'alt': string [optional] Alternative text on image + * + * 'cssclass': string [optional] The CSS Stylesheet class + * + * 'border': int [optional] The border width on the image + */ + function toHtml($params) + { + parent::toHtml($params); + return '' . $params['alt'] . '_imageMap) ? ' usemap="#' . $params['filename'] . '"' : '') . '>' . + (isset($this->_imageMap) ? "\n" . $this->_imageMap->toHtml(array('name' => $params['filename'])) : ''); + } + + /** + * Resets the canvas. + * + * Include fillstyle, linestyle, thickness and polygon + * @access private + */ + function _reset() + { + if ($this->_gd2) { + ImageSetThickness($this->_canvas, 1); + } + if ($this->_tileImage != null) { + ImageDestroy($this->_tileImage); + $this->_tileImage = null; + } + parent::_reset(); + $this->_font = array('font' => 1, 'color' => 'black'); + } + + /** + * Check which version of GD is installed + * + * @return int 0 if GD isn't installed, 1 if GD 1.x is installed and 2 if GD + * 2.x is installed + * @access private + */ + function _version() + { + $result = false; + if (function_exists('gd_info')) { + $info = gd_info(); + $version = $info['GD Version']; + } else { + ob_start(); + phpinfo(8); + $php_info = ob_get_contents(); + ob_end_clean(); + + if (ereg("]*>GD Version *<\/td>]*>([^<]*)<\/td>", + $php_info, $result)) + { + $version = $result[1]; + } + } + + if (ereg('1\.[0-9]{1,2}', $version)) { + return 1; + } elseif (ereg('2\.[0-9]{1,2}', $version)) { + return 2; + } else { + return 0; + } + } + +} + +?> diff --git a/pandora_console/reporting/Image/Canvas/GD/JPG.php b/pandora_console/reporting/Image/Canvas/GD/JPG.php index f8c6f7b489..392fd6bd60 100644 --- a/pandora_console/reporting/Image/Canvas/GD/JPG.php +++ b/pandora_console/reporting/Image/Canvas/GD/JPG.php @@ -1,119 +1,119 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: JPG.php,v 1.2 2005/08/24 20:37:34 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas/GD.php - */ -require_once 'Image/Canvas/GD.php'; - -/** - * JPEG Canvas class. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ -class Image_Canvas_GD_JPG extends Image_Canvas_GD -{ - - /** - * The JPEG quality - * @var int - * @access private - */ - var $_quality = 75; - - /** - * Create the JPEG canvas - * - * Additional parameters other than those available for common {@link - * Image_Graph_Canvas_GD} class are: - * - * 'quality' The JPEG quality in as a percentage value from 0 (lowest - * quality, smallest file) to 100 (highest quality, biggest file) - * - * @param array $param Parameter array - */ - function Image_Canvas_GD_JPG($param) - { - parent::Image_Canvas_GD($param); - - if (isset($param['quality'])) { - $this->_quality = max(0, min(100, $param['quality'])); - } - - $this->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_left + $this->_width - 1, - 'y1' => $this->_top + $this->_height - 1, - 'fill' => 'white', - 'line' => 'transparent' - ) - ); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function show($param = false) - { - parent::show($param); - header('Content-type: image/jpg'); - header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.jpg\"'); - ImageJPEG($this->_canvas, '', $this->_quality); - ImageDestroy($this->_canvas); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function save($param = false) - { - parent::save($param); - ImageJPEG($this->_canvas, $param['filename'], $this->_quality); - ImageDestroy($this->_canvas); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: JPG.php,v 1.2 2005/08/24 20:37:34 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas/GD.php + */ +require_once 'Image/Canvas/GD.php'; + +/** + * JPEG Canvas class. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ +class Image_Canvas_GD_JPG extends Image_Canvas_GD +{ + + /** + * The JPEG quality + * @var int + * @access private + */ + var $_quality = 75; + + /** + * Create the JPEG canvas + * + * Additional parameters other than those available for common {@link + * Image_Graph_Canvas_GD} class are: + * + * 'quality' The JPEG quality in as a percentage value from 0 (lowest + * quality, smallest file) to 100 (highest quality, biggest file) + * + * @param array $param Parameter array + */ + function Image_Canvas_GD_JPG($param) + { + parent::Image_Canvas_GD($param); + + if (isset($param['quality'])) { + $this->_quality = max(0, min(100, $param['quality'])); + } + + $this->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_left + $this->_width - 1, + 'y1' => $this->_top + $this->_height - 1, + 'fill' => 'white', + 'line' => 'transparent' + ) + ); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function show($param = false) + { + parent::show($param); + header('Content-type: image/jpg'); + header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.jpg\"'); + ImageJPEG($this->_canvas, '', $this->_quality); + ImageDestroy($this->_canvas); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function save($param = false) + { + parent::save($param); + ImageJPEG($this->_canvas, $param['filename'], $this->_quality); + ImageDestroy($this->_canvas); + } + +} + ?> \ No newline at end of file diff --git a/pandora_console/reporting/Image/Canvas/GD/PNG.php b/pandora_console/reporting/Image/Canvas/GD/PNG.php index 45d9f81f7a..5659d8b2ca 100644 --- a/pandora_console/reporting/Image/Canvas/GD/PNG.php +++ b/pandora_console/reporting/Image/Canvas/GD/PNG.php @@ -1,125 +1,125 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: PNG.php,v 1.3 2005/08/24 20:37:34 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas/GD.php - */ -require_once 'Image/Canvas/GD.php'; - -/** - * PNG Canvas class. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ -class Image_Canvas_GD_PNG extends Image_Canvas_GD -{ - - /** - * Create the PNG canvas - * - * @param array $param Parameter array - */ - function Image_Canvas_GD_PNG($param) - { - parent::Image_Canvas_GD($param); - - if ((isset($param['transparent'])) && ($param['transparent']) && - ($this->_gd2) - ) { - if ($param['transparent'] === true) { - $transparent = '#123ABD'; - } else { - $transparent = $param['transparent']; - } - $color = $this->_color($transparent); - $trans = ImageColorTransparent($this->_canvas, $color); - - $this->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_left + $this->_width - 1, - 'y1' => $this->_top + $this->_height - 1, - 'fill' => 'opague', - 'line' => 'transparent' - ) - ); - } else { - $this->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_left + $this->_width - 1, - 'y1' => $this->_top + $this->_height - 1, - 'fill' => 'white', - 'line' => 'transparent' - ) - ); - } - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function show($param = false) - { - parent::show($param); - header('Content-type: image/png'); - header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.png\"'); - ImagePNG($this->_canvas); - ImageDestroy($this->_canvas); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function save($param = false) - { - parent::save($param); - ImagePNG($this->_canvas, $param['filename']); - ImageDestroy($this->_canvas); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: PNG.php,v 1.3 2005/08/24 20:37:34 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas/GD.php + */ +require_once 'Image/Canvas/GD.php'; + +/** + * PNG Canvas class. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ +class Image_Canvas_GD_PNG extends Image_Canvas_GD +{ + + /** + * Create the PNG canvas + * + * @param array $param Parameter array + */ + function Image_Canvas_GD_PNG($param) + { + parent::Image_Canvas_GD($param); + + if ((isset($param['transparent'])) && ($param['transparent']) && + ($this->_gd2) + ) { + if ($param['transparent'] === true) { + $transparent = '#123ABD'; + } else { + $transparent = $param['transparent']; + } + $color = $this->_color($transparent); + $trans = ImageColorTransparent($this->_canvas, $color); + + $this->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_left + $this->_width - 1, + 'y1' => $this->_top + $this->_height - 1, + 'fill' => 'opague', + 'line' => 'transparent' + ) + ); + } else { + $this->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_left + $this->_width - 1, + 'y1' => $this->_top + $this->_height - 1, + 'fill' => 'white', + 'line' => 'transparent' + ) + ); + } + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function show($param = false) + { + parent::show($param); + header('Content-type: image/png'); + header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.png\"'); + ImagePNG($this->_canvas); + ImageDestroy($this->_canvas); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function save($param = false) + { + parent::save($param); + ImagePNG($this->_canvas, $param['filename']); + ImageDestroy($this->_canvas); + } + +} + ?> \ No newline at end of file diff --git a/pandora_console/reporting/Image/Canvas/ImageMap.php b/pandora_console/reporting/Image/Canvas/ImageMap.php index bfd3676122..925de9fb06 100644 --- a/pandora_console/reporting/Image/Canvas/ImageMap.php +++ b/pandora_console/reporting/Image/Canvas/ImageMap.php @@ -1,354 +1,354 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: ImageMap.php,v 1.6 2005/08/17 17:59:11 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Class for handling output as a HTML imagemap - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @since version 0.2.0 - */ -class Image_Canvas_ImageMap extends Image_Canvas -{ - - /** - * The image map (if any) - * @var array - * @access private - */ - var $_map = array(); - - /** - * Add a map tag - * @param string $shape The shape, either rect, circle or polygon - * @param string $coords The list of coordinates for the shape - * @param array $params Parameter array - */ - function _addMapTag($shape, $coords, $params) - { - if (isset($params['url'])) { - $url = $params['url']; - $target = (isset($params['target']) ? $params['target'] : false); - $alt = (isset($params['alt']) ? $params['alt'] : false); - - $tags = ''; - if (isset($params['htmltags'])) { - foreach ($params['htmltags'] as $key => $value) { - $tags .= ' '; - if (strpos($value, '"') >= 0) { - $tags .= $key . '=\'' . $value . '\''; - } else { - $tags .= $key . '="' . $value . '"'; - } - } - } - - $this->_map[] = - '' . $alt . ''; - } - } - - /** - * Draw a line - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'color': mixed [optional] The line color - * 'mapsize': int [optional] The size of the image map (surrounding the line) - * @param array $params Parameter array - */ - function line($params) - { - if (isset($params['url'])) { - $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2); - $this->_addMapTag( - 'polygon', - $this->_getX($params['x0'] - $mapsize) . ',' . - $this->_getY($params['y0'] - $mapsize) . ',' . - $this->_getX($params['x1'] + $mapsize) . ',' . - $this->_getY($params['y1'] - $mapsize) . ',' . - - $this->_getX($params['x1'] + $mapsize) . ',' . - $this->_getY($params['y1'] + $mapsize) . ',' . - $this->_getX($params['x0'] - $mapsize) . ',' . - $this->_getY($params['y0'] + $mapsize), - $params - ); - } - parent::line($params); - } - - /** - * Draws a polygon - * - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * 'map_vertices': bool [optional] Specifies whether the image map should map the vertices instead of the polygon as a whole - * 'url': string [optional] URL to link the polygon as a whole to (also used for default in case 'map_vertices' is used) - * 'alt': string [optional] Alternative text to show in the image map (also used for default in case 'map_vertices' is used) - * 'target': string [optional] The link target on the image map (also used for default in case 'map_vertices' is used) - * @param array $params Parameter array - */ - function polygon($params) - { - if ((isset($params['map_vertices'])) && ($params['map_vertices'] === true)) { - $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2); - foreach ($this->_polygon as $point) { - $vertex_param = $params; - if (isset($point['url'])) { - $vertex_param['url'] = $point['url']; - } - if (isset($point['target'])) { - $vertex_param['target'] = $point['target']; - } - if (isset($point['alt'])) { - $vertex_param['alt'] = $point['alt']; - } - $vertex_mapsize = $mapsize; - if (isset($point['mapsize'])) { - $vertex_mapsize = $point['mapsize']; - } - if (isset($point['htmltags'])) { - $vertex_param['htmltags'] = $point['htmltags']; - } - $this->_addMapTag( - 'circle', - $this->_getX($point['X']) . ',' . - $this->_getY($point['Y']) . ',' . - $mapsize, - $vertex_param - ); - } - } - else if (isset($params['url'])) { - $points = ''; - foreach ($this->_polygon as $point) { - if ($points != '') { - $points .= ','; - } - $points .= $this->_getX($point['X']) . ',' . $this->_getY($point['Y']); - } - $this->_addMapTag('polygon', $points, $params); - } - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - if (isset($params['url'])) { - $this->_addMapTag( - 'rect', - $this->_getX($params['x0']) . ',' . - $this->_getY($params['y0']) . ',' . - $this->_getX($params['x1']) . ',' . - $this->_getY($params['y1']), - $params - ); - } - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - if (isset($params['url'])) { - if ($params['rx'] == $params['ry']) { - $this->_addMapTag( - 'circle', - $this->_getX($params['x']) . ',' . - $this->_getY($params['y']) . ',' . - $this->_getX($params['rx']), - $params - ); - } else { - $points = ''; - for ($v = 0; $v <= 360; $v += 30) { - if ($points != '') { - $points .= ','; - } - $points .= - round($this->_getX($params['x']) + $this->_getX($params['rx']) * cos(deg2rad($v % 360))) . ',' . - round($this->_getY($params['y']) + $this->_getX($params['ry']) * sin(deg2rad($v % 360))); - } - $this->_addMapTag( - 'polygon', - $points, - $params - ); - } - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - if (isset($params['url'])) { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $params['rx']; - $ry = $params['ry']; - $v1a = $params['v1']; - $v2a = $params['v2']; - $v1 = min($v1a, $v2a); - $v2 = max($v1a, $v2a); - $srx = (isset($params['srx']) ? $params['srx'] : 0); - $sry = (isset($params['sry']) ? $params['sry'] : 0); - - $points = - round(($x + $srx * cos(deg2rad($v1 % 360)))) . ',' . - round(($y + $sry * sin(deg2rad($v1 % 360)))) . ','; - - for ($v = $v1; $v < $v2; $v += 30) { - $points .= - round(($x + $rx * cos(deg2rad($v % 360)))) . ',' . - round(($y + $ry * sin(deg2rad($v % 360)))) . ','; - } - - $points .= - round(($x + $rx * cos(deg2rad($v2 % 360)))) . ',' . - round(($y + $ry * sin(deg2rad($v2 % 360)))); - - if (($srx != 0) || ($sry != 0)) { - $points .= ','; - for ($v = $v2; $v > $v1; $v -= 30) { - $points .= - round(($x + $srx * cos(deg2rad($v % 360)))) . ',' . - round(($y + $sry * sin(deg2rad($v % 360)))) . ','; - } - - } - - $this->_addMapTag('polygon', $points, $params); - } - parent::pieslice($params); - } - - /** - * Output the result of the canvas to the browser - * - * @param array $params Parameter array, the contents and meaning depends on the actual Canvas - * @abstract - */ - function show($params = false) - { - parent::show($params); - if (count($this->_map) > 0) { - print $this->toHtml($params); - } - } - - /** - * Save the result of the canvas to a file - * - * Parameter array: - * 'filename': string The file to output to - * @param array $params Parameter array, the contents and meaning depends on the actual Canvas - * @abstract - */ - function save($params = false) - { - parent::save($params); - $file = fopen($param['filename'], 'w+'); - fwrite($file, $this->toHtml($params)); - fclose($file); - } - - /** - * Get a canvas specific HTML tag. - * - * Parameter array: - * 'name': string The name of the image map - */ - function toHtml($params) - { - if (count($this->_map) > 0) { - return '' . "\n\t" . implode($this->_map, "\n\t") . "\n"; - } - return ''; - } -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: ImageMap.php,v 1.6 2005/08/17 17:59:11 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Class for handling output as a HTML imagemap + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @since version 0.2.0 + */ +class Image_Canvas_ImageMap extends Image_Canvas +{ + + /** + * The image map (if any) + * @var array + * @access private + */ + var $_map = array(); + + /** + * Add a map tag + * @param string $shape The shape, either rect, circle or polygon + * @param string $coords The list of coordinates for the shape + * @param array $params Parameter array + */ + function _addMapTag($shape, $coords, $params) + { + if (isset($params['url'])) { + $url = $params['url']; + $target = (isset($params['target']) ? $params['target'] : false); + $alt = (isset($params['alt']) ? $params['alt'] : false); + + $tags = ''; + if (isset($params['htmltags'])) { + foreach ($params['htmltags'] as $key => $value) { + $tags .= ' '; + if (strpos($value, '"') >= 0) { + $tags .= $key . '=\'' . $value . '\''; + } else { + $tags .= $key . '="' . $value . '"'; + } + } + } + + $this->_map[] = + '' . $alt . ''; + } + } + + /** + * Draw a line + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'color': mixed [optional] The line color + * 'mapsize': int [optional] The size of the image map (surrounding the line) + * @param array $params Parameter array + */ + function line($params) + { + if (isset($params['url'])) { + $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2); + $this->_addMapTag( + 'polygon', + $this->_getX($params['x0'] - $mapsize) . ',' . + $this->_getY($params['y0'] - $mapsize) . ',' . + $this->_getX($params['x1'] + $mapsize) . ',' . + $this->_getY($params['y1'] - $mapsize) . ',' . + + $this->_getX($params['x1'] + $mapsize) . ',' . + $this->_getY($params['y1'] + $mapsize) . ',' . + $this->_getX($params['x0'] - $mapsize) . ',' . + $this->_getY($params['y0'] + $mapsize), + $params + ); + } + parent::line($params); + } + + /** + * Draws a polygon + * + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * 'map_vertices': bool [optional] Specifies whether the image map should map the vertices instead of the polygon as a whole + * 'url': string [optional] URL to link the polygon as a whole to (also used for default in case 'map_vertices' is used) + * 'alt': string [optional] Alternative text to show in the image map (also used for default in case 'map_vertices' is used) + * 'target': string [optional] The link target on the image map (also used for default in case 'map_vertices' is used) + * @param array $params Parameter array + */ + function polygon($params) + { + if ((isset($params['map_vertices'])) && ($params['map_vertices'] === true)) { + $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2); + foreach ($this->_polygon as $point) { + $vertex_param = $params; + if (isset($point['url'])) { + $vertex_param['url'] = $point['url']; + } + if (isset($point['target'])) { + $vertex_param['target'] = $point['target']; + } + if (isset($point['alt'])) { + $vertex_param['alt'] = $point['alt']; + } + $vertex_mapsize = $mapsize; + if (isset($point['mapsize'])) { + $vertex_mapsize = $point['mapsize']; + } + if (isset($point['htmltags'])) { + $vertex_param['htmltags'] = $point['htmltags']; + } + $this->_addMapTag( + 'circle', + $this->_getX($point['X']) . ',' . + $this->_getY($point['Y']) . ',' . + $mapsize, + $vertex_param + ); + } + } + else if (isset($params['url'])) { + $points = ''; + foreach ($this->_polygon as $point) { + if ($points != '') { + $points .= ','; + } + $points .= $this->_getX($point['X']) . ',' . $this->_getY($point['Y']); + } + $this->_addMapTag('polygon', $points, $params); + } + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + if (isset($params['url'])) { + $this->_addMapTag( + 'rect', + $this->_getX($params['x0']) . ',' . + $this->_getY($params['y0']) . ',' . + $this->_getX($params['x1']) . ',' . + $this->_getY($params['y1']), + $params + ); + } + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + if (isset($params['url'])) { + if ($params['rx'] == $params['ry']) { + $this->_addMapTag( + 'circle', + $this->_getX($params['x']) . ',' . + $this->_getY($params['y']) . ',' . + $this->_getX($params['rx']), + $params + ); + } else { + $points = ''; + for ($v = 0; $v <= 360; $v += 30) { + if ($points != '') { + $points .= ','; + } + $points .= + round($this->_getX($params['x']) + $this->_getX($params['rx']) * cos(deg2rad($v % 360))) . ',' . + round($this->_getY($params['y']) + $this->_getX($params['ry']) * sin(deg2rad($v % 360))); + } + $this->_addMapTag( + 'polygon', + $points, + $params + ); + } + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + if (isset($params['url'])) { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $params['rx']; + $ry = $params['ry']; + $v1a = $params['v1']; + $v2a = $params['v2']; + $v1 = min($v1a, $v2a); + $v2 = max($v1a, $v2a); + $srx = (isset($params['srx']) ? $params['srx'] : 0); + $sry = (isset($params['sry']) ? $params['sry'] : 0); + + $points = + round(($x + $srx * cos(deg2rad($v1 % 360)))) . ',' . + round(($y + $sry * sin(deg2rad($v1 % 360)))) . ','; + + for ($v = $v1; $v < $v2; $v += 30) { + $points .= + round(($x + $rx * cos(deg2rad($v % 360)))) . ',' . + round(($y + $ry * sin(deg2rad($v % 360)))) . ','; + } + + $points .= + round(($x + $rx * cos(deg2rad($v2 % 360)))) . ',' . + round(($y + $ry * sin(deg2rad($v2 % 360)))); + + if (($srx != 0) || ($sry != 0)) { + $points .= ','; + for ($v = $v2; $v > $v1; $v -= 30) { + $points .= + round(($x + $srx * cos(deg2rad($v % 360)))) . ',' . + round(($y + $sry * sin(deg2rad($v % 360)))) . ','; + } + + } + + $this->_addMapTag('polygon', $points, $params); + } + parent::pieslice($params); + } + + /** + * Output the result of the canvas to the browser + * + * @param array $params Parameter array, the contents and meaning depends on the actual Canvas + * @abstract + */ + function show($params = false) + { + parent::show($params); + if (count($this->_map) > 0) { + print $this->toHtml($params); + } + } + + /** + * Save the result of the canvas to a file + * + * Parameter array: + * 'filename': string The file to output to + * @param array $params Parameter array, the contents and meaning depends on the actual Canvas + * @abstract + */ + function save($params = false) + { + parent::save($params); + $file = fopen($param['filename'], 'w+'); + fwrite($file, $this->toHtml($params)); + fclose($file); + } + + /** + * Get a canvas specific HTML tag. + * + * Parameter array: + * 'name': string The name of the image map + */ + function toHtml($params) + { + if (count($this->_map) > 0) { + return '' . "\n\t" . implode($this->_map, "\n\t") . "\n"; + } + return ''; + } +} + ?> \ No newline at end of file diff --git a/pandora_console/reporting/Image/Canvas/PDF.php b/pandora_console/reporting/Image/Canvas/PDF.php index 2ed2ee8b82..ae00a1207a 100644 --- a/pandora_console/reporting/Image/Canvas/PDF.php +++ b/pandora_console/reporting/Image/Canvas/PDF.php @@ -1,1007 +1,1007 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: PDF.php,v 1.4 2005/09/14 20:37:05 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas.php - */ -require_once 'Image/Canvas.php'; - -/** - * Include file Image/Canvas/Color.php - */ -require_once 'Image/Canvas/Color.php'; - -/** - * PDF Canvas class. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ -class Image_Canvas_PDF extends Image_Canvas -{ - - /** - * The PDF document - * @var resource - * @access private - */ - var $_pdf; - - /** - * The major version of PDFlib - * @var int - * @access private - */ - var $_pdflib; - - /** - * The font - * @var mixed - * @access private - */ - var $_pdfFont = false; - - /** - * The width of the page - * @var int - * @access private - */ - var $_pageWidth; - - /** - * The height of the page - * @var int - * @access private - */ - var $_pageHeight; - - /** - * Create the PDF canvas. - * - * Parameters available: - * - * 'page' Specify the page/paper format for the graph's page, available - * formats are: A0, A1, A2, A3, A4, A5, A6, B5, letter, legal, ledger, - * 11x17, cd_front, inlay, inlay_nosides - * - * 'align' Alignment of the graph on the page, available options are: - * topleft, topcenter, topright, leftcenter, center, rightcenter, - * leftbottom, centerbottom, rightbottom - * - * 'orientation' Specifies the paper orientation, default is 'portrait' and - * 'landscape' is also supported. - * - * 'creator' The creator tag of the PDF/graph - * - * 'author' The author tag of the PDF/graph - * - * 'title' The title tag of the PDF/graph - * - * 'width' The width of the graph on the page - * - * 'height' The height of the graph on the page - * - * 'left' The left offset of the graph on the page - * - * 'top' The top offset of the graph on the page - * - * 'filename' The PDF file to open/add page to, using 'filename' requires - * the commercial version of PDFlib (http://www.pdflib.com/), this has for - * obvious ($ 450) reasons not been tested - * - * 'pdf' An existing PDFlib PDF document to add the page to - * - * 'add_page' (true/false) Used together with 'pdf', to specify whether the - * canvas should add a new graph page (true) or create the graph on the - * current page (false), default is 'true' - * - * The 'page' and 'width' & 'height' can be mutually omitted, if 'page' is - * omitted the page is created using dimensions of width x height, and if - * width and height are omitted the page dimensions are used for the graph. - * - * If 'pdf' is specified, 'filename', 'creator', 'author' and 'title' has no - * effect. - * - * 'left' and 'top' are overridden by 'align' - * - * It is required either to specify 'width' & 'height' or 'page'. - * - * The PDF format/PDFlib has some limitations on the capabilities, which - * means some functionality available using other canvass (fx. alpha - * blending and gradient fills) are not supported with PDF (see Canvas.txt - * in the docs/ folder for further details) - * - * @param array $param Parameter array - */ - function Image_Canvas_PDF($param) - { - if (isset($param['page'])) { - switch (strtoupper($param['page'])) { - case 'A0': - $this->_pageWidth = 2380; - $this->_pageHeight = 3368; - break; - - case 'A1': - $this->_pageWidth = 1684; - $this->_pageHeight = 2380; - break; - - case 'A2': - $this->_pageWidth = 1190; - $this->_pageHeight = 1684; - break; - - case 'A3': - $this->_pageWidth = 842; - $this->_pageHeight = 1190; - break; - - case 'A4': - $this->_pageWidth = 595; - $this->_pageHeight = 842; - break; - - case 'A5': - $this->_pageWidth = 421; - $this->_pageHeight = 595; - break; - - case 'A6': - $this->_pageWidth = 297; - $this->_pageHeight = 421; - break; - - case 'B5': - $this->_pageWidth = 501; - $this->_pageHeight = 709; - break; - - case 'LETTER': - $this->_pageWidth = 612; - $this->_pageHeight = 792; - break; - - case 'LEGAL': - $this->_pageWidth = 612; - $this->_pageHeight = 1008; - break; - - case 'LEDGER': - $this->_pageWidth = 1224; - $this->_pageHeight = 792; - break; - - case '11X17': - $this->_pageWidth = 792; - $this->_pageHeight = 1224; - break; - - case 'CD_FRONT': - $this->_pageWidth = 337; - $this->_pageHeight = 337; - break; - - case 'INLAY': - $this->_pageWidth = 425; - $this->_pageHeight = 332; - break; - - case 'INLAY_NOSIDES': - $this->_pageWidth = 390; - $this->_pageHeight = 332; - break; - } - } - - if ((isset($param['orientation'])) && (strtoupper($param['orientation']) == 'LANDSCAPE')) { - $w = $this->_pageWidth; - $this->_pageWidth = $this->_pageHeight; - $this->_pageHeight = $w; - } - - parent::Image_Canvas($param); - - if (!$this->_pageWidth) { - $this->_pageWidth = $this->_width; - } elseif (!$this->_width) { - $this->_width = $this->_pageWidth; - } - - if (!$this->_pageHeight) { - $this->_pageHeight = $this->_height; - } elseif (!$this->_height) { - $this->_height = $this->_pageHeight; - } - - $this->_width = min($this->_width, $this->_pageWidth); - $this->_height = min($this->_height, $this->_pageHeight); - - if ((isset($param['align'])) && - (($this->_width != $this->_pageWidth) || ($this->_height != $this->_pageHeight)) - ) { - switch (strtoupper($param['align'])) { - case 'TOPLEFT': - $this->_top = 0; - $this->_left = 0; - break; - - case 'TOPCENTER': - $this->_top = 0; - $this->_left = ($this->_pageWidth - $this->_width) / 2; - break; - - case 'TOPRIGHT': - $this->_top = 0; - $this->_left = $this->_pageWidth - $this->_width; - break; - - case 'LEFTCENTER': - $this->_top = ($this->_pageHeight - $this->_height) / 2; - $this->_left = 0; - break; - - case 'CENTER': - $this->_top = ($this->_pageHeight - $this->_height) / 2; - $this->_left = ($this->_pageWidth - $this->_width) / 2; - break; - - case 'RIGHTCENTER': - $this->_top = ($this->_pageHeight - $this->_height) / 2; - $this->_left = $this->_pageWidth - $this->_width; - break; - - case 'LEFTBOTTOM': - $this->_top = $this->_pageHeight - $this->_height; - $this->_left = 0; - break; - - case 'CENTERBOTTOM': - $this->_top = $this->_pageHeight - $this->_height; - $this->_left = ($this->_pageWidth - $this->_width) / 2; - break; - - case 'RIGHTBOTTOM': - $this->_top = $this->_pageHeight - $this->_height; - $this->_left = $this->_pageWidth - $this->_width; - break; - } - } - - $this->_pdflib = $this->_version(); - - $addPage = true; - if ((isset($param['pdf'])) && (is_resource($param['pdf']))) { - $this->_pdf =& $param['pdf']; - if ((isset($param['add_page'])) && ($param['add_page'] === false)) { - $addPage = false; - } - } else { - $this->_pdf = pdf_new(); - - if (isset($param['filename'])) { - pdf_open_file($this->_pdf, $param['filename']); - } else { - pdf_open_file($this->_pdf, ''); - } - - pdf_set_parameter($this->_pdf, 'warning', 'true'); - - pdf_set_info($this->_pdf, 'Creator', (isset($param['creator']) ? $param['creator'] : 'PEAR::Image_Canvas')); - pdf_set_info($this->_pdf, 'Author', (isset($param['author']) ? $param['author'] : 'Jesper Veggerby')); - pdf_set_info($this->_pdf, 'Title', (isset($param['title']) ? $param['title'] : 'Image_Canvas')); - } - - if ($addPage) { - pdf_begin_page($this->_pdf, $this->_pageWidth, $this->_pageHeight); - } - $this->_reset(); - } - - /** - * Get the x-point from the relative to absolute coordinates - * - * @param float $x The relative x-coordinate (in percentage of total width) - * @return float The x-coordinate as applied to the canvas - * @access private - */ - function _getX($x) - { - return $this->_left + $x; - } - - /** - * Get the y-point from the relative to absolute coordinates - * - * @param float $y The relative y-coordinate (in percentage of total width) - * @return float The y-coordinate as applied to the canvas - * @access private - */ - function _getY($y) - { - return $this->_pageHeight - ($this->_top + $y); - } - - /** - * Get the color index for the RGB color - * - * @param int $color The color - * @return int The GD image index of the color - * @access private - */ - function _color($color = false) - { - if ($color === false) { - return false; - } else { - $color = Image_Canvas_Color::color2RGB($color); - $color[0] = $color[0]/255; - $color[1] = $color[1]/255; - $color[2] = $color[2]/255; - return $color; - } - } - - /** - * Get the PDF linestyle - * - * @param mixed $lineStyle The line style to return, false if the one - * explicitly set - * @return bool True if set (so that a line should be drawn) - * @access private - */ - function _setLineStyle($lineStyle = false) - { - if ($lineStyle === false) { - $lineStyle = $this->_lineStyle; - } - - if (($lineStyle == 'transparent') || ($lineStyle === false)) { - return false; - } - - if (is_array($lineStyle)) { - // TODO Implement linestyles in PDFlib (using pdf_setcolor(.., 'pattern'...); ? - reset($lineStyle); - $lineStyle = current($lineStyle); - } - - $color = $this->_color($lineStyle); - - pdf_setlinewidth($this->_pdf, $this->_thickness); - if ($this->_pdflib < 4) { - pdf_setrgbcolor_stroke($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); - } else { - pdf_setcolor($this->_pdf, 'stroke', 'rgb', $color[0], $color[1], $color[2], 0); - } - return true; - } - - /** - * Set the PDF fill style - * - * @param mixed $fillStyle The fillstyle to return, false if the one - * explicitly set - * @return bool True if set (so that a line should be drawn) - * @access private - */ - function _setFillStyle($fillStyle = false) - { - if ($fillStyle === false) { - $fillStyle = $this->_fillStyle; - } - - if (($fillStyle == 'transparent') || ($fillStyle === false)) { - return false; - } - - $color = $this->_color($fillStyle); - - if ($this->_pdflib < 4) { - pdf_setrgbcolor_fill($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); - } else { - pdf_setcolor($this->_pdf, 'fill', 'rgb', $color[0], $color[1], $color[2], 0); - } - return true; - } - - /** - * Set the PDF font - * - * @access private - */ - function _setFont() - { - $this->_pdfFont = false; - if (isset($this->_font['name'])) { - pdf_set_parameter($this->_pdf, 'FontOutline', $this->_font['name'] . '=' . $this->_font['file']); - $this->_pdfFont = pdf_findfont($this->_pdf, $this->_font['name'], $this->_font['encoding'], 1); - - if ($this->_pdfFont) { - pdf_setfont($this->_pdf, $this->_pdfFont, $this->_font['size']); - $this->_setFillStyle($this->_font['color']); - } - } else { - $this->_setFillStyle('black'); - } - } - - /** - * Sets an image that should be used for filling. - * - * Image filling is not supported with PDF, filling 'transparent' - * - * @param string $filename The filename of the image to fill with - */ - function setFillImage($filename) - { - $this->_fillStyle = 'transparent'; - } - - /** - * Sets a gradient fill - * - * Gradient filling is not supported with PDF, end color used as solid fill. - * - * @param array $gradient Gradient fill options - */ - function setGradientFill($gradient) - { - $this->_fillStyle = $gradient['end']; - } - - /** - * Sets the font options. - * - * The $font array may have the following entries: - * - * 'ttf' = the .ttf file (either the basename, filename or full path) - * If 'ttf' is specified, then the following can be specified - * - * 'size' = size in pixels - * - * 'angle' = the angle with which to write the text - * - * @param array $font The font options. - */ - function setFont($fontOptions) - { - parent::setFont($fontOptions); - - if (!isset($this->_font['size'])) { - $this->_font['size'] = 12; - } - - if (!isset($this->_font['encoding'])) { - $this->_font['encoding'] = 'winansi'; - } - - if (!isset($this->_font['color'])) { - $this->_font['color'] = 'black'; - } - } - - /** - * Resets the canvas. - * - * Includes fillstyle, linestyle, thickness and polygon - * - * @access private - */ - function _reset() - { - pdf_initgraphics($this->_pdf); - parent::_reset(); - } - - /** - * Draw a line - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'color': mixed [optional] The line color - * @param array $params Parameter array - */ - function line($params) - { - $color = (isset($params['color']) ? $params['color'] : false); - if ($this->_setLineStyle($color)) { - pdf_moveto($this->_pdf, $this->_getX($params['x0']), $this->_getY($params['y0'])); - pdf_lineto($this->_pdf, $this->_getX($params['x1']), $this->_getY($params['x1'])); - pdf_stroke($this->_pdf); - } - parent::line($params); - } - - /** - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params = array()) - { - $connectEnds = (isset($params['connect']) ? $params['connect'] : false); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $line = $this->_setLineStyle($lineColor); - $fill = false; - if ($connectEnds) { - $fill = $this->_setFillStyle($fillColor); - } - - $first = true; - foreach ($this->_polygon as $point) { - if ($first === true) { - pdf_moveto($this->_pdf, $point['X'], $point['Y']); - $first = $point; - } else { - if (isset($last['P1X'])) { - pdf_curveto($this->_pdf, - $last['P1X'], - $last['P1Y'], - $last['P2X'], - $last['P2Y'], - $point['X'], - $point['Y'] - ); - } else { - pdf_lineto($this->_pdf, - $point['X'], - $point['Y'] - ); - } - } - $last = $point; - } - - if ($connectEnds) { - if (isset($last['P1X'])) { - pdf_curveto($this->_pdf, - $last['P1X'], - $last['P1Y'], - $last['P2X'], - $last['P2Y'], - $first['X'], - $first['Y'] - ); - } else { - pdf_lineto($this->_pdf, - $first['X'], - $first['Y'] - ); - } - } - - if (($line) && ($fill)) { - pdf_fill_stroke($this->_pdf); - } elseif ($line) { - pdf_stroke($this->_pdf); - } elseif ($fill) { - pdf_fill($this->_pdf); - } - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $line = $this->_setLineStyle($lineColor); - $fill = $this->_setFillStyle($fillColor); - if (($line) || ($fill)) { - pdf_rect($this->_pdf, $this->_getX(min($x0, $x1)), $this->_getY(max($y0, $y1)), abs($x1 - $x0), abs($y1 - $y0)); - if (($line) && ($fill)) { - pdf_fill_stroke($this->_pdf); - } elseif ($line) { - pdf_stroke($this->_pdf); - } elseif ($fill) { - pdf_fill($this->_pdf); - } - } - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $line = $this->_setLineStyle($lineColor); - $fill = $this->_setFillStyle($fillColor); - if (($line) || ($fill)) { - if ($rx == $ry) { - pdf_circle($this->_pdf, $this->_getX($x), $this->_getY($y), $rx); - } else { - pdf_moveto($this->_pdf, $this->_getX($x - $rx), $this->_getY($y)); - pdf_curveto($this->_pdf, - $this->_getX($x - $rx), $this->_getY($y), - $this->_getX($x - $rx), $this->_getY($y - $ry), - $this->_getX($x), $this->_getY($y - $ry) - ); - pdf_curveto($this->_pdf, - $this->_getX($x), $this->_getY($y - $ry), - $this->_getX($x + $rx), $this->_getY($y - $ry), - $this->_getX($x + $rx), $this->_getY($y) - ); - pdf_curveto($this->_pdf, - $this->_getX($x + $rx), $this->_getY($y), - $this->_getX($x + $rx), $this->_getY($y + $ry), - $this->_getX($x), $this->_getY($y + $ry) - ); - pdf_curveto($this->_pdf, - $this->_getX($x), $this->_getY($y + $ry), - $this->_getX($x - $rx), $this->_getY($y + $ry), - $this->_getX($x - $rx), $this->_getY($y) - ); - } - - if (($line) && ($fill)) { - pdf_fill_stroke($this->_pdf); - } elseif ($line) { - pdf_stroke($this->_pdf); - } elseif ($fill) { - pdf_fill($this->_pdf); - } - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $v1 = $this->_getX($params['v1']); - $v2 = $this->_getY($params['v2']); - $srx = $this->_getX($params['srx']); - $sry = $this->_getY($params['sry']); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - // TODO Implement PDFLIB::pieSlice() - parent::pieslice($params); - } - - /** - * Get the width of a text, - * - * @param string $text The text to get the width of - * @return int The width of the text - */ - function textWidth($text) - { - if ($this->_pdfFont === false) { - return $this->_font['size'] * 0.7 * strlen($text); - } else { - return pdf_stringwidth($this->_pdf, $text, $this->_pdfFont, $this->_font['size']); - } - } - - /** - * Get the height of a text, - * - * @param string $text The text to get the height of - * @return int The height of the text - */ - function textHeight($text) - { - if (isset($this->_font['size'])) { - return $this->_font['size']; - } else { - return 12; - } - } - - /** - * Writes text - * - * Parameter array: - * 'x': int X-point of text - * 'y': int Y-point of text - * 'text': string The text to add - * 'alignment': array [optional] Alignment - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $text = $params['text']; - $color = (isset($params['color']) ? $params['color'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - $this->_setFont(); - - $textWidth = $this->textWidth($text); - $textHeight = $this->textHeight($text); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - if ($alignment['horizontal'] == 'right') { - $x = $x - $textWidth; - } elseif ($alignment['horizontal'] == 'center') { - $x = $x - ($textWidth / 2); - } - - if ($alignment['vertical'] == 'top') { - $y = $y + $textHeight; - } elseif ($alignment['vertical'] == 'center') { - $y = $y + ($textHeight / 2); - } - - if (($color === false) && (isset($this->_font['color']))) { - $color = $this->_font['color']; - } - - pdf_show_xy($this->_pdf, $text, $this->_getX($x), $this->_getY($y)); - - parent::write($params); - } - - /** - * Overlay image - * - * Parameter array: - * 'x': int X-point of overlayed image - * 'y': int Y-point of overlayed image - * 'filename': string The filename of the image to overlay - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * 'alignment': array [optional] Alignment - */ - function image($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $filename = $params['filename']; - $width = (isset($params['width']) ? $params['width'] : false); - $height = (isset($params['height']) ? $params['height'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - if (substr($filename, -4) == '.png') { - $type = 'png'; - } elseif (substr($filename, -4) == '.jpg') { - $type = 'jpeg'; - } - - $image = pdf_load_image($this->_pdf, $type, realpath($filename), ''); - $width_ = pdf_get_value($this->_pdf, 'imagewidth', $image); - $height_ = pdf_get_value($this->_pdf, 'imageheight', $image); - - $outputWidth = ($width !== false ? $width : $width_); - $outputHeight = ($height !== false ? $height : $height_); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - if ($alignment['horizontal'] == 'right') { - $x -= $outputWidth; - } elseif ($alignment['horizontal'] == 'center') { - $x -= $outputWidth / 2; - } - - if ($alignment['vertical'] == 'top') { - $y += $outputHeight; - } elseif ($alignment['vertical'] == 'center') { - $y += $outputHeight / 2; - } - - if (($width === false) && ($height === false)) { - $scale = 1; - } else { - $scale = max(($height/$height_), ($width/$width_)); - } - - pdf_place_image($this->_pdf, $image, $this->_getX($x), $this->_getY($y), $scale); - pdf_close_image($this->_pdf, $image); - - parent::image($params); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function show($param = false) - { - parent::show($param); - pdf_end_page($this->_pdf); - pdf_close($this->_pdf); - - $buf = pdf_get_buffer($this->_pdf); - $len = strlen($buf); - - header('Content-type: application/pdf'); - header('Content-Length: ' . $len); - header('Content-Disposition: inline; filename=image_graph.pdf'); - print $buf; - - pdf_delete($this->_pdf); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function save($param = false) - { - parent::save($param); - pdf_end_page($this->_pdf); - pdf_close($this->_pdf); - - $buf = pdf_get_buffer($this->_pdf); - $len = strlen($buf); - - $fp = @fopen($param['filename'], 'wb'); - if ($fp) { - fwrite($fp, $buf, strlen($buf)); - fclose($fp); - } - pdf_delete($this->_pdf); - } - - /** - * Get a canvas specific HTML tag. - * - * This method implicitly saves the canvas to the filename in the - * filesystem path specified and parses it as URL specified by URL path - * - * Parameter array: - * 'filename': string - * 'filepath': string Path to the file on the file system. Remember the final slash - * 'urlpath': string Path to the file available through an URL. Remember the final slash - * 'title': string The url title - */ - function toHtml($params) - { - parent::toHtml($params); - return '' . $params['title'] . ''; - } - - /** - * Check which major version of PDFlib is installed - * - * @return int The mahor version number of PDFlib - * @access private - */ - function _version() - { - $result = false; - if (function_exists('pdf_get_majorversion')) { - $version = pdf_get_majorversion(); - } else { - ob_start(); - phpinfo(8); - $php_info = ob_get_contents(); - ob_end_clean(); - - if (ereg("]*>PDFlib GmbH Version *<\/td>]*>([^<]*)<\/td>", - $php_info, $result)) - { - $version = $result[1]; - } - } - - if (ereg('([0-9]{1,2})\.[0-9]{1,2}(\.[0-9]{1,2})?', trim($version), $result)) { - return $result[1]; - } else { - return 0; - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: PDF.php,v 1.4 2005/09/14 20:37:05 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas.php + */ +require_once 'Image/Canvas.php'; + +/** + * Include file Image/Canvas/Color.php + */ +require_once 'Image/Canvas/Color.php'; + +/** + * PDF Canvas class. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ +class Image_Canvas_PDF extends Image_Canvas +{ + + /** + * The PDF document + * @var resource + * @access private + */ + var $_pdf; + + /** + * The major version of PDFlib + * @var int + * @access private + */ + var $_pdflib; + + /** + * The font + * @var mixed + * @access private + */ + var $_pdfFont = false; + + /** + * The width of the page + * @var int + * @access private + */ + var $_pageWidth; + + /** + * The height of the page + * @var int + * @access private + */ + var $_pageHeight; + + /** + * Create the PDF canvas. + * + * Parameters available: + * + * 'page' Specify the page/paper format for the graph's page, available + * formats are: A0, A1, A2, A3, A4, A5, A6, B5, letter, legal, ledger, + * 11x17, cd_front, inlay, inlay_nosides + * + * 'align' Alignment of the graph on the page, available options are: + * topleft, topcenter, topright, leftcenter, center, rightcenter, + * leftbottom, centerbottom, rightbottom + * + * 'orientation' Specifies the paper orientation, default is 'portrait' and + * 'landscape' is also supported. + * + * 'creator' The creator tag of the PDF/graph + * + * 'author' The author tag of the PDF/graph + * + * 'title' The title tag of the PDF/graph + * + * 'width' The width of the graph on the page + * + * 'height' The height of the graph on the page + * + * 'left' The left offset of the graph on the page + * + * 'top' The top offset of the graph on the page + * + * 'filename' The PDF file to open/add page to, using 'filename' requires + * the commercial version of PDFlib (http://www.pdflib.com/), this has for + * obvious ($ 450) reasons not been tested + * + * 'pdf' An existing PDFlib PDF document to add the page to + * + * 'add_page' (true/false) Used together with 'pdf', to specify whether the + * canvas should add a new graph page (true) or create the graph on the + * current page (false), default is 'true' + * + * The 'page' and 'width' & 'height' can be mutually omitted, if 'page' is + * omitted the page is created using dimensions of width x height, and if + * width and height are omitted the page dimensions are used for the graph. + * + * If 'pdf' is specified, 'filename', 'creator', 'author' and 'title' has no + * effect. + * + * 'left' and 'top' are overridden by 'align' + * + * It is required either to specify 'width' & 'height' or 'page'. + * + * The PDF format/PDFlib has some limitations on the capabilities, which + * means some functionality available using other canvass (fx. alpha + * blending and gradient fills) are not supported with PDF (see Canvas.txt + * in the docs/ folder for further details) + * + * @param array $param Parameter array + */ + function Image_Canvas_PDF($param) + { + if (isset($param['page'])) { + switch (strtoupper($param['page'])) { + case 'A0': + $this->_pageWidth = 2380; + $this->_pageHeight = 3368; + break; + + case 'A1': + $this->_pageWidth = 1684; + $this->_pageHeight = 2380; + break; + + case 'A2': + $this->_pageWidth = 1190; + $this->_pageHeight = 1684; + break; + + case 'A3': + $this->_pageWidth = 842; + $this->_pageHeight = 1190; + break; + + case 'A4': + $this->_pageWidth = 595; + $this->_pageHeight = 842; + break; + + case 'A5': + $this->_pageWidth = 421; + $this->_pageHeight = 595; + break; + + case 'A6': + $this->_pageWidth = 297; + $this->_pageHeight = 421; + break; + + case 'B5': + $this->_pageWidth = 501; + $this->_pageHeight = 709; + break; + + case 'LETTER': + $this->_pageWidth = 612; + $this->_pageHeight = 792; + break; + + case 'LEGAL': + $this->_pageWidth = 612; + $this->_pageHeight = 1008; + break; + + case 'LEDGER': + $this->_pageWidth = 1224; + $this->_pageHeight = 792; + break; + + case '11X17': + $this->_pageWidth = 792; + $this->_pageHeight = 1224; + break; + + case 'CD_FRONT': + $this->_pageWidth = 337; + $this->_pageHeight = 337; + break; + + case 'INLAY': + $this->_pageWidth = 425; + $this->_pageHeight = 332; + break; + + case 'INLAY_NOSIDES': + $this->_pageWidth = 390; + $this->_pageHeight = 332; + break; + } + } + + if ((isset($param['orientation'])) && (strtoupper($param['orientation']) == 'LANDSCAPE')) { + $w = $this->_pageWidth; + $this->_pageWidth = $this->_pageHeight; + $this->_pageHeight = $w; + } + + parent::Image_Canvas($param); + + if (!$this->_pageWidth) { + $this->_pageWidth = $this->_width; + } elseif (!$this->_width) { + $this->_width = $this->_pageWidth; + } + + if (!$this->_pageHeight) { + $this->_pageHeight = $this->_height; + } elseif (!$this->_height) { + $this->_height = $this->_pageHeight; + } + + $this->_width = min($this->_width, $this->_pageWidth); + $this->_height = min($this->_height, $this->_pageHeight); + + if ((isset($param['align'])) && + (($this->_width != $this->_pageWidth) || ($this->_height != $this->_pageHeight)) + ) { + switch (strtoupper($param['align'])) { + case 'TOPLEFT': + $this->_top = 0; + $this->_left = 0; + break; + + case 'TOPCENTER': + $this->_top = 0; + $this->_left = ($this->_pageWidth - $this->_width) / 2; + break; + + case 'TOPRIGHT': + $this->_top = 0; + $this->_left = $this->_pageWidth - $this->_width; + break; + + case 'LEFTCENTER': + $this->_top = ($this->_pageHeight - $this->_height) / 2; + $this->_left = 0; + break; + + case 'CENTER': + $this->_top = ($this->_pageHeight - $this->_height) / 2; + $this->_left = ($this->_pageWidth - $this->_width) / 2; + break; + + case 'RIGHTCENTER': + $this->_top = ($this->_pageHeight - $this->_height) / 2; + $this->_left = $this->_pageWidth - $this->_width; + break; + + case 'LEFTBOTTOM': + $this->_top = $this->_pageHeight - $this->_height; + $this->_left = 0; + break; + + case 'CENTERBOTTOM': + $this->_top = $this->_pageHeight - $this->_height; + $this->_left = ($this->_pageWidth - $this->_width) / 2; + break; + + case 'RIGHTBOTTOM': + $this->_top = $this->_pageHeight - $this->_height; + $this->_left = $this->_pageWidth - $this->_width; + break; + } + } + + $this->_pdflib = $this->_version(); + + $addPage = true; + if ((isset($param['pdf'])) && (is_resource($param['pdf']))) { + $this->_pdf =& $param['pdf']; + if ((isset($param['add_page'])) && ($param['add_page'] === false)) { + $addPage = false; + } + } else { + $this->_pdf = pdf_new(); + + if (isset($param['filename'])) { + pdf_open_file($this->_pdf, $param['filename']); + } else { + pdf_open_file($this->_pdf, ''); + } + + pdf_set_parameter($this->_pdf, 'warning', 'true'); + + pdf_set_info($this->_pdf, 'Creator', (isset($param['creator']) ? $param['creator'] : 'PEAR::Image_Canvas')); + pdf_set_info($this->_pdf, 'Author', (isset($param['author']) ? $param['author'] : 'Jesper Veggerby')); + pdf_set_info($this->_pdf, 'Title', (isset($param['title']) ? $param['title'] : 'Image_Canvas')); + } + + if ($addPage) { + pdf_begin_page($this->_pdf, $this->_pageWidth, $this->_pageHeight); + } + $this->_reset(); + } + + /** + * Get the x-point from the relative to absolute coordinates + * + * @param float $x The relative x-coordinate (in percentage of total width) + * @return float The x-coordinate as applied to the canvas + * @access private + */ + function _getX($x) + { + return $this->_left + $x; + } + + /** + * Get the y-point from the relative to absolute coordinates + * + * @param float $y The relative y-coordinate (in percentage of total width) + * @return float The y-coordinate as applied to the canvas + * @access private + */ + function _getY($y) + { + return $this->_pageHeight - ($this->_top + $y); + } + + /** + * Get the color index for the RGB color + * + * @param int $color The color + * @return int The GD image index of the color + * @access private + */ + function _color($color = false) + { + if ($color === false) { + return false; + } else { + $color = Image_Canvas_Color::color2RGB($color); + $color[0] = $color[0]/255; + $color[1] = $color[1]/255; + $color[2] = $color[2]/255; + return $color; + } + } + + /** + * Get the PDF linestyle + * + * @param mixed $lineStyle The line style to return, false if the one + * explicitly set + * @return bool True if set (so that a line should be drawn) + * @access private + */ + function _setLineStyle($lineStyle = false) + { + if ($lineStyle === false) { + $lineStyle = $this->_lineStyle; + } + + if (($lineStyle == 'transparent') || ($lineStyle === false)) { + return false; + } + + if (is_array($lineStyle)) { + // TODO Implement linestyles in PDFlib (using pdf_setcolor(.., 'pattern'...); ? + reset($lineStyle); + $lineStyle = current($lineStyle); + } + + $color = $this->_color($lineStyle); + + pdf_setlinewidth($this->_pdf, $this->_thickness); + if ($this->_pdflib < 4) { + pdf_setrgbcolor_stroke($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); + } else { + pdf_setcolor($this->_pdf, 'stroke', 'rgb', $color[0], $color[1], $color[2], 0); + } + return true; + } + + /** + * Set the PDF fill style + * + * @param mixed $fillStyle The fillstyle to return, false if the one + * explicitly set + * @return bool True if set (so that a line should be drawn) + * @access private + */ + function _setFillStyle($fillStyle = false) + { + if ($fillStyle === false) { + $fillStyle = $this->_fillStyle; + } + + if (($fillStyle == 'transparent') || ($fillStyle === false)) { + return false; + } + + $color = $this->_color($fillStyle); + + if ($this->_pdflib < 4) { + pdf_setrgbcolor_fill($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); + } else { + pdf_setcolor($this->_pdf, 'fill', 'rgb', $color[0], $color[1], $color[2], 0); + } + return true; + } + + /** + * Set the PDF font + * + * @access private + */ + function _setFont() + { + $this->_pdfFont = false; + if (isset($this->_font['name'])) { + pdf_set_parameter($this->_pdf, 'FontOutline', $this->_font['name'] . '=' . $this->_font['file']); + $this->_pdfFont = pdf_findfont($this->_pdf, $this->_font['name'], $this->_font['encoding'], 1); + + if ($this->_pdfFont) { + pdf_setfont($this->_pdf, $this->_pdfFont, $this->_font['size']); + $this->_setFillStyle($this->_font['color']); + } + } else { + $this->_setFillStyle('black'); + } + } + + /** + * Sets an image that should be used for filling. + * + * Image filling is not supported with PDF, filling 'transparent' + * + * @param string $filename The filename of the image to fill with + */ + function setFillImage($filename) + { + $this->_fillStyle = 'transparent'; + } + + /** + * Sets a gradient fill + * + * Gradient filling is not supported with PDF, end color used as solid fill. + * + * @param array $gradient Gradient fill options + */ + function setGradientFill($gradient) + { + $this->_fillStyle = $gradient['end']; + } + + /** + * Sets the font options. + * + * The $font array may have the following entries: + * + * 'ttf' = the .ttf file (either the basename, filename or full path) + * If 'ttf' is specified, then the following can be specified + * + * 'size' = size in pixels + * + * 'angle' = the angle with which to write the text + * + * @param array $font The font options. + */ + function setFont($fontOptions) + { + parent::setFont($fontOptions); + + if (!isset($this->_font['size'])) { + $this->_font['size'] = 12; + } + + if (!isset($this->_font['encoding'])) { + $this->_font['encoding'] = 'winansi'; + } + + if (!isset($this->_font['color'])) { + $this->_font['color'] = 'black'; + } + } + + /** + * Resets the canvas. + * + * Includes fillstyle, linestyle, thickness and polygon + * + * @access private + */ + function _reset() + { + pdf_initgraphics($this->_pdf); + parent::_reset(); + } + + /** + * Draw a line + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'color': mixed [optional] The line color + * @param array $params Parameter array + */ + function line($params) + { + $color = (isset($params['color']) ? $params['color'] : false); + if ($this->_setLineStyle($color)) { + pdf_moveto($this->_pdf, $this->_getX($params['x0']), $this->_getY($params['y0'])); + pdf_lineto($this->_pdf, $this->_getX($params['x1']), $this->_getY($params['x1'])); + pdf_stroke($this->_pdf); + } + parent::line($params); + } + + /** + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params = array()) + { + $connectEnds = (isset($params['connect']) ? $params['connect'] : false); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $line = $this->_setLineStyle($lineColor); + $fill = false; + if ($connectEnds) { + $fill = $this->_setFillStyle($fillColor); + } + + $first = true; + foreach ($this->_polygon as $point) { + if ($first === true) { + pdf_moveto($this->_pdf, $point['X'], $point['Y']); + $first = $point; + } else { + if (isset($last['P1X'])) { + pdf_curveto($this->_pdf, + $last['P1X'], + $last['P1Y'], + $last['P2X'], + $last['P2Y'], + $point['X'], + $point['Y'] + ); + } else { + pdf_lineto($this->_pdf, + $point['X'], + $point['Y'] + ); + } + } + $last = $point; + } + + if ($connectEnds) { + if (isset($last['P1X'])) { + pdf_curveto($this->_pdf, + $last['P1X'], + $last['P1Y'], + $last['P2X'], + $last['P2Y'], + $first['X'], + $first['Y'] + ); + } else { + pdf_lineto($this->_pdf, + $first['X'], + $first['Y'] + ); + } + } + + if (($line) && ($fill)) { + pdf_fill_stroke($this->_pdf); + } elseif ($line) { + pdf_stroke($this->_pdf); + } elseif ($fill) { + pdf_fill($this->_pdf); + } + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $line = $this->_setLineStyle($lineColor); + $fill = $this->_setFillStyle($fillColor); + if (($line) || ($fill)) { + pdf_rect($this->_pdf, $this->_getX(min($x0, $x1)), $this->_getY(max($y0, $y1)), abs($x1 - $x0), abs($y1 - $y0)); + if (($line) && ($fill)) { + pdf_fill_stroke($this->_pdf); + } elseif ($line) { + pdf_stroke($this->_pdf); + } elseif ($fill) { + pdf_fill($this->_pdf); + } + } + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $this->_getX($params['rx']); + $ry = $this->_getY($params['ry']); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $line = $this->_setLineStyle($lineColor); + $fill = $this->_setFillStyle($fillColor); + if (($line) || ($fill)) { + if ($rx == $ry) { + pdf_circle($this->_pdf, $this->_getX($x), $this->_getY($y), $rx); + } else { + pdf_moveto($this->_pdf, $this->_getX($x - $rx), $this->_getY($y)); + pdf_curveto($this->_pdf, + $this->_getX($x - $rx), $this->_getY($y), + $this->_getX($x - $rx), $this->_getY($y - $ry), + $this->_getX($x), $this->_getY($y - $ry) + ); + pdf_curveto($this->_pdf, + $this->_getX($x), $this->_getY($y - $ry), + $this->_getX($x + $rx), $this->_getY($y - $ry), + $this->_getX($x + $rx), $this->_getY($y) + ); + pdf_curveto($this->_pdf, + $this->_getX($x + $rx), $this->_getY($y), + $this->_getX($x + $rx), $this->_getY($y + $ry), + $this->_getX($x), $this->_getY($y + $ry) + ); + pdf_curveto($this->_pdf, + $this->_getX($x), $this->_getY($y + $ry), + $this->_getX($x - $rx), $this->_getY($y + $ry), + $this->_getX($x - $rx), $this->_getY($y) + ); + } + + if (($line) && ($fill)) { + pdf_fill_stroke($this->_pdf); + } elseif ($line) { + pdf_stroke($this->_pdf); + } elseif ($fill) { + pdf_fill($this->_pdf); + } + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $this->_getX($params['rx']); + $ry = $this->_getY($params['ry']); + $v1 = $this->_getX($params['v1']); + $v2 = $this->_getY($params['v2']); + $srx = $this->_getX($params['srx']); + $sry = $this->_getY($params['sry']); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + // TODO Implement PDFLIB::pieSlice() + parent::pieslice($params); + } + + /** + * Get the width of a text, + * + * @param string $text The text to get the width of + * @return int The width of the text + */ + function textWidth($text) + { + if ($this->_pdfFont === false) { + return $this->_font['size'] * 0.7 * strlen($text); + } else { + return pdf_stringwidth($this->_pdf, $text, $this->_pdfFont, $this->_font['size']); + } + } + + /** + * Get the height of a text, + * + * @param string $text The text to get the height of + * @return int The height of the text + */ + function textHeight($text) + { + if (isset($this->_font['size'])) { + return $this->_font['size']; + } else { + return 12; + } + } + + /** + * Writes text + * + * Parameter array: + * 'x': int X-point of text + * 'y': int Y-point of text + * 'text': string The text to add + * 'alignment': array [optional] Alignment + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $text = $params['text']; + $color = (isset($params['color']) ? $params['color'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + $this->_setFont(); + + $textWidth = $this->textWidth($text); + $textHeight = $this->textHeight($text); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + if ($alignment['horizontal'] == 'right') { + $x = $x - $textWidth; + } elseif ($alignment['horizontal'] == 'center') { + $x = $x - ($textWidth / 2); + } + + if ($alignment['vertical'] == 'top') { + $y = $y + $textHeight; + } elseif ($alignment['vertical'] == 'center') { + $y = $y + ($textHeight / 2); + } + + if (($color === false) && (isset($this->_font['color']))) { + $color = $this->_font['color']; + } + + pdf_show_xy($this->_pdf, $text, $this->_getX($x), $this->_getY($y)); + + parent::write($params); + } + + /** + * Overlay image + * + * Parameter array: + * 'x': int X-point of overlayed image + * 'y': int Y-point of overlayed image + * 'filename': string The filename of the image to overlay + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * 'alignment': array [optional] Alignment + */ + function image($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $filename = $params['filename']; + $width = (isset($params['width']) ? $params['width'] : false); + $height = (isset($params['height']) ? $params['height'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + if (substr($filename, -4) == '.png') { + $type = 'png'; + } elseif (substr($filename, -4) == '.jpg') { + $type = 'jpeg'; + } + + $image = pdf_load_image($this->_pdf, $type, realpath($filename), ''); + $width_ = pdf_get_value($this->_pdf, 'imagewidth', $image); + $height_ = pdf_get_value($this->_pdf, 'imageheight', $image); + + $outputWidth = ($width !== false ? $width : $width_); + $outputHeight = ($height !== false ? $height : $height_); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + if ($alignment['horizontal'] == 'right') { + $x -= $outputWidth; + } elseif ($alignment['horizontal'] == 'center') { + $x -= $outputWidth / 2; + } + + if ($alignment['vertical'] == 'top') { + $y += $outputHeight; + } elseif ($alignment['vertical'] == 'center') { + $y += $outputHeight / 2; + } + + if (($width === false) && ($height === false)) { + $scale = 1; + } else { + $scale = max(($height/$height_), ($width/$width_)); + } + + pdf_place_image($this->_pdf, $image, $this->_getX($x), $this->_getY($y), $scale); + pdf_close_image($this->_pdf, $image); + + parent::image($params); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function show($param = false) + { + parent::show($param); + pdf_end_page($this->_pdf); + pdf_close($this->_pdf); + + $buf = pdf_get_buffer($this->_pdf); + $len = strlen($buf); + + header('Content-type: application/pdf'); + header('Content-Length: ' . $len); + header('Content-Disposition: inline; filename=image_graph.pdf'); + print $buf; + + pdf_delete($this->_pdf); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function save($param = false) + { + parent::save($param); + pdf_end_page($this->_pdf); + pdf_close($this->_pdf); + + $buf = pdf_get_buffer($this->_pdf); + $len = strlen($buf); + + $fp = @fopen($param['filename'], 'wb'); + if ($fp) { + fwrite($fp, $buf, strlen($buf)); + fclose($fp); + } + pdf_delete($this->_pdf); + } + + /** + * Get a canvas specific HTML tag. + * + * This method implicitly saves the canvas to the filename in the + * filesystem path specified and parses it as URL specified by URL path + * + * Parameter array: + * 'filename': string + * 'filepath': string Path to the file on the file system. Remember the final slash + * 'urlpath': string Path to the file available through an URL. Remember the final slash + * 'title': string The url title + */ + function toHtml($params) + { + parent::toHtml($params); + return '' . $params['title'] . ''; + } + + /** + * Check which major version of PDFlib is installed + * + * @return int The mahor version number of PDFlib + * @access private + */ + function _version() + { + $result = false; + if (function_exists('pdf_get_majorversion')) { + $version = pdf_get_majorversion(); + } else { + ob_start(); + phpinfo(8); + $php_info = ob_get_contents(); + ob_end_clean(); + + if (ereg("]*>PDFlib GmbH Version *<\/td>]*>([^<]*)<\/td>", + $php_info, $result)) + { + $version = $result[1]; + } + } + + if (ereg('([0-9]{1,2})\.[0-9]{1,2}(\.[0-9]{1,2})?', trim($version), $result)) { + return $result[1]; + } else { + return 0; + } + } + +} + ?> \ No newline at end of file diff --git a/pandora_console/reporting/Image/Canvas/SVG.php b/pandora_console/reporting/Image/Canvas/SVG.php index 4936db650d..47aa04dc75 100644 --- a/pandora_console/reporting/Image/Canvas/SVG.php +++ b/pandora_console/reporting/Image/Canvas/SVG.php @@ -1,885 +1,885 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: SVG.php,v 1.6 2005/08/24 20:37:35 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas.php - */ -require_once 'Image/Canvas.php'; - -/** - * Include file Image/Canvas/Color.php - */ -require_once 'Image/Canvas/Color.php'; - -/** - * SVG Canvas class. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ -class Image_Canvas_SVG extends Image_Canvas -{ - - /** - * The SVG elements - * @var string - * @access private - */ - var $_elements = ''; - - /** - * The SVG defines - * @var string - * @access private - */ - var $_defs = ''; - - /** - * The current indention level - * @var string - * @access private - */ - var $_indent = ' '; - - /** - * A unieuq id counter - * @var int - * @access private - */ - var $_id = 1; - - /** - * The current group ids - * @var array - * @access private - */ - var $_groupIDs = array(); - - /** - * Create the SVG canvas. - * - * Parameters available: - * - * 'width' The width of the graph - * - * 'height' The height of the graph - * - * @param array $param Parameter array - */ - function Image_Canvas_SVG($param) - { - parent::Image_Canvas($param); - $this->_reset(); - } - - /** - * Add a SVG "element" to the output - * - * @param string $element The element - * @access private - */ - function _addElement($element, $params) { - $elementdata = $this->_indent . $element . "\n"; - - if (isset($params['url'])) { - $url = $params['url']; - $target = (isset($params['target']) ? $params['target'] : false); - $alt = (isset($params['alt']) ? $params['alt'] : false); - - $tags = ''; - if (isset($params['htmltags'])) { - foreach ($params['htmltags'] as $key => $value) { - $tags .= ' '; - if (strpos($value, '"') >= 0) { - $tags .= $key . '=\'' . $value . '\''; - } else { - $tags .= $key . '="' . $value . '"'; - } - } - } - - $elementdata = - $this->_indent . '' . "\n" . - ' ' . $elementdata . - $this->_indent . '' . "\n"; - } - - - $this->_elements .= $elementdata; - } - - /** - * Add a SVG "define" to the output - * - * @param string $def The define - * @access private - */ - function _addDefine($def) { - $this->_defs .= ' ' . $def . "\n"; - } - - /** - * Get the color index for the RGB color - * - * @param int $color The color - * @return int A SVG compatible color - * @access private - */ - function _color($color = false) - { - if ($color === false) { - return 'transparent'; - } else { - $color = Image_Canvas_Color::color2RGB($color); - return 'rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')'; - } - } - - /** - * Get the opacity for the RGB color - * - * @param int $color The color - * @return int A SVG compatible opacity value - * @access private - */ - function _opacity($color = false) - { - if ($color === false) { - return false; - } else { - $color = Image_Canvas_Color::color2RGB($color); - if ($color[3] != 255) { - return sprintf('%0.1f', $color[3]/255); - } else { - return false; - } - } - } - - /** - * Get the SVG applicable linestyle - * - * @param mixed $lineStyle The line style to return, false if the one - * explicitly set - * @return mixed A SVG compatible linestyle - * @access private - */ - function _getLineStyle($lineStyle = false) - { - $result = ''; - if ($lineStyle === false) { - $lineStyle = $this->_lineStyle; - } - - // TODO Linestyles (i.e. fx. dotted) does not work - - if (($lineStyle != 'transparent') && ($lineStyle !== false)) { - $result = 'stroke-width:' . $this->_thickness . ';'; - $result .= 'stroke:' .$this->_color($lineStyle) . ';'; - if ($opacity = $this->_opacity($lineStyle)) { - $result .= 'stroke-opacity:' . $opacity . ';'; - } - } - return $result; - } - - /** - * Get the SVG applicable fillstyle - * - * @param mixed $fillStyle The fillstyle to return, false if the one - * explicitly set - * @return mixed A SVG compatible fillstyle - * @access private - */ - function _getFillStyle($fillStyle = false) - { - $result = ''; - if ($fillStyle === false) { - $fillStyle = $this->_fillStyle; - } - - if (is_array($fillStyle)) { - if ($fillStyle['type'] == 'gradient') { - $id = 'gradient_' . ($this->_id++); - $startColor = $this->_color($fillStyle['start']); - $endColor = $this->_color($fillStyle['end']); - $startOpacity = $this->_opacity($fillStyle['start']); - $endOpacity = $this->_opacity($fillStyle['end']); - - switch ($fillStyle['direction']) { - case 'horizontal': - case 'horizontal_mirror': - $x1 = '0%'; - $y1 = '0%'; - $x2 = '100%'; - $y2 = '0%'; - break; - - case 'vertical': - case 'vertical_mirror': - $x1 = '0%'; - $y1 = '100%'; - $x2 = '0%'; - $y2 = '0%'; - break; - - case 'diagonal_tl_br': - $x1 = '0%'; - $y1 = '0%'; - $x2 = '100%'; - $y2 = '100%'; - break; - - case 'diagonal_bl_tr': - $x1 = '0%'; - $y1 = '100%'; - $x2 = '100%'; - $y2 = '0%'; - break; - - case 'radial': - $cx = '50%'; - $cy = '50%'; - $r = '100%'; - $fx = '50%'; - $fy = '50%'; - break; - - } - - if ($fillStyle['direction'] == 'radial') { - $this->_addDefine( - '' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - '' - ); - } elseif (($fillStyle['direction'] == 'vertical_mirror') || - ($fillStyle['direction'] == 'horizontal_mirror')) - { - $this->_addDefine( - '' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - '' - ); - } else { - $this->_addDefine( - '' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - '' - ); - } - - return 'fill:url(#' . $id . ');'; - } - } elseif (($fillStyle != 'transparent') && ($fillStyle !== false)) { - $result = 'fill:' . $this->_color($fillStyle) . ';'; - if ($opacity = $this->_opacity($fillStyle)) { - $result .= 'fill-opacity:' . $opacity . ';'; - } - return $result; - } else { - return 'fill:none;'; - } - } - - /** - * Sets an image that should be used for filling - * - * @param string $filename The filename of the image to fill with - */ - function setFillImage($filename) - { - } - - /** - * Sets a gradient fill - * - * @param array $gradient Gradient fill options - */ - function setGradientFill($gradient) - { - $this->_fillStyle = $gradient; - $this->_fillStyle['type'] = 'gradient'; - } - - /** - * Sets the font options. - * - * The $font array may have the following entries: - * 'type' = 'ttf' (TrueType) or omitted for default
- * If 'type' = 'ttf' then the following can be specified
- * 'size' = size in pixels
- * 'angle' = the angle with which to write the text - * 'file' = the .ttf file (either the basename, filename or full path) - * - * @param array $font The font options. - */ - function setFont($fontOptions) - { - parent::setFont($fontOptions); - if (!isset($this->_font['size'])) { - $this->_font['size'] = 10; - } - } - - /** - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'color': mixed [optional] The line color - * @param array $params Parameter array - */ - function line($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - $color = (isset($params['color']) ? $params['color'] : false); - - $style = $this->_getLineStyle($color) . $this->_getFillStyle('transparent'); - if ($style != '') { - $this->_addElement( - '', - $params - ); - } - parent::line($params); - } - - /** - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params = array()) - { - $connectEnds = (isset($params['connect']) ? $params['connect'] : false); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - if (!$connectEnds) { - $fillColor = 'transparent'; - } - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - - $first = true; - $spline = false; - $lastpoint = false; - foreach($this->_polygon as $point) { - if ($first) { - $points = 'M'; - } elseif (!$spline) { - $points .= ' L'; - } - - if (($spline) && ($lastpoint !== false)) { - $points .= ' ' .round($lastpoint['P1X']) . ',' . round($lastpoint['P1Y']) . ' ' . - round($lastpoint['P2X']) . ',' . round($lastpoint['P2Y']); - } - - $points .= ' ' . round($point['X']) . ',' . round($point['Y']); - - if ((isset($point['P1X'])) && (isset($point['P1Y'])) && - (isset($point['P2X'])) && (isset($point['P2Y']))) - { - if (($first) || (!$spline)) { - $points .= ' C'; - } - $lastpoint = $point; - $spline = true; - } else { - $spline = false; - } - $first = false; - } - if ($connectEnds) { - $point .= ' Z'; - } - $this->_addElement( - '', - $params - ); - - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - if ($style != '') { - $this->_addElement( - '', - $params - ); - } - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - if ($style != '') { - $this->_addElement( - '', - $params - ); - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $v1 = $this->_getX($params['v1']); - $v2 = $this->_getY($params['v2']); - $srx = (isset($params['srx']) ? $this->_getX($params['srx']) : false); - $sry = (isset($params['sry']) ? $this->_getX($params['sry']) : false); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $dv = max($v2, $v1) - min($v2, $v1); - if ($dv >= 360) { - $this->ellipse($params); - } - else { - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - if ($style != '') { - $x1 = ($x + $rx * cos(deg2rad(min($v1, $v2) % 360))); - $y1 = ($y + $ry * sin(deg2rad(min($v1, $v2) % 360))); - $x2 = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360))); - $y2 = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360))); - $this->_addElement( - '', - $params - ); - } - - parent::pieslice($params); - } - } - - /** - * Get the width of a text, - * - * @param string $text The text to get the width of - * @return int The width of the text - */ - function textWidth($text) - { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - return $this->_font['size']; - } else { - return round($this->_font['size'] * 0.7 * strlen($text)); - } - } - - /** - * Get the height of a text, - * - * @param string $text The text to get the height of - * @return int The height of the text - */ - function textHeight($text) - { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - return round($this->_font['size'] * 0.7 * strlen($text)); - } else { - return $this->_font['size']; - } - } - - /** - * Writes text - * - * Parameter array: - * 'x': int X-point of text - * 'y': int Y-point of text - * 'text': string The text to add - * 'alignment': array [optional] Alignment - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $text = $params['text']; - $color = (isset($params['color']) ? $params['color'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - $textHeight = $this->textHeight($text); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - $align = ''; - - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - $align .= 'writing-mode: tb-rl;'; - - if ($alignment['vertical'] == 'bottom') { - $align .= 'text-anchor:end;'; - //$y = $y + $textHeight; - } elseif ($alignment['vertical'] == 'center') { - //$y = $y + ($textHeight / 2); - $align .= 'text-anchor:middle;'; - } - } else { - if ($alignment['horizontal'] == 'right') { - $align .= 'text-anchor:end;'; - } elseif ($alignment['horizontal'] == 'center') { - $align .= 'text-anchor:middle;'; - } - - if ($alignment['vertical'] == 'top') { - $y = $y + $textHeight; - } elseif ($alignment['vertical'] == 'center') { - $y = $y + ($textHeight / 2); - } - } - - if (($color === false) && (isset($this->_font['color']))) { - $color = $this->_font['color']; - } - - $textColor = $this->_color($color); - $textOpacity = $this->_opacity($color); - - $this->_addElement( - '_font['angle']) && ($this->_font['angle'] > 0) ? - 'rotate="' . $this->_font['angle'] . '" ' : - '' - ) .*/ - 'style="' . - (isset($this->_font['name']) ? - 'font-family:' . $this->_font['name'] . ';' : '') . - 'font-size:' . $this->_font['size'] . 'px;fill=' . - $textColor . ($textOpacity ? ';fill-opacity:' . - $textOpacity : - '' - ) . ';' . $align . '">' . - str_replace('&', '&', $text) . - '', - $params - ); - parent::addText($params); - } - - /** - * Overlay image - * - * Parameter array: - * 'x': int X-point of overlayed image - * 'y': int Y-point of overlayed image - * 'filename': string The filename of the image to overlay - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * 'alignment': array [optional] Alignment - */ - function image($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $filename = $params['filename']; - - list($width, $height, $type, $attr) = getimagesize($filename); - $width = (isset($params['width']) ? $params['width'] : $width); - $height = (isset($params['height']) ? $params['height'] : $height); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - $file = fopen($filename, 'rb'); - $filedata = fread($file, filesize($filename)); - fclose($file); - - $data = 'data:' . image_type_to_mime_type($type) . ';base64,' . base64_encode($filedata); - $this->_addElement( - '', - $params - ); - parent::image($params); - } - - /** - * Start a group. - * - * What this does, depends on the canvas/format. - * - * @param string $name The name of the group - */ - function startGroup($name = false) - { - $name = strtolower(str_replace(' ', '_', $name)); - if (in_array($name, $this->_groupIDs)) { - $name .= $this->_id; - $this->_id++; - } - $this->_groupIDs[] = $name; - $this->_addElement(''); - $this->_indent .= ' '; - } - - /** - * End the "current" group. - * - * What this does, depends on the canvas/format. - */ - function endGroup() - { - $this->_indent = substr($this->_indent, 0, -4); - $this->_addElement(''); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - */ - function show($param = false) - { - parent::show($param); - $output = '' . "\n" . - '' . "\n" . - '' . "\n" . - ($this->_defs ? - ' ' . "\n" . - $this->_defs . - ' ' . "\n" : - '' - ) . - $this->_elements . - ''; - - header('Content-Type: image/svg+xml'); - header('Content-Disposition: inline; filename = "' . basename($_SERVER['PHP_SELF'], '.php') . '.svg"'); - print $output; - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - */ - function save($param = false) - { - parent::save($param); - $output = '' . "\n" . - '' . "\n" . - '' . "\n" . - ($this->_defs ? - ' ' . "\n" . - $this->_defs . - ' ' . "\n" : - '' - ) . - $this->_elements . - ''; - - $file = fopen($param['filename'], 'w+'); - fwrite($file, $output); - fclose($file); - } - - /** - * Get a canvas specific HTML tag. - * - * This method implicitly saves the canvas to the filename in the - * filesystem path specified and parses it as URL specified by URL path - * - * Parameter array: - * 'filename': string - * 'filepath': string Path to the file on the file system. Remember the final slash - * 'urlpath': string Path to the file available through an URL. Remember the final slash - * 'width': int The width in pixels - * 'height': int The height in pixels - */ - function toHtml($params) - { - parent::toHtml($params); - return ''; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: SVG.php,v 1.6 2005/08/24 20:37:35 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas.php + */ +require_once 'Image/Canvas.php'; + +/** + * Include file Image/Canvas/Color.php + */ +require_once 'Image/Canvas/Color.php'; + +/** + * SVG Canvas class. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ +class Image_Canvas_SVG extends Image_Canvas +{ + + /** + * The SVG elements + * @var string + * @access private + */ + var $_elements = ''; + + /** + * The SVG defines + * @var string + * @access private + */ + var $_defs = ''; + + /** + * The current indention level + * @var string + * @access private + */ + var $_indent = ' '; + + /** + * A unieuq id counter + * @var int + * @access private + */ + var $_id = 1; + + /** + * The current group ids + * @var array + * @access private + */ + var $_groupIDs = array(); + + /** + * Create the SVG canvas. + * + * Parameters available: + * + * 'width' The width of the graph + * + * 'height' The height of the graph + * + * @param array $param Parameter array + */ + function Image_Canvas_SVG($param) + { + parent::Image_Canvas($param); + $this->_reset(); + } + + /** + * Add a SVG "element" to the output + * + * @param string $element The element + * @access private + */ + function _addElement($element, $params) { + $elementdata = $this->_indent . $element . "\n"; + + if (isset($params['url'])) { + $url = $params['url']; + $target = (isset($params['target']) ? $params['target'] : false); + $alt = (isset($params['alt']) ? $params['alt'] : false); + + $tags = ''; + if (isset($params['htmltags'])) { + foreach ($params['htmltags'] as $key => $value) { + $tags .= ' '; + if (strpos($value, '"') >= 0) { + $tags .= $key . '=\'' . $value . '\''; + } else { + $tags .= $key . '="' . $value . '"'; + } + } + } + + $elementdata = + $this->_indent . '' . "\n" . + ' ' . $elementdata . + $this->_indent . '' . "\n"; + } + + + $this->_elements .= $elementdata; + } + + /** + * Add a SVG "define" to the output + * + * @param string $def The define + * @access private + */ + function _addDefine($def) { + $this->_defs .= ' ' . $def . "\n"; + } + + /** + * Get the color index for the RGB color + * + * @param int $color The color + * @return int A SVG compatible color + * @access private + */ + function _color($color = false) + { + if ($color === false) { + return 'transparent'; + } else { + $color = Image_Canvas_Color::color2RGB($color); + return 'rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')'; + } + } + + /** + * Get the opacity for the RGB color + * + * @param int $color The color + * @return int A SVG compatible opacity value + * @access private + */ + function _opacity($color = false) + { + if ($color === false) { + return false; + } else { + $color = Image_Canvas_Color::color2RGB($color); + if ($color[3] != 255) { + return sprintf('%0.1f', $color[3]/255); + } else { + return false; + } + } + } + + /** + * Get the SVG applicable linestyle + * + * @param mixed $lineStyle The line style to return, false if the one + * explicitly set + * @return mixed A SVG compatible linestyle + * @access private + */ + function _getLineStyle($lineStyle = false) + { + $result = ''; + if ($lineStyle === false) { + $lineStyle = $this->_lineStyle; + } + + // TODO Linestyles (i.e. fx. dotted) does not work + + if (($lineStyle != 'transparent') && ($lineStyle !== false)) { + $result = 'stroke-width:' . $this->_thickness . ';'; + $result .= 'stroke:' .$this->_color($lineStyle) . ';'; + if ($opacity = $this->_opacity($lineStyle)) { + $result .= 'stroke-opacity:' . $opacity . ';'; + } + } + return $result; + } + + /** + * Get the SVG applicable fillstyle + * + * @param mixed $fillStyle The fillstyle to return, false if the one + * explicitly set + * @return mixed A SVG compatible fillstyle + * @access private + */ + function _getFillStyle($fillStyle = false) + { + $result = ''; + if ($fillStyle === false) { + $fillStyle = $this->_fillStyle; + } + + if (is_array($fillStyle)) { + if ($fillStyle['type'] == 'gradient') { + $id = 'gradient_' . ($this->_id++); + $startColor = $this->_color($fillStyle['start']); + $endColor = $this->_color($fillStyle['end']); + $startOpacity = $this->_opacity($fillStyle['start']); + $endOpacity = $this->_opacity($fillStyle['end']); + + switch ($fillStyle['direction']) { + case 'horizontal': + case 'horizontal_mirror': + $x1 = '0%'; + $y1 = '0%'; + $x2 = '100%'; + $y2 = '0%'; + break; + + case 'vertical': + case 'vertical_mirror': + $x1 = '0%'; + $y1 = '100%'; + $x2 = '0%'; + $y2 = '0%'; + break; + + case 'diagonal_tl_br': + $x1 = '0%'; + $y1 = '0%'; + $x2 = '100%'; + $y2 = '100%'; + break; + + case 'diagonal_bl_tr': + $x1 = '0%'; + $y1 = '100%'; + $x2 = '100%'; + $y2 = '0%'; + break; + + case 'radial': + $cx = '50%'; + $cy = '50%'; + $r = '100%'; + $fx = '50%'; + $fy = '50%'; + break; + + } + + if ($fillStyle['direction'] == 'radial') { + $this->_addDefine( + '' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + '' + ); + } elseif (($fillStyle['direction'] == 'vertical_mirror') || + ($fillStyle['direction'] == 'horizontal_mirror')) + { + $this->_addDefine( + '' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + '' + ); + } else { + $this->_addDefine( + '' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + '' + ); + } + + return 'fill:url(#' . $id . ');'; + } + } elseif (($fillStyle != 'transparent') && ($fillStyle !== false)) { + $result = 'fill:' . $this->_color($fillStyle) . ';'; + if ($opacity = $this->_opacity($fillStyle)) { + $result .= 'fill-opacity:' . $opacity . ';'; + } + return $result; + } else { + return 'fill:none;'; + } + } + + /** + * Sets an image that should be used for filling + * + * @param string $filename The filename of the image to fill with + */ + function setFillImage($filename) + { + } + + /** + * Sets a gradient fill + * + * @param array $gradient Gradient fill options + */ + function setGradientFill($gradient) + { + $this->_fillStyle = $gradient; + $this->_fillStyle['type'] = 'gradient'; + } + + /** + * Sets the font options. + * + * The $font array may have the following entries: + * 'type' = 'ttf' (TrueType) or omitted for default
+ * If 'type' = 'ttf' then the following can be specified
+ * 'size' = size in pixels
+ * 'angle' = the angle with which to write the text + * 'file' = the .ttf file (either the basename, filename or full path) + * + * @param array $font The font options. + */ + function setFont($fontOptions) + { + parent::setFont($fontOptions); + if (!isset($this->_font['size'])) { + $this->_font['size'] = 10; + } + } + + /** + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'color': mixed [optional] The line color + * @param array $params Parameter array + */ + function line($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + $color = (isset($params['color']) ? $params['color'] : false); + + $style = $this->_getLineStyle($color) . $this->_getFillStyle('transparent'); + if ($style != '') { + $this->_addElement( + '', + $params + ); + } + parent::line($params); + } + + /** + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params = array()) + { + $connectEnds = (isset($params['connect']) ? $params['connect'] : false); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + if (!$connectEnds) { + $fillColor = 'transparent'; + } + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + + $first = true; + $spline = false; + $lastpoint = false; + foreach($this->_polygon as $point) { + if ($first) { + $points = 'M'; + } elseif (!$spline) { + $points .= ' L'; + } + + if (($spline) && ($lastpoint !== false)) { + $points .= ' ' .round($lastpoint['P1X']) . ',' . round($lastpoint['P1Y']) . ' ' . + round($lastpoint['P2X']) . ',' . round($lastpoint['P2Y']); + } + + $points .= ' ' . round($point['X']) . ',' . round($point['Y']); + + if ((isset($point['P1X'])) && (isset($point['P1Y'])) && + (isset($point['P2X'])) && (isset($point['P2Y']))) + { + if (($first) || (!$spline)) { + $points .= ' C'; + } + $lastpoint = $point; + $spline = true; + } else { + $spline = false; + } + $first = false; + } + if ($connectEnds) { + $point .= ' Z'; + } + $this->_addElement( + '', + $params + ); + + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + if ($style != '') { + $this->_addElement( + '', + $params + ); + } + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $this->_getX($params['rx']); + $ry = $this->_getY($params['ry']); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + if ($style != '') { + $this->_addElement( + '', + $params + ); + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $this->_getX($params['rx']); + $ry = $this->_getY($params['ry']); + $v1 = $this->_getX($params['v1']); + $v2 = $this->_getY($params['v2']); + $srx = (isset($params['srx']) ? $this->_getX($params['srx']) : false); + $sry = (isset($params['sry']) ? $this->_getX($params['sry']) : false); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $dv = max($v2, $v1) - min($v2, $v1); + if ($dv >= 360) { + $this->ellipse($params); + } + else { + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + if ($style != '') { + $x1 = ($x + $rx * cos(deg2rad(min($v1, $v2) % 360))); + $y1 = ($y + $ry * sin(deg2rad(min($v1, $v2) % 360))); + $x2 = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360))); + $y2 = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360))); + $this->_addElement( + '', + $params + ); + } + + parent::pieslice($params); + } + } + + /** + * Get the width of a text, + * + * @param string $text The text to get the width of + * @return int The width of the text + */ + function textWidth($text) + { + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + return $this->_font['size']; + } else { + return round($this->_font['size'] * 0.7 * strlen($text)); + } + } + + /** + * Get the height of a text, + * + * @param string $text The text to get the height of + * @return int The height of the text + */ + function textHeight($text) + { + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + return round($this->_font['size'] * 0.7 * strlen($text)); + } else { + return $this->_font['size']; + } + } + + /** + * Writes text + * + * Parameter array: + * 'x': int X-point of text + * 'y': int Y-point of text + * 'text': string The text to add + * 'alignment': array [optional] Alignment + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $text = $params['text']; + $color = (isset($params['color']) ? $params['color'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + $textHeight = $this->textHeight($text); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + $align = ''; + + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + $align .= 'writing-mode: tb-rl;'; + + if ($alignment['vertical'] == 'bottom') { + $align .= 'text-anchor:end;'; + //$y = $y + $textHeight; + } elseif ($alignment['vertical'] == 'center') { + //$y = $y + ($textHeight / 2); + $align .= 'text-anchor:middle;'; + } + } else { + if ($alignment['horizontal'] == 'right') { + $align .= 'text-anchor:end;'; + } elseif ($alignment['horizontal'] == 'center') { + $align .= 'text-anchor:middle;'; + } + + if ($alignment['vertical'] == 'top') { + $y = $y + $textHeight; + } elseif ($alignment['vertical'] == 'center') { + $y = $y + ($textHeight / 2); + } + } + + if (($color === false) && (isset($this->_font['color']))) { + $color = $this->_font['color']; + } + + $textColor = $this->_color($color); + $textOpacity = $this->_opacity($color); + + $this->_addElement( + '_font['angle']) && ($this->_font['angle'] > 0) ? + 'rotate="' . $this->_font['angle'] . '" ' : + '' + ) .*/ + 'style="' . + (isset($this->_font['name']) ? + 'font-family:' . $this->_font['name'] . ';' : '') . + 'font-size:' . $this->_font['size'] . 'px;fill=' . + $textColor . ($textOpacity ? ';fill-opacity:' . + $textOpacity : + '' + ) . ';' . $align . '">' . + str_replace('&', '&', $text) . + '', + $params + ); + parent::addText($params); + } + + /** + * Overlay image + * + * Parameter array: + * 'x': int X-point of overlayed image + * 'y': int Y-point of overlayed image + * 'filename': string The filename of the image to overlay + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * 'alignment': array [optional] Alignment + */ + function image($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $filename = $params['filename']; + + list($width, $height, $type, $attr) = getimagesize($filename); + $width = (isset($params['width']) ? $params['width'] : $width); + $height = (isset($params['height']) ? $params['height'] : $height); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + $file = fopen($filename, 'rb'); + $filedata = fread($file, filesize($filename)); + fclose($file); + + $data = 'data:' . image_type_to_mime_type($type) . ';base64,' . base64_encode($filedata); + $this->_addElement( + '', + $params + ); + parent::image($params); + } + + /** + * Start a group. + * + * What this does, depends on the canvas/format. + * + * @param string $name The name of the group + */ + function startGroup($name = false) + { + $name = strtolower(str_replace(' ', '_', $name)); + if (in_array($name, $this->_groupIDs)) { + $name .= $this->_id; + $this->_id++; + } + $this->_groupIDs[] = $name; + $this->_addElement(''); + $this->_indent .= ' '; + } + + /** + * End the "current" group. + * + * What this does, depends on the canvas/format. + */ + function endGroup() + { + $this->_indent = substr($this->_indent, 0, -4); + $this->_addElement(''); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + */ + function show($param = false) + { + parent::show($param); + $output = '' . "\n" . + '' . "\n" . + '' . "\n" . + ($this->_defs ? + ' ' . "\n" . + $this->_defs . + ' ' . "\n" : + '' + ) . + $this->_elements . + ''; + + header('Content-Type: image/svg+xml'); + header('Content-Disposition: inline; filename = "' . basename($_SERVER['PHP_SELF'], '.php') . '.svg"'); + print $output; + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + */ + function save($param = false) + { + parent::save($param); + $output = '' . "\n" . + '' . "\n" . + '' . "\n" . + ($this->_defs ? + ' ' . "\n" . + $this->_defs . + ' ' . "\n" : + '' + ) . + $this->_elements . + ''; + + $file = fopen($param['filename'], 'w+'); + fwrite($file, $output); + fclose($file); + } + + /** + * Get a canvas specific HTML tag. + * + * This method implicitly saves the canvas to the filename in the + * filesystem path specified and parses it as URL specified by URL path + * + * Parameter array: + * 'filename': string + * 'filepath': string Path to the file on the file system. Remember the final slash + * 'urlpath': string Path to the file available through an URL. Remember the final slash + * 'width': int The width in pixels + * 'height': int The height in pixels + */ + function toHtml($params) + { + parent::toHtml($params); + return ''; + } + +} + ?> \ No newline at end of file diff --git a/pandora_console/reporting/Image/Canvas/Tool.php b/pandora_console/reporting/Image/Canvas/Tool.php index fb1393a923..7252f47827 100644 --- a/pandora_console/reporting/Image/Canvas/Tool.php +++ b/pandora_console/reporting/Image/Canvas/Tool.php @@ -1,217 +1,217 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Tool.php,v 1.3 2005/08/22 20:52:11 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * This class contains a set of tool-functions. - * - * These functions are all to be called statically - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @abstract - */ -class Image_Canvas_Tool -{ - - /** - * Maps a font name to an actual font file (fx. a .ttf file) - * - * Used to translate names (i.e. 'Courier New' to 'cour.ttf' or - * '/Windows/Fonts/Cour.ttf') - * - * Font names are translated using the tab-separated file - * Image/Canvas/Tool/fontmap.txt. - * - * The translated font-name (or the original if no translation) exists is - * then returned if it is an existing file, otherwise the file is searched - * first in the path specified by IMAGE_CANVAS_SYSTEM_FONT_PATH defined in - * Image/Canvas.php, then in the Image/Canvas/Fonts folder. If a font is - * still not found and the name is not beginning with a '/' the search is - * left to the library, otherwise the font is deemed non-existing. - * - * @param string $name The name of the font - * @param string $type The needed file type of the font - * @return string The filename of the font - * @static - */ - function fontMap($name, $type = '.ttf') - { - static $_fontMap; - - if (!is_array($_fontMap)) { - if (file_exists($fontmap = (dirname(__FILE__) . '/Fonts/fontmap.txt'))) { - $file = file($fontmap); - foreach($file as $fontmapping) { - list($fontname, $filenames) = explode(',', $fontmapping, 2); - $fontname = trim($fontname); - $filenames = trim($filenames); - $filenames = explode(',', $filenames); - foreach ($filenames as $filename) { - $type_pos = strrpos($filename, '.'); - $type = substr($filename, $type_pos); - $_fontMap[$fontname][$type] = $filename; - } - } - } - } - - $type = strtolower($type); - - if ((isset($_fontMap[$name])) && (isset($_fontMap[$name][$type]))) { - $filename = $_fontMap[$name][$type]; - } else { - $filename = $name; - } - - if (substr($filename, -strlen($type)) !== $type) { - $filename .= $type; - } - - $result = false; - if (file_exists($filename)) { - $result = $filename; - } elseif (file_exists($file = (IMAGE_CANVAS_SYSTEM_FONT_PATH . $filename))) { - $result = $file; - } elseif (file_exists($file = (dirname(__FILE__) . '/Fonts/' . $filename))) { - $result = $file; - } elseif (substr($name, 0, 1) !== '/') { - // leave it to the library to find the font - $result = $name; - } - - return str_replace('\\', '/', $result); - } - - /** - * Return the average of 2 points - * - * @param double P1 1st point - * @param double P2 2nd point - * @return double The average of P1 and P2 - * @static - */ - function mid($p1, $p2) - { - return ($p1 + $p2) / 2; - } - - /** - * Mirrors P1 in P2 by a amount of Factor - * - * @param double $p1 1st point, point to mirror - * @param double $o2 2nd point, mirror point - * @param double $factor Mirror factor, 0 returns $p2, 1 returns a pure - * mirror, ie $p1 on the exact other side of $p2 - * @return double $p1 mirrored in $p2 by Factor - * @static - */ - function mirror($p1, $p2, $factor = 1) - { - return $p2 + $factor * ($p2 - $p1); - } - - /** - * Calculates a Bezier control point, this function must be called for BOTH - * X and Y coordinates (will it work for 3D coordinates!?) - * - * @param double $p1 1st point - * @param double $p2 Point to - * @param double $factor Mirror factor, 0 returns P2, 1 returns a pure - * mirror, i.e. P1 on the exact other side of P2 - * @return double P1 mirrored in P2 by Factor - * @static - */ - function controlPoint($p1, $p2, $factor, $smoothFactor = 0.75) - { - $sa = Image_Canvas_Tool::mirror($p1, $p2, $smoothFactor); - $sb = Image_Canvas_Tool::mid($p2, $sa); - - $m = Image_Canvas_Tool::mid($p2, $factor); - - $pC = Image_Canvas_Tool::mid($sb, $m); - - return $pC; - } - - /** - * Calculates a Bezier point, this function must be called for BOTH X and Y - * coordinates (will it work for 3D coordinates!?) - * - * @param double $t A position between $p2 and $p3, value between 0 and 1 - * @param double $p1 Point to use for calculating control points - * @param double $p2 Point 1 to calculate bezier curve between - * @param double $p3 Point 2 to calculate bezier curve between - * @param double $p4 Point to use for calculating control points - * @return double The bezier value of the point t between $p2 and $p3 using - * $p1 and $p4 to calculate control points - * @static - */ - function bezier($t, $p1, $p2, $p3, $p4) - { - // (1-t)^3*p1 + 3*(1-t)^2*t*p2 + 3*(1-t)*t^2*p3 + t^3*p4 - return pow(1 - $t, 3) * $p1 + - 3 * pow(1 - $t, 2) * $t * $p2 + - 3 * (1 - $t) * pow($t, 2) * $p3 + - pow($t, 3) * $p4; - } - - /** - * Gets the angle / slope of a line relative to horizontal (left -> right) - * - * @param double $x0 The starting x point - * @param double $y0 The starting y point - * @param double $x1 The ending x point - * @param double $y1 The ending y point - * @param double The angle in degrees of the line - * @static - */ - function getAngle($x0, $y0, $x1, $y1) - { - - $dx = ($x1 - $x0); - $dy = ($y1 - $y0); - $l = sqrt($dx * $dx + $dy * $dy); - $v = rad2deg(asin(($y0 - $y1) / $l)); - if ($dx < 0) { - $v = 180 - $v; - } - return $v; - - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Tool.php,v 1.3 2005/08/22 20:52:11 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * This class contains a set of tool-functions. + * + * These functions are all to be called statically + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @abstract + */ +class Image_Canvas_Tool +{ + + /** + * Maps a font name to an actual font file (fx. a .ttf file) + * + * Used to translate names (i.e. 'Courier New' to 'cour.ttf' or + * '/Windows/Fonts/Cour.ttf') + * + * Font names are translated using the tab-separated file + * Image/Canvas/Tool/fontmap.txt. + * + * The translated font-name (or the original if no translation) exists is + * then returned if it is an existing file, otherwise the file is searched + * first in the path specified by IMAGE_CANVAS_SYSTEM_FONT_PATH defined in + * Image/Canvas.php, then in the Image/Canvas/Fonts folder. If a font is + * still not found and the name is not beginning with a '/' the search is + * left to the library, otherwise the font is deemed non-existing. + * + * @param string $name The name of the font + * @param string $type The needed file type of the font + * @return string The filename of the font + * @static + */ + function fontMap($name, $type = '.ttf') + { + static $_fontMap; + + if (!is_array($_fontMap)) { + if (file_exists($fontmap = (dirname(__FILE__) . '/Fonts/fontmap.txt'))) { + $file = file($fontmap); + foreach($file as $fontmapping) { + list($fontname, $filenames) = explode(',', $fontmapping, 2); + $fontname = trim($fontname); + $filenames = trim($filenames); + $filenames = explode(',', $filenames); + foreach ($filenames as $filename) { + $type_pos = strrpos($filename, '.'); + $type = substr($filename, $type_pos); + $_fontMap[$fontname][$type] = $filename; + } + } + } + } + + $type = strtolower($type); + + if ((isset($_fontMap[$name])) && (isset($_fontMap[$name][$type]))) { + $filename = $_fontMap[$name][$type]; + } else { + $filename = $name; + } + + if (substr($filename, -strlen($type)) !== $type) { + $filename .= $type; + } + + $result = false; + if (file_exists($filename)) { + $result = $filename; + } elseif (file_exists($file = (IMAGE_CANVAS_SYSTEM_FONT_PATH . $filename))) { + $result = $file; + } elseif (file_exists($file = (dirname(__FILE__) . '/Fonts/' . $filename))) { + $result = $file; + } elseif (substr($name, 0, 1) !== '/') { + // leave it to the library to find the font + $result = $name; + } + + return str_replace('\\', '/', $result); + } + + /** + * Return the average of 2 points + * + * @param double P1 1st point + * @param double P2 2nd point + * @return double The average of P1 and P2 + * @static + */ + function mid($p1, $p2) + { + return ($p1 + $p2) / 2; + } + + /** + * Mirrors P1 in P2 by a amount of Factor + * + * @param double $p1 1st point, point to mirror + * @param double $o2 2nd point, mirror point + * @param double $factor Mirror factor, 0 returns $p2, 1 returns a pure + * mirror, ie $p1 on the exact other side of $p2 + * @return double $p1 mirrored in $p2 by Factor + * @static + */ + function mirror($p1, $p2, $factor = 1) + { + return $p2 + $factor * ($p2 - $p1); + } + + /** + * Calculates a Bezier control point, this function must be called for BOTH + * X and Y coordinates (will it work for 3D coordinates!?) + * + * @param double $p1 1st point + * @param double $p2 Point to + * @param double $factor Mirror factor, 0 returns P2, 1 returns a pure + * mirror, i.e. P1 on the exact other side of P2 + * @return double P1 mirrored in P2 by Factor + * @static + */ + function controlPoint($p1, $p2, $factor, $smoothFactor = 0.75) + { + $sa = Image_Canvas_Tool::mirror($p1, $p2, $smoothFactor); + $sb = Image_Canvas_Tool::mid($p2, $sa); + + $m = Image_Canvas_Tool::mid($p2, $factor); + + $pC = Image_Canvas_Tool::mid($sb, $m); + + return $pC; + } + + /** + * Calculates a Bezier point, this function must be called for BOTH X and Y + * coordinates (will it work for 3D coordinates!?) + * + * @param double $t A position between $p2 and $p3, value between 0 and 1 + * @param double $p1 Point to use for calculating control points + * @param double $p2 Point 1 to calculate bezier curve between + * @param double $p3 Point 2 to calculate bezier curve between + * @param double $p4 Point to use for calculating control points + * @return double The bezier value of the point t between $p2 and $p3 using + * $p1 and $p4 to calculate control points + * @static + */ + function bezier($t, $p1, $p2, $p3, $p4) + { + // (1-t)^3*p1 + 3*(1-t)^2*t*p2 + 3*(1-t)*t^2*p3 + t^3*p4 + return pow(1 - $t, 3) * $p1 + + 3 * pow(1 - $t, 2) * $t * $p2 + + 3 * (1 - $t) * pow($t, 2) * $p3 + + pow($t, 3) * $p4; + } + + /** + * Gets the angle / slope of a line relative to horizontal (left -> right) + * + * @param double $x0 The starting x point + * @param double $y0 The starting y point + * @param double $x1 The ending x point + * @param double $y1 The ending y point + * @param double The angle in degrees of the line + * @static + */ + function getAngle($x0, $y0, $x1, $y1) + { + + $dx = ($x1 - $x0); + $dy = ($y1 - $y0); + $l = sqrt($dx * $dx + $dy * $dy); + $v = rad2deg(asin(($y0 - $y1) / $l)); + if ($dx < 0) { + $v = 180 - $v; + } + return $v; + + } + +} + ?> \ No newline at end of file diff --git a/pandora_console/reporting/Image/Canvas/WithMap.php b/pandora_console/reporting/Image/Canvas/WithMap.php index b968975797..3206af4b89 100644 --- a/pandora_console/reporting/Image/Canvas/WithMap.php +++ b/pandora_console/reporting/Image/Canvas/WithMap.php @@ -1,278 +1,278 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: WithMap.php,v 1.3 2005/08/24 20:37:35 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Class for handling different output formats including a HTML image map - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @since version 0.2.0 - * @abstract - */ -class Image_Canvas_WithMap extends Image_Canvas -{ - - /** - * The image map - * @var Image_Canvas_ImageMap - * @access private - */ - var $_imageMap = null; - - /** - * Create the canvas. - * - * Parameters available: - * - * 'width' The width of the graph on the canvas - * - * 'height' The height of the graph on the canvas - * - * 'left' The left offset of the graph on the canvas - * - * 'top' The top offset of the graph on the canvas - * - * 'usemap' Initialize an image map - * - * @param array $params Parameter array - * @abstract - */ - function Image_Canvas_WithMap($params) - { - parent::Image_Canvas($params); - - if ((isset($params['usemap'])) && ($params['usemap'] === true)) { - $this->_imageMap =& Image_Canvas::factory( - 'ImageMap', - array( - 'left' => $this->_left, - 'top' => $this->_top, - 'width' => $this->_width, - 'height' => $this->_height - ) - ); - } - } - /** - * Draw a line - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'color': mixed [optional] The line color - * @param array $params Parameter array - */ - function line($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->line($params); - } - parent::line($params); - } - - /** - * Adds vertex to a polygon - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * @param array $params Parameter array - */ - function addVertex($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->addVertex($params); - } - parent::addVertex($params); - } - - /** - * Adds "splined" vertex to a polygon - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * 'p1x': X Control point 1 - * 'p1y': Y Control point 1 - * 'p2x': X Control point 2 - * 'p2y': Y Control point 2 - * @param array $params Parameter array - */ - function addSpline($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->addSpline($params); - } - parent::addSpline($params); - } - - /** - * Draws a polygon - * - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->polygon($params); - } - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->rectangle($params); - } - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->ellipse($params); - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->pieslice($params); - } - parent::pieslice($params); - } - - /** - * Writes text - * - * Parameter array: - * 'x': int X-point of text - * 'y': int Y-point of text - * 'text': string The text to add - * 'alignment': array [optional] Alignment - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->addText($params); - } - parent::addText($params); - } - - /** - * Overlay image - * - * Parameter array: - * 'x': int X-point of overlayed image - * 'y': int Y-point of overlayed image - * 'filename': string The filename of the image to overlay - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * 'alignment': array [optional] Alignment - */ - function image($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->image($params); - } - parent::image($params); - } - - /** - * Get the imagemap - * @return Image_Graph_ImageMap The image map (or false if none) - */ - function &getImageMap() - { - $result = null; - if (isset($this->_imageMap)) { - $result =& $this->_imageMap; - } - return $result; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: WithMap.php,v 1.3 2005/08/24 20:37:35 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Class for handling different output formats including a HTML image map + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @since version 0.2.0 + * @abstract + */ +class Image_Canvas_WithMap extends Image_Canvas +{ + + /** + * The image map + * @var Image_Canvas_ImageMap + * @access private + */ + var $_imageMap = null; + + /** + * Create the canvas. + * + * Parameters available: + * + * 'width' The width of the graph on the canvas + * + * 'height' The height of the graph on the canvas + * + * 'left' The left offset of the graph on the canvas + * + * 'top' The top offset of the graph on the canvas + * + * 'usemap' Initialize an image map + * + * @param array $params Parameter array + * @abstract + */ + function Image_Canvas_WithMap($params) + { + parent::Image_Canvas($params); + + if ((isset($params['usemap'])) && ($params['usemap'] === true)) { + $this->_imageMap =& Image_Canvas::factory( + 'ImageMap', + array( + 'left' => $this->_left, + 'top' => $this->_top, + 'width' => $this->_width, + 'height' => $this->_height + ) + ); + } + } + /** + * Draw a line + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'color': mixed [optional] The line color + * @param array $params Parameter array + */ + function line($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->line($params); + } + parent::line($params); + } + + /** + * Adds vertex to a polygon + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * @param array $params Parameter array + */ + function addVertex($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->addVertex($params); + } + parent::addVertex($params); + } + + /** + * Adds "splined" vertex to a polygon + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * 'p1x': X Control point 1 + * 'p1y': Y Control point 1 + * 'p2x': X Control point 2 + * 'p2y': Y Control point 2 + * @param array $params Parameter array + */ + function addSpline($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->addSpline($params); + } + parent::addSpline($params); + } + + /** + * Draws a polygon + * + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->polygon($params); + } + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->rectangle($params); + } + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->ellipse($params); + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->pieslice($params); + } + parent::pieslice($params); + } + + /** + * Writes text + * + * Parameter array: + * 'x': int X-point of text + * 'y': int Y-point of text + * 'text': string The text to add + * 'alignment': array [optional] Alignment + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->addText($params); + } + parent::addText($params); + } + + /** + * Overlay image + * + * Parameter array: + * 'x': int X-point of overlayed image + * 'y': int Y-point of overlayed image + * 'filename': string The filename of the image to overlay + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * 'alignment': array [optional] Alignment + */ + function image($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->image($params); + } + parent::image($params); + } + + /** + * Get the imagemap + * @return Image_Graph_ImageMap The image map (or false if none) + */ + function &getImageMap() + { + $result = null; + if (isset($this->_imageMap)) { + $result =& $this->_imageMap; + } + return $result; + } + +} + ?> \ No newline at end of file diff --git a/pandora_console/reporting/Image/Color.php b/pandora_console/reporting/Image/Color.php index 99e83c9601..471f6f2467 100644 --- a/pandora_console/reporting/Image/Color.php +++ b/pandora_console/reporting/Image/Color.php @@ -1,719 +1,719 @@ - - * @author Andrew Morton - * @copyright 2003-2005 The PHP Group - * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Color.php,v 1.15 2005/09/12 19:12:02 drewish Exp $ - * @link http://pear.php.net/package/Image_Color - */ - -/** - * Image_Color handles color conversion and mixing. - * - * The class is quick, simple to use, and does its job fairly well but it's got - * some code smells: - * - Call setColors() for some functions but not others. - * - Different functions expect different color formats. setColors() only - * accepts hex while allocateColor() will accept named or hex (provided the - * hex ones start with the # character). - * - Some conversions go in only one direction, ie HSV->RGB but no RGB->HSV. - * I'm going to try to straighten out some of this but I'll be hard to do so - * without breaking backwards compatibility. - * - * @category Image - * @package Image_Color - * @author Jason Lotito - * @author Andrew Morton - * @copyright 2003-2005 The PHP Group - * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 0.1.2 - * @link http://pear.php.net/package/Image_Color - */ -class Image_Color -{ - /** - * First color that the class handles for ranges and mixes. - * @var array - * @access public - * @see setColors() - */ - var $color1 = array(); - - /** - * Second color that the class handles for ranges and mixes. - * @var array - * @access public - * @see setColors() - */ - var $color2 = array(); - - /** - * Boolean value for determining whether colors outputted should be limited - * to the web safe pallet or not. - * - * @var boolean - * @access private - * @see setWebSafe() - */ - var $_websafeb = false; - - /** - * Mix two colors together by finding their average. If the colors are not - * passed as parameters, the class's colors will be mixed instead. - * - * @param string $col1 The first color you want to mix - * @param string $col2 The second color you want to mix - * @return string The mixed color. - * @access public - * @author Jason Lotito - * @uses _setColors() to assign the colors if any are passed to the - * class. - */ - function mixColors($col1 = false, $col2 = false) - { - if ($col1) { - $this->_setColors($col1, $col2); - } - - // after finding the average, it will be a float. add 0.5 and then - // cast to an integer to properly round it to an integer. - $color3[0] = (int) ((($this->color1[0] + $this->color2[0]) / 2) + 0.5); - $color3[1] = (int) ((($this->color1[1] + $this->color2[1]) / 2) + 0.5); - $color3[2] = (int) ((($this->color1[2] + $this->color2[2]) / 2) + 0.5); - - if ($this->_websafeb) { - array_walk($color3, '_makeWebSafe'); - } - - return Image_Color::rgb2hex($color3); - } - - /** - * Determines whether colors the returned by this class will be rounded to - * the nearest web safe value. - * - * @param boolean $bool Indicates if colors should be limited to the - * websafe pallet. - * @return void - * @access public - * @author Jason Lotito - */ - function setWebSafe($bool = true) - { - $this->_websafeb = (boolean) $bool; - } - - /** - * Set the two colors this class uses for mixing and ranges. - * - * @param string $col1 The first color in hex format - * @param string $col2 The second color in hex format - * @return void - * @access public - * @author Jason Lotito - */ - function setColors($col1, $col2) - { - $this->_setColors($col1, $col2); - } - - /** - * Get the range of colors between the class's two colors, given a degree. - * - * @param integer $degrees How large a 'step' we should take between the - * colors. - * @return array Returns an array of hex strings, one element for each - * color. - * @access public - * @author Jason Lotito - * @todo Allow for degrees for individual parts of the colors. - */ - function getRange($degrees = 2) - { - if ($degrees == 0) { - $degrees = 1; - } - - // The degrees give us how much we should advance each color at each - // phase of the loop. This way, the advance is equal throughout all - // the colors. - - $red_steps = ($this->color2[0] - $this->color1[0]) / $degrees; - $green_steps = ($this->color2[1] - $this->color1[1]) / $degrees; - $blue_steps = ($this->color2[2] - $this->color1[2]) / $degrees; - - $allcolors = array(); - - /** - * The loop stops once any color has gone beyond the end color. - */ - - // Loop through all the degrees between the colors - for ($x = 0; $x < $degrees; $x++) { - $col[0] = $red_steps * $x; - $col[1] = $green_steps * $x; - $col[2] = $blue_steps * $x; - - // Loop through each R, G, and B - for ($i = 0; $i < 3; $i++) { - $partcolor = $this->color1[$i] + $col[$i]; - // If the color is less than 256 - if ($partcolor < 256) { - // Makes sure the colors is not less than 0 - if ($partcolor > -1) { - $newcolor[$i] = $partcolor; - } else { - $newcolor[$i] = 0; - } - // Color was greater than 255 - } else { - $newcolor[$i] = 255; - } - } - - if ($this->_websafeb) { - array_walk($newcolor, '_makeWebSafe'); - } - - $allcolors[] = Image_Color::rgb2hex($newcolor); - } - - return $allcolors; - } - - /** - * Change the lightness of the class's two colors. - * - * @param integer $degree The degree of the change. Positive values - * lighten the color while negative values will darken it. - * @return void - * @access public - * @author Jason Lotito - * @uses Image_Color::$color1 as an input and return value. - * @uses Image_Color::$color2 as an input and return value. - */ - function changeLightness($degree = 10) - { - $color1 =& $this->color1; - $color2 =& $this->color2; - - for ($x = 0; $x < 3; $x++) { - if (($color1[$x] + $degree) < 256) { - if (($color1[$x] + $degree) > -1) { - $color1[$x] += $degree; - } else { - $color1[$x] = 0; - } - } else { - $color1[$x] = 255; - } - - if (($color2[$x] + $degree) < 256) { - if (($color2[$x] + $degree) > -1) { - $color2[$x] += $degree; - } else { - $color2[$x] = 0; - } - } else { - $color2[$x] = 255; - } - } - } - - /** - * Determine if a light or dark text color would be more readable on a - * background of a given color. This is determined by the G(reen) value of - * RGB. You can change the dark and the light colors from their default - * black and white. - * - * @param string $color The hex color to analyze - * @param string $light The light color value to return if we should - * have light text. - * @param string $dark The dark color value to return if we should have - * dark text. - * @return string The light or dark value which would make the text most - * readable. - * @access public - * @static - * @author Jason Lotito - */ - function getTextColor($color, $light = '#FFFFFF', $dark = '#000000') - { - $color = Image_Color::_splitColor($color); - if ($color[1] > hexdec('66')) { - return $dark; - } else { - return $light; - } - } - - - /** - * Internal method to set the colors. - * - * @param string $col1 First color, either a name or hex value - * @param string $col2 Second color, either a name or hex value - * @return void - * @access private - * @author Jason Lotito - */ - function _setColors($col1, $col2) - { - if ($col1) { - $this->color1 = Image_Color::_splitColor($col1); - } - if ($col2) { - $this->color2 = Image_Color::_splitColor($col2); - } - } - - /** - * Given a color, properly split it up into a 3 element RGB array. - * - * @param string $color The color. - * @return array A three element RGB array. - * @access private - * @static - * @author Jason Lotito - */ - function _splitColor($color) - { - $color = str_replace('#', '', $color); - $c[] = hexdec(substr($color, 0, 2)); - $c[] = hexdec(substr($color, 2, 2)); - $c[] = hexdec(substr($color, 4, 2)); - return $c; - } - - /** - * This is deprecated. Use rgb2hex() instead. - * @access private - * @deprecated Function deprecated after 1.0.1 - * @see rgb2hex(). - */ - function _returnColor ( $color ) - { - return Image_Color::rgb2hex($color); - } - - /** - * Convert an RGB array to a hex string. - * - * @param array $color 3 element RGB array. - * @return string Hex color string. - * @access public - * @static - * @author Jason Lotito - * @see hex2rgb() - */ - function rgb2hex($color) - { - return sprintf('%02X%02X%02X',$color[0],$color[1],$color[2]); - } - - /** - * Convert a hex color string into an RGB array. An extra fourth element - * will be returned with the original hex value. - * - * @param string $hex Hex color string. - * @return array RGB color array with an extra 'hex' element containing - * the original hex string. - * @access public - * @static - * @author Jason Lotito - * @see rgb2hex() - */ - function hex2rgb($hex) - { - $return = Image_Color::_splitColor($hex); - $return['hex'] = $hex; - return $return; - } - - /** - * Convert an HSV (Hue, Saturation, Brightness) value to RGB. - * - * @param integer $h Hue - * @param integer $s Saturation - * @param integer $v Brightness - * @return array RGB array. - * @access public - * @static - * @author Jason Lotito - * @uses hsv2hex() to convert the HSV value to Hex. - * @uses hex2rgb() to convert the Hex value to RGB. - */ - function hsv2rgb($h, $s, $v) - { - return Image_Color::hex2rgb(Image_Color::hsv2hex($h, $s, $v)); - } - - /** - * Convert HSV (Hue, Saturation, Brightness) to a hex color string. - * - * Originally written by Jurgen Schwietering. Integrated into the class by - * Jason Lotito. - * - * @param integer $h Hue - * @param integer $s Saturation - * @param integer $v Brightness - * @return string The hex string. - * @access public - * @static - * @author Jurgen Schwietering - * @uses rgb2hex() to convert the return value to a hex string. - */ - function hsv2hex($h, $s, $v) - { - $s /= 256.0; - $v /= 256.0; - if ($s == 0.0) { - $r = $g = $b = $v; - return ''; - } else { - $h = $h / 256.0 * 6.0; - $i = floor($h); - $f = $h - $i; - - $v *= 256.0; - $p = (integer)($v * (1.0 - $s)); - $q = (integer)($v * (1.0 - $s * $f)); - $t = (integer)($v * (1.0 - $s * (1.0 - $f))); - switch($i) { - case 0: - $r = $v; - $g = $t; - $b = $p; - break; - - case 1: - $r = $q; - $g = $v; - $b = $p; - break; - - case 2: - $r = $p; - $g = $v; - $b = $t; - break; - - case 3: - $r = $p; - $g = $q; - $b = $v; - break; - - case 4: - $r = $t; - $g = $p; - $b = $v; - break; - - default: - $r = $v; - $g = $p; - $b = $q; - break; - } - } - return $this->rgb2hex(array($r, $g, $b)); - } - - /** - * Allocates a color in the given image. - * - * User defined color specifications get translated into an array of RGB - * values. - * - * @param resource $img Image handle - * @param string|array $color Name or hex string or an RGB array. - * @return resource Image color handle. - * @access public - * @static - * @uses ImageColorAllocate() to allocate the color. - * @uses color2RGB() to parse the color into RGB values. - */ - function allocateColor(&$img, $color) { - $color = Image_Color::color2RGB($color); - - return ImageColorAllocate($img, $color[0], $color[1], $color[2]); - } - - /** - * Convert a named or hex color string to an RGB array. If the color begins - * with the # character it will be treated as a hex value. Everything else - * will be treated as a named color. If the named color is not known, black - * will be returned. - * - * @param string $color - * @return array RGB color - * @access public - * @static - * @author Laurent Laville - * @uses hex2rgb() to convert colors begining with the # character. - * @uses namedColor2RGB() to convert everything not starting with a #. - */ - function color2RGB($color) - { - $c = array(); - - if ($color{0} == '#') { - $c = Image_Color::hex2rgb($color); - } else { - $c = Image_Color::namedColor2RGB($color); - } - - return $c; - } - - /** - * Convert a named color to an RGB array. If the color is unknown black - * is returned. - * - * @param string $color Case insensitive color name. - * @return array RGB color array. If the color was unknown, the result - * will be black. - * @access public - * @static - * @author Sebastian Bergmann - */ - function namedColor2RGB($color) - { - static $colornames; - - if (!isset($colornames)) { - $colornames = array( - 'aliceblue' => array(240, 248, 255), - 'antiquewhite' => array(250, 235, 215), - 'aqua' => array( 0, 255, 255), - 'aquamarine' => array(127, 255, 212), - 'azure' => array(240, 255, 255), - 'beige' => array(245, 245, 220), - 'bisque' => array(255, 228, 196), - 'black' => array( 0, 0, 0), - 'blanchedalmond' => array(255, 235, 205), - 'blue' => array( 0, 0, 255), - 'blueviolet' => array(138, 43, 226), - 'brown' => array(165, 42, 42), - 'burlywood' => array(222, 184, 135), - 'cadetblue' => array( 95, 158, 160), - 'chartreuse' => array(127, 255, 0), - 'chocolate' => array(210, 105, 30), - 'coral' => array(255, 127, 80), - 'cornflowerblue' => array(100, 149, 237), - 'cornsilk' => array(255, 248, 220), - 'crimson' => array(220, 20, 60), - 'cyan' => array( 0, 255, 255), - 'darkblue' => array( 0, 0, 13), - 'darkcyan' => array( 0, 139, 139), - 'darkgoldenrod' => array(184, 134, 11), - 'darkgray' => array(169, 169, 169), - 'darkgreen' => array( 0, 100, 0), - 'darkkhaki' => array(189, 183, 107), - 'darkmagenta' => array(139, 0, 139), - 'darkolivegreen' => array( 85, 107, 47), - 'darkorange' => array(255, 140, 0), - 'darkorchid' => array(153, 50, 204), - 'darkred' => array(139, 0, 0), - 'darksalmon' => array(233, 150, 122), - 'darkseagreen' => array(143, 188, 143), - 'darkslateblue' => array( 72, 61, 139), - 'darkslategray' => array( 47, 79, 79), - 'darkturquoise' => array( 0, 206, 209), - 'darkviolet' => array(148, 0, 211), - 'deeppink' => array(255, 20, 147), - 'deepskyblue' => array( 0, 191, 255), - 'dimgray' => array(105, 105, 105), - 'dodgerblue' => array( 30, 144, 255), - 'firebrick' => array(178, 34, 34), - 'floralwhite' => array(255, 250, 240), - 'forestgreen' => array( 34, 139, 34), - 'fuchsia' => array(255, 0, 255), - 'gainsboro' => array(220, 220, 220), - 'ghostwhite' => array(248, 248, 255), - 'gold' => array(255, 215, 0), - 'goldenrod' => array(218, 165, 32), - 'gray' => array(128, 128, 128), - 'green' => array( 0, 128, 0), - 'greenyellow' => array(173, 255, 47), - 'honeydew' => array(240, 255, 240), - 'hotpink' => array(255, 105, 180), - 'indianred' => array(205, 92, 92), - 'indigo' => array(75, 0, 130), - 'ivory' => array(255, 255, 240), - 'khaki' => array(240, 230, 140), - 'lavender' => array(230, 230, 250), - 'lavenderblush' => array(255, 240, 245), - 'lawngreen' => array(124, 252, 0), - 'lemonchiffon' => array(255, 250, 205), - 'lightblue' => array(173, 216, 230), - 'lightcoral' => array(240, 128, 128), - 'lightcyan' => array(224, 255, 255), - 'lightgoldenrodyellow' => array(250, 250, 210), - 'lightgreen' => array(144, 238, 144), - 'lightgrey' => array(211, 211, 211), - 'lightpink' => array(255, 182, 193), - 'lightsalmon' => array(255, 160, 122), - 'lightseagreen' => array( 32, 178, 170), - 'lightskyblue' => array(135, 206, 250), - 'lightslategray' => array(119, 136, 153), - 'lightsteelblue' => array(176, 196, 222), - 'lightyellow' => array(255, 255, 224), - 'lime' => array( 0, 255, 0), - 'limegreen' => array( 50, 205, 50), - 'linen' => array(250, 240, 230), - 'magenta' => array(255, 0, 255), - 'maroon' => array(128, 0, 0), - 'mediumaquamarine' => array(102, 205, 170), - 'mediumblue' => array( 0, 0, 205), - 'mediumorchid' => array(186, 85, 211), - 'mediumpurple' => array(147, 112, 219), - 'mediumseagreen' => array( 60, 179, 113), - 'mediumslateblue' => array(123, 104, 238), - 'mediumspringgreen' => array( 0, 250, 154), - 'mediumturquoise' => array(72, 209, 204), - 'mediumvioletred' => array(199, 21, 133), - 'midnightblue' => array( 25, 25, 112), - 'mintcream' => array(245, 255, 250), - 'mistyrose' => array(255, 228, 225), - 'moccasin' => array(255, 228, 181), - 'navajowhite' => array(255, 222, 173), - 'navy' => array( 0, 0, 128), - 'oldlace' => array(253, 245, 230), - 'olive' => array(128, 128, 0), - 'olivedrab' => array(107, 142, 35), - 'orange' => array(255, 165, 0), - 'orangered' => array(255, 69, 0), - 'orchid' => array(218, 112, 214), - 'palegoldenrod' => array(238, 232, 170), - 'palegreen' => array(152, 251, 152), - 'paleturquoise' => array(175, 238, 238), - 'palevioletred' => array(219, 112, 147), - 'papayawhip' => array(255, 239, 213), - 'peachpuff' => array(255, 218, 185), - 'peru' => array(205, 133, 63), - 'pink' => array(255, 192, 203), - 'plum' => array(221, 160, 221), - 'powderblue' => array(176, 224, 230), - 'purple' => array(128, 0, 128), - 'red' => array(255, 0, 0), - 'rosybrown' => array(188, 143, 143), - 'royalblue' => array( 65, 105, 225), - 'saddlebrown' => array(139, 69, 19), - 'salmon' => array(250, 128, 114), - 'sandybrown' => array(244, 164, 96), - 'seagreen' => array( 46, 139, 87), - 'seashell' => array(255, 245, 238), - 'sienna' => array(160, 82, 45), - 'silver' => array(192, 192, 192), - 'skyblue' => array(135, 206, 235), - 'slateblue' => array(106, 90, 205), - 'slategray' => array(112, 128, 144), - 'snow' => array(255, 250, 250), - 'springgreen' => array( 0, 255, 127), - 'steelblue' => array( 70, 130, 180), - 'tan' => array(210, 180, 140), - 'teal' => array( 0, 128, 128), - 'thistle' => array(216, 191, 216), - 'tomato' => array(255, 99, 71), - 'turquoise' => array( 64, 224, 208), - 'violet' => array(238, 130, 238), - 'wheat' => array(245, 222, 179), - 'white' => array(255, 255, 255), - 'whitesmoke' => array(245, 245, 245), - 'yellow' => array(255, 255, 0), - 'yellowgreen' => array(154, 205, 50) - ); - } - - $color = strtolower($color); - - if (isset($colornames[$color])) { - return $colornames[$color]; - } else { - return array(0, 0, 0); - } - } - - /** - * Convert an RGB percentage string into an RGB array. - * - * @param string $color Percentage color string like "50%,20%,100%". - * @return array RGB color array. - * @access public - * @static - */ - function percentageColor2RGB($color) - { - // remove spaces - $color = str_replace(' ', '', $color); - // remove the percent signs - $color = str_replace('%', '', $color); - // split the string by commas - $color = explode(',', $color); - - $ret = array(); - foreach ($color as $k => $v) { - // range checks - if ($v <= 0) { - $ret[$k] = 0; - } else if ($v <= 100) { - // add 0.5 then cast to an integer to round the value. - $ret[$k] = (integer) ((2.55 * $v) + 0.5); - } else { - $ret[$k] = 255; - } - } - - return $ret; - } -} - -// For Array Walk -// {{{ -/** - * Function for array_walk() to round colors to the closest web safe value. - * - * @param integer $color One channel of an RGB color. - * @return integer The websafe equivalent of the color channel. - * @author Jason Lotito - * @author Andrew Morton - * @access private - * @static - */ -function _makeWebSafe(&$color) -{ - if ($color < 0x1a) { - $color = 0x00; - } else if ($color < 0x4d) { - $color = 0x33; - } else if ($color < 0x80) { - $color = 0x66; - } else if ($color < 0xB3) { - $color = 0x99; - } else if ($color < 0xE6) { - $color = 0xCC; - } else { - $color = 0xFF; - } - return $color; -} -// }}} - -?> + + * @author Andrew Morton + * @copyright 2003-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Color.php,v 1.15 2005/09/12 19:12:02 drewish Exp $ + * @link http://pear.php.net/package/Image_Color + */ + +/** + * Image_Color handles color conversion and mixing. + * + * The class is quick, simple to use, and does its job fairly well but it's got + * some code smells: + * - Call setColors() for some functions but not others. + * - Different functions expect different color formats. setColors() only + * accepts hex while allocateColor() will accept named or hex (provided the + * hex ones start with the # character). + * - Some conversions go in only one direction, ie HSV->RGB but no RGB->HSV. + * I'm going to try to straighten out some of this but I'll be hard to do so + * without breaking backwards compatibility. + * + * @category Image + * @package Image_Color + * @author Jason Lotito + * @author Andrew Morton + * @copyright 2003-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 0.1.2 + * @link http://pear.php.net/package/Image_Color + */ +class Image_Color +{ + /** + * First color that the class handles for ranges and mixes. + * @var array + * @access public + * @see setColors() + */ + var $color1 = array(); + + /** + * Second color that the class handles for ranges and mixes. + * @var array + * @access public + * @see setColors() + */ + var $color2 = array(); + + /** + * Boolean value for determining whether colors outputted should be limited + * to the web safe pallet or not. + * + * @var boolean + * @access private + * @see setWebSafe() + */ + var $_websafeb = false; + + /** + * Mix two colors together by finding their average. If the colors are not + * passed as parameters, the class's colors will be mixed instead. + * + * @param string $col1 The first color you want to mix + * @param string $col2 The second color you want to mix + * @return string The mixed color. + * @access public + * @author Jason Lotito + * @uses _setColors() to assign the colors if any are passed to the + * class. + */ + function mixColors($col1 = false, $col2 = false) + { + if ($col1) { + $this->_setColors($col1, $col2); + } + + // after finding the average, it will be a float. add 0.5 and then + // cast to an integer to properly round it to an integer. + $color3[0] = (int) ((($this->color1[0] + $this->color2[0]) / 2) + 0.5); + $color3[1] = (int) ((($this->color1[1] + $this->color2[1]) / 2) + 0.5); + $color3[2] = (int) ((($this->color1[2] + $this->color2[2]) / 2) + 0.5); + + if ($this->_websafeb) { + array_walk($color3, '_makeWebSafe'); + } + + return Image_Color::rgb2hex($color3); + } + + /** + * Determines whether colors the returned by this class will be rounded to + * the nearest web safe value. + * + * @param boolean $bool Indicates if colors should be limited to the + * websafe pallet. + * @return void + * @access public + * @author Jason Lotito + */ + function setWebSafe($bool = true) + { + $this->_websafeb = (boolean) $bool; + } + + /** + * Set the two colors this class uses for mixing and ranges. + * + * @param string $col1 The first color in hex format + * @param string $col2 The second color in hex format + * @return void + * @access public + * @author Jason Lotito + */ + function setColors($col1, $col2) + { + $this->_setColors($col1, $col2); + } + + /** + * Get the range of colors between the class's two colors, given a degree. + * + * @param integer $degrees How large a 'step' we should take between the + * colors. + * @return array Returns an array of hex strings, one element for each + * color. + * @access public + * @author Jason Lotito + * @todo Allow for degrees for individual parts of the colors. + */ + function getRange($degrees = 2) + { + if ($degrees == 0) { + $degrees = 1; + } + + // The degrees give us how much we should advance each color at each + // phase of the loop. This way, the advance is equal throughout all + // the colors. + + $red_steps = ($this->color2[0] - $this->color1[0]) / $degrees; + $green_steps = ($this->color2[1] - $this->color1[1]) / $degrees; + $blue_steps = ($this->color2[2] - $this->color1[2]) / $degrees; + + $allcolors = array(); + + /** + * The loop stops once any color has gone beyond the end color. + */ + + // Loop through all the degrees between the colors + for ($x = 0; $x < $degrees; $x++) { + $col[0] = $red_steps * $x; + $col[1] = $green_steps * $x; + $col[2] = $blue_steps * $x; + + // Loop through each R, G, and B + for ($i = 0; $i < 3; $i++) { + $partcolor = $this->color1[$i] + $col[$i]; + // If the color is less than 256 + if ($partcolor < 256) { + // Makes sure the colors is not less than 0 + if ($partcolor > -1) { + $newcolor[$i] = $partcolor; + } else { + $newcolor[$i] = 0; + } + // Color was greater than 255 + } else { + $newcolor[$i] = 255; + } + } + + if ($this->_websafeb) { + array_walk($newcolor, '_makeWebSafe'); + } + + $allcolors[] = Image_Color::rgb2hex($newcolor); + } + + return $allcolors; + } + + /** + * Change the lightness of the class's two colors. + * + * @param integer $degree The degree of the change. Positive values + * lighten the color while negative values will darken it. + * @return void + * @access public + * @author Jason Lotito + * @uses Image_Color::$color1 as an input and return value. + * @uses Image_Color::$color2 as an input and return value. + */ + function changeLightness($degree = 10) + { + $color1 =& $this->color1; + $color2 =& $this->color2; + + for ($x = 0; $x < 3; $x++) { + if (($color1[$x] + $degree) < 256) { + if (($color1[$x] + $degree) > -1) { + $color1[$x] += $degree; + } else { + $color1[$x] = 0; + } + } else { + $color1[$x] = 255; + } + + if (($color2[$x] + $degree) < 256) { + if (($color2[$x] + $degree) > -1) { + $color2[$x] += $degree; + } else { + $color2[$x] = 0; + } + } else { + $color2[$x] = 255; + } + } + } + + /** + * Determine if a light or dark text color would be more readable on a + * background of a given color. This is determined by the G(reen) value of + * RGB. You can change the dark and the light colors from their default + * black and white. + * + * @param string $color The hex color to analyze + * @param string $light The light color value to return if we should + * have light text. + * @param string $dark The dark color value to return if we should have + * dark text. + * @return string The light or dark value which would make the text most + * readable. + * @access public + * @static + * @author Jason Lotito + */ + function getTextColor($color, $light = '#FFFFFF', $dark = '#000000') + { + $color = Image_Color::_splitColor($color); + if ($color[1] > hexdec('66')) { + return $dark; + } else { + return $light; + } + } + + + /** + * Internal method to set the colors. + * + * @param string $col1 First color, either a name or hex value + * @param string $col2 Second color, either a name or hex value + * @return void + * @access private + * @author Jason Lotito + */ + function _setColors($col1, $col2) + { + if ($col1) { + $this->color1 = Image_Color::_splitColor($col1); + } + if ($col2) { + $this->color2 = Image_Color::_splitColor($col2); + } + } + + /** + * Given a color, properly split it up into a 3 element RGB array. + * + * @param string $color The color. + * @return array A three element RGB array. + * @access private + * @static + * @author Jason Lotito + */ + function _splitColor($color) + { + $color = str_replace('#', '', $color); + $c[] = hexdec(substr($color, 0, 2)); + $c[] = hexdec(substr($color, 2, 2)); + $c[] = hexdec(substr($color, 4, 2)); + return $c; + } + + /** + * This is deprecated. Use rgb2hex() instead. + * @access private + * @deprecated Function deprecated after 1.0.1 + * @see rgb2hex(). + */ + function _returnColor ( $color ) + { + return Image_Color::rgb2hex($color); + } + + /** + * Convert an RGB array to a hex string. + * + * @param array $color 3 element RGB array. + * @return string Hex color string. + * @access public + * @static + * @author Jason Lotito + * @see hex2rgb() + */ + function rgb2hex($color) + { + return sprintf('%02X%02X%02X',$color[0],$color[1],$color[2]); + } + + /** + * Convert a hex color string into an RGB array. An extra fourth element + * will be returned with the original hex value. + * + * @param string $hex Hex color string. + * @return array RGB color array with an extra 'hex' element containing + * the original hex string. + * @access public + * @static + * @author Jason Lotito + * @see rgb2hex() + */ + function hex2rgb($hex) + { + $return = Image_Color::_splitColor($hex); + $return['hex'] = $hex; + return $return; + } + + /** + * Convert an HSV (Hue, Saturation, Brightness) value to RGB. + * + * @param integer $h Hue + * @param integer $s Saturation + * @param integer $v Brightness + * @return array RGB array. + * @access public + * @static + * @author Jason Lotito + * @uses hsv2hex() to convert the HSV value to Hex. + * @uses hex2rgb() to convert the Hex value to RGB. + */ + function hsv2rgb($h, $s, $v) + { + return Image_Color::hex2rgb(Image_Color::hsv2hex($h, $s, $v)); + } + + /** + * Convert HSV (Hue, Saturation, Brightness) to a hex color string. + * + * Originally written by Jurgen Schwietering. Integrated into the class by + * Jason Lotito. + * + * @param integer $h Hue + * @param integer $s Saturation + * @param integer $v Brightness + * @return string The hex string. + * @access public + * @static + * @author Jurgen Schwietering + * @uses rgb2hex() to convert the return value to a hex string. + */ + function hsv2hex($h, $s, $v) + { + $s /= 256.0; + $v /= 256.0; + if ($s == 0.0) { + $r = $g = $b = $v; + return ''; + } else { + $h = $h / 256.0 * 6.0; + $i = floor($h); + $f = $h - $i; + + $v *= 256.0; + $p = (integer)($v * (1.0 - $s)); + $q = (integer)($v * (1.0 - $s * $f)); + $t = (integer)($v * (1.0 - $s * (1.0 - $f))); + switch($i) { + case 0: + $r = $v; + $g = $t; + $b = $p; + break; + + case 1: + $r = $q; + $g = $v; + $b = $p; + break; + + case 2: + $r = $p; + $g = $v; + $b = $t; + break; + + case 3: + $r = $p; + $g = $q; + $b = $v; + break; + + case 4: + $r = $t; + $g = $p; + $b = $v; + break; + + default: + $r = $v; + $g = $p; + $b = $q; + break; + } + } + return $this->rgb2hex(array($r, $g, $b)); + } + + /** + * Allocates a color in the given image. + * + * User defined color specifications get translated into an array of RGB + * values. + * + * @param resource $img Image handle + * @param string|array $color Name or hex string or an RGB array. + * @return resource Image color handle. + * @access public + * @static + * @uses ImageColorAllocate() to allocate the color. + * @uses color2RGB() to parse the color into RGB values. + */ + function allocateColor(&$img, $color) { + $color = Image_Color::color2RGB($color); + + return ImageColorAllocate($img, $color[0], $color[1], $color[2]); + } + + /** + * Convert a named or hex color string to an RGB array. If the color begins + * with the # character it will be treated as a hex value. Everything else + * will be treated as a named color. If the named color is not known, black + * will be returned. + * + * @param string $color + * @return array RGB color + * @access public + * @static + * @author Laurent Laville + * @uses hex2rgb() to convert colors begining with the # character. + * @uses namedColor2RGB() to convert everything not starting with a #. + */ + function color2RGB($color) + { + $c = array(); + + if ($color{0} == '#') { + $c = Image_Color::hex2rgb($color); + } else { + $c = Image_Color::namedColor2RGB($color); + } + + return $c; + } + + /** + * Convert a named color to an RGB array. If the color is unknown black + * is returned. + * + * @param string $color Case insensitive color name. + * @return array RGB color array. If the color was unknown, the result + * will be black. + * @access public + * @static + * @author Sebastian Bergmann + */ + function namedColor2RGB($color) + { + static $colornames; + + if (!isset($colornames)) { + $colornames = array( + 'aliceblue' => array(240, 248, 255), + 'antiquewhite' => array(250, 235, 215), + 'aqua' => array( 0, 255, 255), + 'aquamarine' => array(127, 255, 212), + 'azure' => array(240, 255, 255), + 'beige' => array(245, 245, 220), + 'bisque' => array(255, 228, 196), + 'black' => array( 0, 0, 0), + 'blanchedalmond' => array(255, 235, 205), + 'blue' => array( 0, 0, 255), + 'blueviolet' => array(138, 43, 226), + 'brown' => array(165, 42, 42), + 'burlywood' => array(222, 184, 135), + 'cadetblue' => array( 95, 158, 160), + 'chartreuse' => array(127, 255, 0), + 'chocolate' => array(210, 105, 30), + 'coral' => array(255, 127, 80), + 'cornflowerblue' => array(100, 149, 237), + 'cornsilk' => array(255, 248, 220), + 'crimson' => array(220, 20, 60), + 'cyan' => array( 0, 255, 255), + 'darkblue' => array( 0, 0, 13), + 'darkcyan' => array( 0, 139, 139), + 'darkgoldenrod' => array(184, 134, 11), + 'darkgray' => array(169, 169, 169), + 'darkgreen' => array( 0, 100, 0), + 'darkkhaki' => array(189, 183, 107), + 'darkmagenta' => array(139, 0, 139), + 'darkolivegreen' => array( 85, 107, 47), + 'darkorange' => array(255, 140, 0), + 'darkorchid' => array(153, 50, 204), + 'darkred' => array(139, 0, 0), + 'darksalmon' => array(233, 150, 122), + 'darkseagreen' => array(143, 188, 143), + 'darkslateblue' => array( 72, 61, 139), + 'darkslategray' => array( 47, 79, 79), + 'darkturquoise' => array( 0, 206, 209), + 'darkviolet' => array(148, 0, 211), + 'deeppink' => array(255, 20, 147), + 'deepskyblue' => array( 0, 191, 255), + 'dimgray' => array(105, 105, 105), + 'dodgerblue' => array( 30, 144, 255), + 'firebrick' => array(178, 34, 34), + 'floralwhite' => array(255, 250, 240), + 'forestgreen' => array( 34, 139, 34), + 'fuchsia' => array(255, 0, 255), + 'gainsboro' => array(220, 220, 220), + 'ghostwhite' => array(248, 248, 255), + 'gold' => array(255, 215, 0), + 'goldenrod' => array(218, 165, 32), + 'gray' => array(128, 128, 128), + 'green' => array( 0, 128, 0), + 'greenyellow' => array(173, 255, 47), + 'honeydew' => array(240, 255, 240), + 'hotpink' => array(255, 105, 180), + 'indianred' => array(205, 92, 92), + 'indigo' => array(75, 0, 130), + 'ivory' => array(255, 255, 240), + 'khaki' => array(240, 230, 140), + 'lavender' => array(230, 230, 250), + 'lavenderblush' => array(255, 240, 245), + 'lawngreen' => array(124, 252, 0), + 'lemonchiffon' => array(255, 250, 205), + 'lightblue' => array(173, 216, 230), + 'lightcoral' => array(240, 128, 128), + 'lightcyan' => array(224, 255, 255), + 'lightgoldenrodyellow' => array(250, 250, 210), + 'lightgreen' => array(144, 238, 144), + 'lightgrey' => array(211, 211, 211), + 'lightpink' => array(255, 182, 193), + 'lightsalmon' => array(255, 160, 122), + 'lightseagreen' => array( 32, 178, 170), + 'lightskyblue' => array(135, 206, 250), + 'lightslategray' => array(119, 136, 153), + 'lightsteelblue' => array(176, 196, 222), + 'lightyellow' => array(255, 255, 224), + 'lime' => array( 0, 255, 0), + 'limegreen' => array( 50, 205, 50), + 'linen' => array(250, 240, 230), + 'magenta' => array(255, 0, 255), + 'maroon' => array(128, 0, 0), + 'mediumaquamarine' => array(102, 205, 170), + 'mediumblue' => array( 0, 0, 205), + 'mediumorchid' => array(186, 85, 211), + 'mediumpurple' => array(147, 112, 219), + 'mediumseagreen' => array( 60, 179, 113), + 'mediumslateblue' => array(123, 104, 238), + 'mediumspringgreen' => array( 0, 250, 154), + 'mediumturquoise' => array(72, 209, 204), + 'mediumvioletred' => array(199, 21, 133), + 'midnightblue' => array( 25, 25, 112), + 'mintcream' => array(245, 255, 250), + 'mistyrose' => array(255, 228, 225), + 'moccasin' => array(255, 228, 181), + 'navajowhite' => array(255, 222, 173), + 'navy' => array( 0, 0, 128), + 'oldlace' => array(253, 245, 230), + 'olive' => array(128, 128, 0), + 'olivedrab' => array(107, 142, 35), + 'orange' => array(255, 165, 0), + 'orangered' => array(255, 69, 0), + 'orchid' => array(218, 112, 214), + 'palegoldenrod' => array(238, 232, 170), + 'palegreen' => array(152, 251, 152), + 'paleturquoise' => array(175, 238, 238), + 'palevioletred' => array(219, 112, 147), + 'papayawhip' => array(255, 239, 213), + 'peachpuff' => array(255, 218, 185), + 'peru' => array(205, 133, 63), + 'pink' => array(255, 192, 203), + 'plum' => array(221, 160, 221), + 'powderblue' => array(176, 224, 230), + 'purple' => array(128, 0, 128), + 'red' => array(255, 0, 0), + 'rosybrown' => array(188, 143, 143), + 'royalblue' => array( 65, 105, 225), + 'saddlebrown' => array(139, 69, 19), + 'salmon' => array(250, 128, 114), + 'sandybrown' => array(244, 164, 96), + 'seagreen' => array( 46, 139, 87), + 'seashell' => array(255, 245, 238), + 'sienna' => array(160, 82, 45), + 'silver' => array(192, 192, 192), + 'skyblue' => array(135, 206, 235), + 'slateblue' => array(106, 90, 205), + 'slategray' => array(112, 128, 144), + 'snow' => array(255, 250, 250), + 'springgreen' => array( 0, 255, 127), + 'steelblue' => array( 70, 130, 180), + 'tan' => array(210, 180, 140), + 'teal' => array( 0, 128, 128), + 'thistle' => array(216, 191, 216), + 'tomato' => array(255, 99, 71), + 'turquoise' => array( 64, 224, 208), + 'violet' => array(238, 130, 238), + 'wheat' => array(245, 222, 179), + 'white' => array(255, 255, 255), + 'whitesmoke' => array(245, 245, 245), + 'yellow' => array(255, 255, 0), + 'yellowgreen' => array(154, 205, 50) + ); + } + + $color = strtolower($color); + + if (isset($colornames[$color])) { + return $colornames[$color]; + } else { + return array(0, 0, 0); + } + } + + /** + * Convert an RGB percentage string into an RGB array. + * + * @param string $color Percentage color string like "50%,20%,100%". + * @return array RGB color array. + * @access public + * @static + */ + function percentageColor2RGB($color) + { + // remove spaces + $color = str_replace(' ', '', $color); + // remove the percent signs + $color = str_replace('%', '', $color); + // split the string by commas + $color = explode(',', $color); + + $ret = array(); + foreach ($color as $k => $v) { + // range checks + if ($v <= 0) { + $ret[$k] = 0; + } else if ($v <= 100) { + // add 0.5 then cast to an integer to round the value. + $ret[$k] = (integer) ((2.55 * $v) + 0.5); + } else { + $ret[$k] = 255; + } + } + + return $ret; + } +} + +// For Array Walk +// {{{ +/** + * Function for array_walk() to round colors to the closest web safe value. + * + * @param integer $color One channel of an RGB color. + * @return integer The websafe equivalent of the color channel. + * @author Jason Lotito + * @author Andrew Morton + * @access private + * @static + */ +function _makeWebSafe(&$color) +{ + if ($color < 0x1a) { + $color = 0x00; + } else if ($color < 0x4d) { + $color = 0x33; + } else if ($color < 0x80) { + $color = 0x66; + } else if ($color < 0xB3) { + $color = 0x99; + } else if ($color < 0xE6) { + $color = 0xCC; + } else { + $color = 0xFF; + } + return $color; +} +// }}} + +?> diff --git a/pandora_console/reporting/Image/Graph.php b/pandora_console/reporting/Image/Graph.php index 90e4bec8f3..13e3a62f48 100644 --- a/pandora_console/reporting/Image/Graph.php +++ b/pandora_console/reporting/Image/Graph.php @@ -1,851 +1,851 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Graph.php,v 1.58 2005/11/27 18:48:05 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - - -/** - * Include PEAR.php - */ -require_once 'PEAR.php'; - -/** - * 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. - * - * @category Images - * @package Image_Graph - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: 0.7.2 - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph extends Image_Graph_Element -{ - - /** - * Show generation time on graph - * @var bool - * @access private - */ - var $_showTime = false; - - /** - * Display errors on the canvas - * @var boolean - * @access private - */ - var $_displayErrors = false; - - /** - * Image_Graph [Constructor]. - * - * If passing the 3 parameters they are defined as follows:' - * - * Fx.: - * - * $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:: - * factory()}) - * - * 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) - { - parent::Image_Graph_Element(); - - $this->setFont(Image_Graph::factory('Image_Graph_Font')); - - if (defined('IMAGE_GRAPH_DEFAULT_CANVAS_TYPE')) { - $canvasType = IMAGE_GRAPH_DEFAULT_CANVAS_TYPE; - } else { - $canvasType = 'png'; // use GD as default, if nothing else is specified - } - - if (is_array($params)) { - if (isset($params['canvas'])) { - $canvasType = $params['canvas']; - } - - $width = 0; - $height = 0; - - 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(); - } elseif (is_numeric($params)) { - $width = $params; - } - - if ($this->_canvas == null) { - include_once 'Image/Canvas.php'; - $this->_canvas =& - Image_Canvas::factory( - $canvasType, - 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()} - * method. - * - * @return Image_Canvas The canvas used by this graph - * @access private - * @since 0.3.0dev2 - */ - function &_getCanvas() - { - return $this->_canvas; - } - - /** - * 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 - * @since 0.3.0dev2 - */ - function &setCanvas(&$canvas) - { - if (!is_a($this->_canvas, 'Image_Canvas')) { - return $this->_error('The canvas introduced is not an Image_Canvas object'); - } - - $this->_canvas =& $canvas; - $this->_setCoords( - 0, - 0, - $this->_canvas->getWidth() - 1, - $this->_canvas->getHeight() - 1 - ); - return $this->_canvas; - } - - /** - * Gets a very precise timestamp - * - * @return The number of seconds to a lot of decimals - * @access private - */ - function _getMicroTime() - { - list($usec, $sec) = explode(' ', microtime()); - 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 - */ - function width() - { - 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 - */ - function height() - { - 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()}. - */ - function displayErrors() - { - $this->_displayErrors = true; - set_error_handler(array(&$this, '_default_error_handler')); - } - - /** - * 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 - * @since 0.3.0dev2 - */ - function setLog($log) - { - } - - /** - * 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); - * - * or - * - * Image_graph::factory('bar', array(array(&$Dataset1, &$Dataset2), - * 'stacked')); - * - * Class name can be either of the following: - * - * 1 The 'real' Image_Graph class name, i.e. Image_Graph_Plotarea or - * Image_Graph_Plot_Line - * - * 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: - * - * 'graph' = Image_Graph - * - * '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 - * @static - */ - 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]; - } else { - $class = 'Image_Graph_' . $class; - } - } - - include_once str_replace('_', '/', $class) . '.php'; - - $obj = null; - - if (is_array($params)) { - switch (count($params)) { - case 1: - $obj =& new $class( - $params[0] - ); - break; - - case 2: - $obj =& new $class( - $params[0], - $params[1] - ); - break; - - case 3: - $obj =& new $class( - $params[0], - $params[1], - $params[2] - ); - break; - - case 4: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3] - ); - break; - - case 5: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4] - ); - break; - - case 6: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5] - ); - break; - - case 7: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5], - $params[6] - ); - break; - - case 8: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5], - $params[6], - $params[7] - ); - break; - - case 9: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5], - $params[6], - $params[7], - $params[8] - ); - break; - - case 10: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5], - $params[6], - $params[7], - $params[8], - $params[9] - ); - break; - - default: - $obj =& new $class(); - break; - - } - } else { - if ($params == null) { - $obj =& new $class(); - } else { - $obj =& new $class($params); - } - } - return $obj; - } - - /** - * 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 - * @static - */ - 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); - return $obj; - } - - /** - * 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 - * @static - */ - function &horizontal(&$part1, &$part2, $percentage = 50) - { - $obj =& Image_Graph::layoutFactory('Horizontal', $part1, $part2, $percentage); - return $obj; - } - - /** - * 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 - * @static - */ - function &vertical(&$part1, &$part2, $percentage = 50) - { - $obj =& Image_Graph::layoutFactory('Vertical', $part1, $part2, $percentage); - return $obj; - } - - /** - * 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. - * @access private - */ - function _default_error_handler($error_type, $error_msg, $error_file, $error_line, $error_context) - { - switch( $error_type ) { - case E_ERROR: - $level = 'error'; - break; - - case E_USER_ERROR: - $level = 'user error'; - break; - - case E_WARNING: - $level = 'warning'; - break; - - case E_USER_WARNING: - $level = 'user warning'; - break; - - case E_NOTICE: - $level = 'notice'; - break; - - case E_USER_NOTICE: - $level = 'user notice'; - break; - - default: - $level = '(unknown)'; - break; - - } - - $this->_error("PHP $level: $error_msg", - array( - 'type' => $error_type, - 'file' => $error_file, - 'line' => $error_line, - '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()} - * method. - * - * @access private - */ - function _displayErrors() - { - return true; - } - - /** - * 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 - * - * @access private - */ - 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 - * supported by it). - * - * 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 - * urlpath + filename) - * - * @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 $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 - * supported by it). - * - * @param mixed $param The output parameters to pass to the canvas - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done($param = false) - { - $timeStart = $this->_getMicroTime(); - - if ($this->_shadow) { - $this->setPadding(20); - $this->_setCoords( - $this->_left, - $this->_top, - $this->_right - 10, - $this->_bottom - 10); - } - - $result = $this->_updateCoords(); - if (PEAR::isError($result)) { - return $result; - } - - if ($this->_getBackground()) { - $this->_canvas->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_right, - 'y1' => $this->_bottom - ) - ); - } - - $result = parent::_done(); - if (PEAR::isError($result)) { - return $result; - } - - if ($this->_displayErrors) { - $this->_displayErrors(); - } - - $timeEnd = $this->_getMicroTime(); - - if (($this->_showTime) || - ((isset($param['showtime'])) && ($param['showtime'] === true)) - ) { - $text = 'Generated in ' . - sprintf('%0.3f', $timeEnd - $timeStart) . ' sec'; - $this->write( - $this->_right, - $this->_bottom, - $text, - IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_BOTTOM, - array('color' => 'red') - ); - } - - if (isset($param['filename'])) { - if ((isset($param['tohtml'])) && ($param['tohtml'])) { - return $this->_canvas->toHtml($param); - } - else { - return $this->_canvas->save($param); - } - } else { - return $this->_canvas->show($param); - } - } -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Graph.php,v 1.58 2005/11/27 18:48:05 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + + +/** + * Include PEAR.php + */ +require_once 'PEAR.php'; + +/** + * 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. + * + * @category Images + * @package Image_Graph + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: 0.7.2 + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph extends Image_Graph_Element +{ + + /** + * Show generation time on graph + * @var bool + * @access private + */ + var $_showTime = false; + + /** + * Display errors on the canvas + * @var boolean + * @access private + */ + var $_displayErrors = false; + + /** + * Image_Graph [Constructor]. + * + * If passing the 3 parameters they are defined as follows:' + * + * Fx.: + * + * $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:: + * factory()}) + * + * 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) + { + parent::Image_Graph_Element(); + + $this->setFont(Image_Graph::factory('Image_Graph_Font')); + + if (defined('IMAGE_GRAPH_DEFAULT_CANVAS_TYPE')) { + $canvasType = IMAGE_GRAPH_DEFAULT_CANVAS_TYPE; + } else { + $canvasType = 'png'; // use GD as default, if nothing else is specified + } + + if (is_array($params)) { + if (isset($params['canvas'])) { + $canvasType = $params['canvas']; + } + + $width = 0; + $height = 0; + + 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(); + } elseif (is_numeric($params)) { + $width = $params; + } + + if ($this->_canvas == null) { + include_once 'Image/Canvas.php'; + $this->_canvas =& + Image_Canvas::factory( + $canvasType, + 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()} + * method. + * + * @return Image_Canvas The canvas used by this graph + * @access private + * @since 0.3.0dev2 + */ + function &_getCanvas() + { + return $this->_canvas; + } + + /** + * 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 + * @since 0.3.0dev2 + */ + function &setCanvas(&$canvas) + { + if (!is_a($this->_canvas, 'Image_Canvas')) { + return $this->_error('The canvas introduced is not an Image_Canvas object'); + } + + $this->_canvas =& $canvas; + $this->_setCoords( + 0, + 0, + $this->_canvas->getWidth() - 1, + $this->_canvas->getHeight() - 1 + ); + return $this->_canvas; + } + + /** + * Gets a very precise timestamp + * + * @return The number of seconds to a lot of decimals + * @access private + */ + function _getMicroTime() + { + list($usec, $sec) = explode(' ', microtime()); + 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 + */ + function width() + { + 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 + */ + function height() + { + 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()}. + */ + function displayErrors() + { + $this->_displayErrors = true; + set_error_handler(array(&$this, '_default_error_handler')); + } + + /** + * 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 + * @since 0.3.0dev2 + */ + function setLog($log) + { + } + + /** + * 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); + * + * or + * + * Image_graph::factory('bar', array(array(&$Dataset1, &$Dataset2), + * 'stacked')); + * + * Class name can be either of the following: + * + * 1 The 'real' Image_Graph class name, i.e. Image_Graph_Plotarea or + * Image_Graph_Plot_Line + * + * 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: + * + * 'graph' = Image_Graph + * + * '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 + * @static + */ + 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]; + } else { + $class = 'Image_Graph_' . $class; + } + } + + include_once str_replace('_', '/', $class) . '.php'; + + $obj = null; + + if (is_array($params)) { + switch (count($params)) { + case 1: + $obj =& new $class( + $params[0] + ); + break; + + case 2: + $obj =& new $class( + $params[0], + $params[1] + ); + break; + + case 3: + $obj =& new $class( + $params[0], + $params[1], + $params[2] + ); + break; + + case 4: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3] + ); + break; + + case 5: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4] + ); + break; + + case 6: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5] + ); + break; + + case 7: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5], + $params[6] + ); + break; + + case 8: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5], + $params[6], + $params[7] + ); + break; + + case 9: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5], + $params[6], + $params[7], + $params[8] + ); + break; + + case 10: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5], + $params[6], + $params[7], + $params[8], + $params[9] + ); + break; + + default: + $obj =& new $class(); + break; + + } + } else { + if ($params == null) { + $obj =& new $class(); + } else { + $obj =& new $class($params); + } + } + return $obj; + } + + /** + * 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 + * @static + */ + 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); + return $obj; + } + + /** + * 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 + * @static + */ + function &horizontal(&$part1, &$part2, $percentage = 50) + { + $obj =& Image_Graph::layoutFactory('Horizontal', $part1, $part2, $percentage); + return $obj; + } + + /** + * 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 + * @static + */ + function &vertical(&$part1, &$part2, $percentage = 50) + { + $obj =& Image_Graph::layoutFactory('Vertical', $part1, $part2, $percentage); + return $obj; + } + + /** + * 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. + * @access private + */ + function _default_error_handler($error_type, $error_msg, $error_file, $error_line, $error_context) + { + switch( $error_type ) { + case E_ERROR: + $level = 'error'; + break; + + case E_USER_ERROR: + $level = 'user error'; + break; + + case E_WARNING: + $level = 'warning'; + break; + + case E_USER_WARNING: + $level = 'user warning'; + break; + + case E_NOTICE: + $level = 'notice'; + break; + + case E_USER_NOTICE: + $level = 'user notice'; + break; + + default: + $level = '(unknown)'; + break; + + } + + $this->_error("PHP $level: $error_msg", + array( + 'type' => $error_type, + 'file' => $error_file, + 'line' => $error_line, + '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()} + * method. + * + * @access private + */ + function _displayErrors() + { + return true; + } + + /** + * 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 + * + * @access private + */ + 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 + * supported by it). + * + * 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 + * urlpath + filename) + * + * @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 $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 + * supported by it). + * + * @param mixed $param The output parameters to pass to the canvas + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done($param = false) + { + $timeStart = $this->_getMicroTime(); + + if ($this->_shadow) { + $this->setPadding(20); + $this->_setCoords( + $this->_left, + $this->_top, + $this->_right - 10, + $this->_bottom - 10); + } + + $result = $this->_updateCoords(); + if (PEAR::isError($result)) { + return $result; + } + + if ($this->_getBackground()) { + $this->_canvas->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ) + ); + } + + $result = parent::_done(); + if (PEAR::isError($result)) { + return $result; + } + + if ($this->_displayErrors) { + $this->_displayErrors(); + } + + $timeEnd = $this->_getMicroTime(); + + if (($this->_showTime) || + ((isset($param['showtime'])) && ($param['showtime'] === true)) + ) { + $text = 'Generated in ' . + sprintf('%0.3f', $timeEnd - $timeStart) . ' sec'; + $this->write( + $this->_right, + $this->_bottom, + $text, + IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_BOTTOM, + array('color' => 'red') + ); + } + + if (isset($param['filename'])) { + if ((isset($param['tohtml'])) && ($param['tohtml'])) { + return $this->_canvas->toHtml($param); + } + else { + return $this->_canvas->save($param); + } + } else { + return $this->_canvas->show($param); + } + } +} + ?> \ No newline at end of file diff --git a/pandora_console/reporting/stat_win.php b/pandora_console/reporting/stat_win.php index df32b5b912..2e2e504609 100644 --- a/pandora_console/reporting/stat_win.php +++ b/pandora_console/reporting/stat_win.php @@ -40,12 +40,10 @@ if (comprueba_login() != 0) { if (isset($_GET['refresh']) and is_numeric($_GET['refresh']) and $_GET['refresh']>0) { header( 'refresh: ' . $_GET['refresh'] ); } -// Read styles -echo ''; - -echo ""; +echo ' +Pandora FMS Graph +'; +; // Get input parameters @@ -151,25 +149,6 @@ echo ""; - - -