From 4427f59c63f88971deeaaa9809374df18d1eb288 Mon Sep 17 00:00:00 2001 From: Daniel Stefan Haischt Date: Thu, 27 Jul 2006 01:32:35 +0000 Subject: - added missing PEAR Image dependency --- packages/dspam/pear/Image/Canvas.php | 733 +++++++++ packages/dspam/pear/Image/Canvas/Color.php | 182 +++ packages/dspam/pear/Image/Canvas/Fonts/README | 12 + packages/dspam/pear/Image/Canvas/Fonts/fontmap.txt | 25 + packages/dspam/pear/Image/Canvas/GD.php | 1693 ++++++++++++++++++++ packages/dspam/pear/Image/Canvas/GD/JPG.php | 119 ++ packages/dspam/pear/Image/Canvas/GD/PNG.php | 125 ++ packages/dspam/pear/Image/Canvas/ImageMap.php | 354 ++++ packages/dspam/pear/Image/Canvas/PDF.php | 1007 ++++++++++++ packages/dspam/pear/Image/Canvas/SVG.php | 918 +++++++++++ packages/dspam/pear/Image/Canvas/Tool.php | 217 +++ packages/dspam/pear/Image/Canvas/WithMap.php | 278 ++++ packages/dspam/pear/Image/Color.php | 719 +++++++++ packages/dspam/pear/Image/Graph.php | 851 ++++++++++ packages/dspam/pear/Image/Graph/Axis.php | 1690 +++++++++++++++++++ packages/dspam/pear/Image/Graph/Axis/Category.php | 437 +++++ .../dspam/pear/Image/Graph/Axis/Logarithmic.php | 152 ++ .../dspam/pear/Image/Graph/Axis/Marker/Area.php | 156 ++ .../dspam/pear/Image/Graph/Axis/Marker/Line.php | 124 ++ packages/dspam/pear/Image/Graph/Axis/Radar.php | 204 +++ packages/dspam/pear/Image/Graph/Common.php | 313 ++++ packages/dspam/pear/Image/Graph/Config.php | 30 + packages/dspam/pear/Image/Graph/Constants.php | 225 +++ .../dspam/pear/Image/Graph/DataPreprocessor.php | 74 + .../pear/Image/Graph/DataPreprocessor/Array.php | 103 ++ .../pear/Image/Graph/DataPreprocessor/Currency.php | 66 + .../pear/Image/Graph/DataPreprocessor/Date.php | 90 ++ .../Image/Graph/DataPreprocessor/Formatted.php | 90 ++ .../pear/Image/Graph/DataPreprocessor/Function.php | 92 ++ .../Image/Graph/DataPreprocessor/NumberText.php | 89 + .../Image/Graph/DataPreprocessor/RomanNumerals.php | 79 + .../Image/Graph/DataPreprocessor/Sequential.php | 67 + packages/dspam/pear/Image/Graph/DataSelector.php | 67 + .../Image/Graph/DataSelector/EveryNthPoint.php | 97 ++ .../pear/Image/Graph/DataSelector/NoZeros.php | 68 + .../dspam/pear/Image/Graph/DataSelector/Values.php | 90 ++ packages/dspam/pear/Image/Graph/Dataset.php | 483 ++++++ .../dspam/pear/Image/Graph/Dataset/Function.php | 147 ++ packages/dspam/pear/Image/Graph/Dataset/Random.php | 77 + .../dspam/pear/Image/Graph/Dataset/Sequential.php | 114 ++ .../dspam/pear/Image/Graph/Dataset/Trivial.php | 260 +++ .../pear/Image/Graph/Dataset/VectorFunction.php | 185 +++ packages/dspam/pear/Image/Graph/Element.php | 763 +++++++++ packages/dspam/pear/Image/Graph/Figure/Circle.php | 64 + packages/dspam/pear/Image/Graph/Figure/Ellipse.php | 97 ++ packages/dspam/pear/Image/Graph/Figure/Polygon.php | 94 ++ .../dspam/pear/Image/Graph/Figure/Rectangle.php | 96 ++ packages/dspam/pear/Image/Graph/Fill.php | 63 + packages/dspam/pear/Image/Graph/Fill/Array.php | 137 ++ packages/dspam/pear/Image/Graph/Fill/Gradient.php | 149 ++ packages/dspam/pear/Image/Graph/Fill/Image.php | 97 ++ packages/dspam/pear/Image/Graph/Font.php | 158 ++ packages/dspam/pear/Image/Graph/Grid.php | 175 ++ packages/dspam/pear/Image/Graph/Grid/Bars.php | 117 ++ packages/dspam/pear/Image/Graph/Grid/Lines.php | 114 ++ packages/dspam/pear/Image/Graph/Grid/Polar.php | 111 ++ .../pear/Image/Graph/Images/Icons/pinpoint.png | Bin 0 -> 452 bytes .../pear/Image/Graph/Images/Icons/pinpointr.png | Bin 0 -> 437 bytes packages/dspam/pear/Image/Graph/Images/Maps/README | 17 + packages/dspam/pear/Image/Graph/Layout.php | 219 +++ .../dspam/pear/Image/Graph/Layout/Horizontal.php | 186 +++ packages/dspam/pear/Image/Graph/Layout/Matrix.php | 201 +++ .../dspam/pear/Image/Graph/Layout/Vertical.php | 108 ++ packages/dspam/pear/Image/Graph/Legend.php | 385 +++++ packages/dspam/pear/Image/Graph/Line/Array.php | 129 ++ packages/dspam/pear/Image/Graph/Line/Dashed.php | 76 + packages/dspam/pear/Image/Graph/Line/Dotted.php | 67 + packages/dspam/pear/Image/Graph/Line/Formatted.php | 90 ++ packages/dspam/pear/Image/Graph/Line/Solid.php | 105 ++ packages/dspam/pear/Image/Graph/Logo.php | 153 ++ packages/dspam/pear/Image/Graph/Marker.php | 123 ++ packages/dspam/pear/Image/Graph/Marker/Array.php | 105 ++ .../dspam/pear/Image/Graph/Marker/Asterisk.php | 109 ++ packages/dspam/pear/Image/Graph/Marker/Average.php | 91 ++ packages/dspam/pear/Image/Graph/Marker/Box.php | 76 + packages/dspam/pear/Image/Graph/Marker/Bubble.php | 91 ++ packages/dspam/pear/Image/Graph/Marker/Circle.php | 96 ++ packages/dspam/pear/Image/Graph/Marker/Cross.php | 114 ++ packages/dspam/pear/Image/Graph/Marker/Diamond.php | 73 + packages/dspam/pear/Image/Graph/Marker/Icon.php | 133 ++ .../dspam/pear/Image/Graph/Marker/Pinpoint.php | 65 + packages/dspam/pear/Image/Graph/Marker/Plus.php | 98 ++ .../dspam/pear/Image/Graph/Marker/Pointing.php | 140 ++ .../pear/Image/Graph/Marker/Pointing/Angular.php | 105 ++ .../pear/Image/Graph/Marker/Pointing/Radial.php | 91 ++ .../pear/Image/Graph/Marker/ReversePinpoint.php | 65 + packages/dspam/pear/Image/Graph/Marker/Star.php | 88 + .../dspam/pear/Image/Graph/Marker/Triangle.php | 75 + packages/dspam/pear/Image/Graph/Marker/Value.php | 214 +++ packages/dspam/pear/Image/Graph/Plot.php | 824 ++++++++++ packages/dspam/pear/Image/Graph/Plot/Area.php | 194 +++ packages/dspam/pear/Image/Graph/Plot/Band.php | 205 +++ packages/dspam/pear/Image/Graph/Plot/Bar.php | 307 ++++ .../dspam/pear/Image/Graph/Plot/BoxWhisker.php | 298 ++++ .../dspam/pear/Image/Graph/Plot/CandleStick.php | 251 +++ packages/dspam/pear/Image/Graph/Plot/Dot.php | 99 ++ packages/dspam/pear/Image/Graph/Plot/Fit/Line.php | 118 ++ packages/dspam/pear/Image/Graph/Plot/Impulse.php | 204 +++ packages/dspam/pear/Image/Graph/Plot/Line.php | 171 ++ packages/dspam/pear/Image/Graph/Plot/Odo.php | 719 +++++++++ packages/dspam/pear/Image/Graph/Plot/Pie.php | 623 +++++++ packages/dspam/pear/Image/Graph/Plot/Radar.php | 118 ++ .../dspam/pear/Image/Graph/Plot/Smoothed/Area.php | 145 ++ .../pear/Image/Graph/Plot/Smoothed/Bezier.php | 173 ++ .../dspam/pear/Image/Graph/Plot/Smoothed/Line.php | 172 ++ .../dspam/pear/Image/Graph/Plot/Smoothed/Radar.php | 142 ++ packages/dspam/pear/Image/Graph/Plot/Step.php | 200 +++ packages/dspam/pear/Image/Graph/Plotarea.php | 1145 +++++++++++++ .../dspam/pear/Image/Graph/Plotarea/Element.php | 87 + packages/dspam/pear/Image/Graph/Plotarea/Map.php | 304 ++++ packages/dspam/pear/Image/Graph/Plotarea/Radar.php | 243 +++ packages/dspam/pear/Image/Graph/Simple.php | 121 ++ packages/dspam/pear/Image/Graph/Title.php | 194 +++ packages/dspam/pear/Image/Graph/Tool.php | 291 ++++ 114 files changed, 26173 insertions(+) create mode 100644 packages/dspam/pear/Image/Canvas.php create mode 100644 packages/dspam/pear/Image/Canvas/Color.php create mode 100644 packages/dspam/pear/Image/Canvas/Fonts/README create mode 100644 packages/dspam/pear/Image/Canvas/Fonts/fontmap.txt create mode 100644 packages/dspam/pear/Image/Canvas/GD.php create mode 100644 packages/dspam/pear/Image/Canvas/GD/JPG.php create mode 100644 packages/dspam/pear/Image/Canvas/GD/PNG.php create mode 100644 packages/dspam/pear/Image/Canvas/ImageMap.php create mode 100644 packages/dspam/pear/Image/Canvas/PDF.php create mode 100644 packages/dspam/pear/Image/Canvas/SVG.php create mode 100644 packages/dspam/pear/Image/Canvas/Tool.php create mode 100644 packages/dspam/pear/Image/Canvas/WithMap.php create mode 100644 packages/dspam/pear/Image/Color.php create mode 100644 packages/dspam/pear/Image/Graph.php create mode 100644 packages/dspam/pear/Image/Graph/Axis.php create mode 100644 packages/dspam/pear/Image/Graph/Axis/Category.php create mode 100644 packages/dspam/pear/Image/Graph/Axis/Logarithmic.php create mode 100644 packages/dspam/pear/Image/Graph/Axis/Marker/Area.php create mode 100644 packages/dspam/pear/Image/Graph/Axis/Marker/Line.php create mode 100644 packages/dspam/pear/Image/Graph/Axis/Radar.php create mode 100644 packages/dspam/pear/Image/Graph/Common.php create mode 100644 packages/dspam/pear/Image/Graph/Config.php create mode 100644 packages/dspam/pear/Image/Graph/Constants.php create mode 100644 packages/dspam/pear/Image/Graph/DataPreprocessor.php create mode 100644 packages/dspam/pear/Image/Graph/DataPreprocessor/Array.php create mode 100644 packages/dspam/pear/Image/Graph/DataPreprocessor/Currency.php create mode 100644 packages/dspam/pear/Image/Graph/DataPreprocessor/Date.php create mode 100644 packages/dspam/pear/Image/Graph/DataPreprocessor/Formatted.php create mode 100644 packages/dspam/pear/Image/Graph/DataPreprocessor/Function.php create mode 100644 packages/dspam/pear/Image/Graph/DataPreprocessor/NumberText.php create mode 100644 packages/dspam/pear/Image/Graph/DataPreprocessor/RomanNumerals.php create mode 100644 packages/dspam/pear/Image/Graph/DataPreprocessor/Sequential.php create mode 100644 packages/dspam/pear/Image/Graph/DataSelector.php create mode 100644 packages/dspam/pear/Image/Graph/DataSelector/EveryNthPoint.php create mode 100644 packages/dspam/pear/Image/Graph/DataSelector/NoZeros.php create mode 100644 packages/dspam/pear/Image/Graph/DataSelector/Values.php create mode 100644 packages/dspam/pear/Image/Graph/Dataset.php create mode 100644 packages/dspam/pear/Image/Graph/Dataset/Function.php create mode 100644 packages/dspam/pear/Image/Graph/Dataset/Random.php create mode 100644 packages/dspam/pear/Image/Graph/Dataset/Sequential.php create mode 100644 packages/dspam/pear/Image/Graph/Dataset/Trivial.php create mode 100644 packages/dspam/pear/Image/Graph/Dataset/VectorFunction.php create mode 100644 packages/dspam/pear/Image/Graph/Element.php create mode 100644 packages/dspam/pear/Image/Graph/Figure/Circle.php create mode 100644 packages/dspam/pear/Image/Graph/Figure/Ellipse.php create mode 100644 packages/dspam/pear/Image/Graph/Figure/Polygon.php create mode 100644 packages/dspam/pear/Image/Graph/Figure/Rectangle.php create mode 100644 packages/dspam/pear/Image/Graph/Fill.php create mode 100644 packages/dspam/pear/Image/Graph/Fill/Array.php create mode 100644 packages/dspam/pear/Image/Graph/Fill/Gradient.php create mode 100644 packages/dspam/pear/Image/Graph/Fill/Image.php create mode 100644 packages/dspam/pear/Image/Graph/Font.php create mode 100644 packages/dspam/pear/Image/Graph/Grid.php create mode 100644 packages/dspam/pear/Image/Graph/Grid/Bars.php create mode 100644 packages/dspam/pear/Image/Graph/Grid/Lines.php create mode 100644 packages/dspam/pear/Image/Graph/Grid/Polar.php create mode 100644 packages/dspam/pear/Image/Graph/Images/Icons/pinpoint.png create mode 100644 packages/dspam/pear/Image/Graph/Images/Icons/pinpointr.png create mode 100644 packages/dspam/pear/Image/Graph/Images/Maps/README create mode 100644 packages/dspam/pear/Image/Graph/Layout.php create mode 100644 packages/dspam/pear/Image/Graph/Layout/Horizontal.php create mode 100644 packages/dspam/pear/Image/Graph/Layout/Matrix.php create mode 100644 packages/dspam/pear/Image/Graph/Layout/Vertical.php create mode 100644 packages/dspam/pear/Image/Graph/Legend.php create mode 100644 packages/dspam/pear/Image/Graph/Line/Array.php create mode 100644 packages/dspam/pear/Image/Graph/Line/Dashed.php create mode 100644 packages/dspam/pear/Image/Graph/Line/Dotted.php create mode 100644 packages/dspam/pear/Image/Graph/Line/Formatted.php create mode 100644 packages/dspam/pear/Image/Graph/Line/Solid.php create mode 100644 packages/dspam/pear/Image/Graph/Logo.php create mode 100644 packages/dspam/pear/Image/Graph/Marker.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Array.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Asterisk.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Average.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Box.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Bubble.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Circle.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Cross.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Diamond.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Icon.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Pinpoint.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Plus.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Pointing.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Pointing/Angular.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Pointing/Radial.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/ReversePinpoint.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Star.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Triangle.php create mode 100644 packages/dspam/pear/Image/Graph/Marker/Value.php create mode 100644 packages/dspam/pear/Image/Graph/Plot.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Area.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Band.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Bar.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/BoxWhisker.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/CandleStick.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Dot.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Fit/Line.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Impulse.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Line.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Odo.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Pie.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Radar.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Smoothed/Area.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Smoothed/Bezier.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Smoothed/Line.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Smoothed/Radar.php create mode 100644 packages/dspam/pear/Image/Graph/Plot/Step.php create mode 100644 packages/dspam/pear/Image/Graph/Plotarea.php create mode 100644 packages/dspam/pear/Image/Graph/Plotarea/Element.php create mode 100644 packages/dspam/pear/Image/Graph/Plotarea/Map.php create mode 100644 packages/dspam/pear/Image/Graph/Plotarea/Radar.php create mode 100644 packages/dspam/pear/Image/Graph/Simple.php create mode 100644 packages/dspam/pear/Image/Graph/Title.php create mode 100644 packages/dspam/pear/Image/Graph/Tool.php (limited to 'packages/dspam/pear/Image') diff --git a/packages/dspam/pear/Image/Canvas.php b/packages/dspam/pear/Image/Canvas.php new file mode 100644 index 00000000..e669807a --- /dev/null +++ b/packages/dspam/pear/Image/Canvas.php @@ -0,0 +1,733 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @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']); + } + } + + /** + * 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; + } + + /** + * Reset the canvas. + * + * Includes fillstyle, linestyle, thickness and polygon + */ + function reset() + { + $this->_reset(); + } + + /** + * 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) + { + } + + /** + * Set clipping to occur + * + * Parameter array: + * + * 'x0': int X point of Upper-left corner + * 'y0': int X point of Upper-left corner + * 'x1': int X point of lower-right corner + * 'y1': int Y point of lower-right corner + */ + function setClipping($params = false) + { + } + + /** + * 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; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Canvas/Color.php b/packages/dspam/pear/Image/Canvas/Color.php new file mode 100644 index 00000000..0ac78553 --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/Color.php @@ -0,0 +1,182 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id$ + +/** +* 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/packages/dspam/pear/Image/Canvas/Fonts/README b/packages/dspam/pear/Image/Canvas/Fonts/README new file mode 100644 index 00000000..0a836147 --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/Fonts/README @@ -0,0 +1,12 @@ +This is where the font files are located. + +Font files can be found at: + +MS CoreFonts + http://corefonts.sourceforge.net/ + +Divide By Zero (most are cartoonish) + http://fonts.tom7.com/ + +MING FDB Fonts + http://ming.sf.net/ \ No newline at end of file diff --git a/packages/dspam/pear/Image/Canvas/Fonts/fontmap.txt b/packages/dspam/pear/Image/Canvas/Fonts/fontmap.txt new file mode 100644 index 00000000..ccec67dd --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/Fonts/fontmap.txt @@ -0,0 +1,25 @@ +Arial,arial.ttf +Arial Bold,arialbd.ttf +Arial Bold Italic,arialbi.ttf +Arial Italic,ariali.ttf +Courier New,cour.ttf +Courier New Bold,courbd.ttf +Courier New Bold Italic,courbi.ttf +Courier New Italic,couri.ttf +Garamond,gara.ttf +Garamond Bold,garabd.ttf +Garamond Italic,garait.ttf +Gothic,gothic.ttf +Gothic Bold,gothicb.ttf +Gothic Bold Italic,gothicbi.ttf +Gothic Italic,gothici.ttf +Sans Serif,micross.ttf +Reference Sans Serif,refsan.ttf +Times New Roman,times.ttf +Times New Roman Bold,timesbd.ttf +Times New Roman Bold Italic,timesbi.ttf +Times New Roman Italic,timesi.ttf +Verdana,verdana.ttf +Verdana Bold,verdanab.ttf +Verdana Bold Italic,verdanaz.ttf +Verdana Italic,verdanai.ttf \ No newline at end of file diff --git a/packages/dspam/pear/Image/Canvas/GD.php b/packages/dspam/pear/Image/Canvas/GD.php new file mode 100644 index 00000000..40132899 --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/GD.php @@ -0,0 +1,1693 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @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 + */ + var $_antialias = 'off'; + + var $_alpha = false; + + var $_clipping = array(); + + /** + * 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); + $this->_alpha = 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')) { + 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('\\', '/', Image_Canvas_Tool::fontMap($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); + } + + /** + * Set clipping to occur + * + * Parameter array: + * + * 'x0': int X point of Upper-left corner + * 'y0': int X point of Upper-left corner + * 'x1': int X point of lower-right corner + * 'y1': int Y point of lower-right corner + */ + function setClipping($params = false) + { + if ($params === false) { + $index = count($this->_clipping) - 1; + if (isset($this->_clipping[$index])) { + $params = $this->_clipping[$index]; + $canvas = $params['canvas']; + ImageCopy( + $canvas, + $this->_canvas, + min($params['x0'], $params['x1']), + min($params['y0'], $params['y1']), + min($params['x0'], $params['x1']), + min($params['y0'], $params['y1']), + abs($params['x1'] - $params['x0'] + 1), + abs($params['y1'] - $params['y0'] + 1) + ); + $this->_canvas = $canvas; + unset($this->_clipping[$index]); + } + } + else { + $params['canvas'] = $this->_canvas; + + if ($this->_gd2) { + $this->_canvas = ImageCreateTrueColor( + $this->_width, + $this->_height + ); + if ($this->_alpha) { + ImageAlphaBlending($this->_canvas, true); + } + } else { + $this->_canvas = ImageCreate($this->_width, $this->_height); + } + + if (($this->_gd2) && ($this->_antialias === 'native')) { + ImageAntialias($this->_canvas, true); + } + + ImageCopy($this->_canvas, $params['canvas'], 0, 0, 0, 0, $this->_width, $this->_height); + + $this->_clipping[count($this->_clipping)] = $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; + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Canvas/GD/JPG.php b/packages/dspam/pear/Image/Canvas/GD/JPG.php new file mode 100644 index 00000000..ef78aeca --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/GD/JPG.php @@ -0,0 +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$ + * @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/packages/dspam/pear/Image/Canvas/GD/PNG.php b/packages/dspam/pear/Image/Canvas/GD/PNG.php new file mode 100644 index 00000000..75184d8c --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/GD/PNG.php @@ -0,0 +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$ + * @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/packages/dspam/pear/Image/Canvas/ImageMap.php b/packages/dspam/pear/Image/Canvas/ImageMap.php new file mode 100644 index 00000000..e69f3de2 --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/ImageMap.php @@ -0,0 +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$ + * @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, '"') !== false) { + $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/packages/dspam/pear/Image/Canvas/PDF.php b/packages/dspam/pear/Image/Canvas/PDF.php new file mode 100644 index 00000000..180263cb --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/PDF.php @@ -0,0 +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$ + * @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) || ($color === 'opague') || ($color === 'transparent')) { + 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::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 (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/packages/dspam/pear/Image/Canvas/SVG.php b/packages/dspam/pear/Image/Canvas/SVG.php new file mode 100644 index 00000000..3fed62ba --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/SVG.php @@ -0,0 +1,918 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @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 = array()) { + $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 = min($this->_getX($params['x0']), $this->_getX($params['x1'])); + $y0 = min($this->_getY($params['y0']), $this->_getY($params['y1'])); + $x1 = max($this->_getX($params['x0']), $this->_getX($params['x1'])); + $y1 = max($this->_getY($params['y0']), $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( + '' . "\n" . + $this->_indent . ' _font['angle']) && ($this->_font['angle'] > 0) ? + 'transform="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 . '">' . + htmlspecialchars($text) . + '' . "\n" . + $this->_indent . '', + $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); + } + + /** + * Set clipping to occur + * + * Parameter array: + * + * 'x0': int X point of Upper-left corner + * 'y0': int X point of Upper-left corner + * 'x1': int X point of lower-right corner + * 'y1': int Y point of lower-right corner + */ + function setClipping($params = false) + { + if ($params === false) { + $this->_addElement(''); + } + else { + $group = "clipping_" . $this->_id; + $this->_id++; + $this->_addElement(''); + + $this->_addDefine(''); + $this->_addDefine(' '); + $this->_addDefine(''); + } + } + + /** + * 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/packages/dspam/pear/Image/Canvas/Tool.php b/packages/dspam/pear/Image/Canvas/Tool.php new file mode 100644 index 00000000..3b87122c --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/Tool.php @@ -0,0 +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$ + * @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/packages/dspam/pear/Image/Canvas/WithMap.php b/packages/dspam/pear/Image/Canvas/WithMap.php new file mode 100644 index 00000000..dc43ec4d --- /dev/null +++ b/packages/dspam/pear/Image/Canvas/WithMap.php @@ -0,0 +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$ + * @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/packages/dspam/pear/Image/Color.php b/packages/dspam/pear/Image/Color.php new file mode 100644 index 00000000..1b20125d --- /dev/null +++ b/packages/dspam/pear/Image/Color.php @@ -0,0 +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$ + * @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/packages/dspam/pear/Image/Graph.php b/packages/dspam/pear/Image/Graph.php new file mode 100644 index 00000000..d2e2492b --- /dev/null +++ b/packages/dspam/pear/Image/Graph.php @@ -0,0 +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$ + * @link http://pear.php.net/package/Image_Graph + */ + + +/** + * Include PEAR.php + */ +require_once 'PEAR.inc'; + +/** + * 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: @package_version@ + * @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/packages/dspam/pear/Image/Graph/Axis.php b/packages/dspam/pear/Image/Graph/Axis.php new file mode 100644 index 00000000..99da305f --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Axis.php @@ -0,0 +1,1690 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea/Element.php + */ +require_once 'Image/Graph/Plotarea/Element.php'; + +/** + * Diplays a normal linear axis (either X- or Y-axis). + * + * @category Images + * @package Image_Graph + * @subpackage Axis + * @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/package/Image_Graph + */ + class Image_Graph_Axis extends Image_Graph_Plotarea_Element +{ + + /** + * The type of the axis, possible values are: + *
    + *
  • IMAGE_GRAPH_AXIS_X / IMAGE_GRAPH_AXIS_HORIZONTAL + *
  • IMAGE_GRAPH_AXIS_Y / IMAGE_GRAPH_AXIS_VERTICAL / + * IMAGE_GRAPH_AXIS_Y_SECONDARY + *
+ * @var int + * @access private + */ + var $_type; + + /** + * The minimum value the axis displays + * @var int + * @access private + */ + var $_minimum = false; + + /** + * The minimum value the axis has been explicitly set by the user + * @var bool + * @access private + */ + var $_minimumSet = false; + + /** + * The maximum value the axis displays + * @var int + * @access private + */ + var $_maximum = false; + + /** + * The maximum value the axis has been explicitly set by the user + * @var bool + * @access private + */ + var $_maximumSet = false; + + /** + * The value span of the axis. + * This is primarily included for performance reasons + * @var double + * @access private + */ + var $_axisSpan = false; + + /** + * The value span of the axis. + * This is primarily included for performance reasons + * @var double + * @access private + */ + var $_axisValueSpan = false; + + /** + * The axis padding. + * The index 'low' specifies the padding for the low axis values (when not + * inverted), i.e. to the left on an x-axis and on the bottom of an y-axis, + * vice versa for 'high'. + * + * Axis padding does not make sense on a normal linear y-axis with a 'y-min' + * of 0 since this corresponds to displaying a small part of the y-axis + * below 0! + * + * @var array + * @access private + */ + var $_axisPadding = array('low' => 0, 'high' => 0); + + /** + * The number of "pixels" representing 1 unit on the axis + * + * This is primarily included for performance reasons + * @var double + * @access private + */ + var $_delta = false; + + /** + * Specify if the axis should label the minimum value + * @var bool + * @access private + */ + var $_showLabelMinimum = true; + + /** + * Specify if the axis should label 0 (zero) + * @var bool + * @access private + */ + var $_showLabelZero = false; + + /** + * Specify if the axis should label the maximum value + * @var bool + * @access private + */ + var $_showLabelMaximum = true; + + /** + * Show arrow heads at the 'end' of the axis, default: false + * @var bool + * @access private + */ + var $_showArrow = false; + + /** + * Intersection data of axis + * @var array + * @access private + */ + var $_intersect = array('value' => 'default', 'axis' => 'default'); + + /** + * The fixed size of the axis (i.e. width for y-axis, height for x-axis) + * @var mixed + * @access private + */ + var $_fixedSize = false; + + /** + * The label options + * + * Should text be shows, preferences for ticks. The indexes start at level + * 1, which is chosen for readability + * @var array + * @access private + */ + var $_labelOptions = array( + 1 => array( + 'interval' => 1, + 'type' => 'auto', + 'tick' => array( + 'start' => -2, + 'end' => 2, + 'color' => false // default color + ), + 'showtext' => true, + 'showoffset' => false, + 'font' => array(), + 'offset' => 0, + 'position' => 'outside', + ) + ); + + /** + * The labels that are shown. + * + * This is used to make values show only once... + * @access private + */ + var $_labelText = array(); + + /** + * A data preprocessor for formatting labels, fx showing dates as a standard + * date instead of Unix time stamp + * @var Image_Graph_DatePreProcessor + * @access private + * @see Image_Graph_DataPreProcessor + */ + var $_dataPreProcessor = null; + + /** + * Point marked in the axis + * @var array + * @access private + */ + var $_marks = array(); + + /** + * Specifies whether the values should be 'pushed' by 0.5 + * @var bool + * @access private + */ + var $_pushValues = false; + + /** + * The title of this axis + * @var string + * @access private + */ + var $_title = ''; + + /** + * The font used for the title of this axis + * @var Image_Graph_Font + * @access private + */ + var $_titleFont = false; + + /** + * Invert the axis (i.e. if an y-axis normally displays minimum values at + * the bottom, they are not displayed at the top + * @var bool + * @access private + * @since 0.3.0dev3 + */ + var $_invert = false; + + /** + * Transpose the axis (i.e. is a normal y-axis transposed, so thats it's not show + * vertically as normally expected, but instead horizontally) + * @var bool + * @access private + */ + var $_transpose = false; + + /** + * Image_Graph_Axis [Constructor]. + * Normally a manual creation should not be necessary, axis are created + * automatically by the {@link Image_Graph_Plotarea} constructor unless + * explicitly defined otherwise + * + * @param int $type The type (direction) of the Axis, use IMAGE_GRAPH_AXIS_X + * for an X-axis (default, may be omitted) and IMAGE_GRAPH_AXIS_Y for Y- + * axis) + */ + function Image_Graph_Axis($type = IMAGE_GRAPH_AXIS_X) + { + parent::Image_Graph_Element(); + $this->_type = $type; + $this->_fillStyle = 'black'; + } + + /** + * Push the values by 0.5 (for bar and step chart) + * + * @access private + */ + function _pushValues() + { + $this->_pushValues = true; + } + + /** + * Sets the axis padding for a given position ('low' or 'high') + * @param string $where The position + * @param int $value The number of pixels to "pad" + * @access private + */ + function _setAxisPadding($where, $value) + { + $this->_axisPadding[$where] = $value; + } + + /** + * Gets the font of the title. + * + * If not font has been set, the parent font is propagated through it's + * children. + * + * @return array An associated array used for canvas + * @access private + */ + function _getTitleFont() + { + if ($this->_titleFont === false) { + if ($this->_defaultFontOptions !== false) { + return $this->_defaultFontOptions; + } else { + return $this->_getFont(); + } + } else { + if (is_object($this->_titleFont)) { + return $this->_titleFont->_getFont(); + } elseif (is_array($this->_titleFont)) { + return $this->_getFont($this->_titleFont); + } elseif (is_int($this->_titleFont)) { + return $this->_getFont(array('size' => $this->_titleFont)); + } + } + return array(); + } + + /** + * Shows a label for the the specified values. + * + * Allowed values are combinations of: + *
    + *
  • IMAGE_GRAPH_LABEL_MINIMUM + *
  • IMAGE_GRAPH_LABEL_ZERO + *
  • IMAGE_GRAPH_LABEL_MAXIMUM + *
+ * By default none of these are shows on the axis + * + * @param int $value The values to show labels for + */ + function showLabel($value) + { + $this->_showLabelMinimum = ($value & IMAGE_GRAPH_LABEL_MINIMUM); + $this->_showLabelZero = ($value & IMAGE_GRAPH_LABEL_ZERO); + $this->_showLabelMaximum = ($value & IMAGE_GRAPH_LABEL_MAXIMUM); + } + + /** + * Sets a data preprocessor for formatting the axis labels + * + * @param Image_Graph_DataPreprocessor $dataPreProcessor The data preprocessor + * @see Image_Graph_DataPreprocessor + */ + function setDataPreProcessor(& $dataPreProcessor) + { + $this->_dataPreProcessor =& $dataPreProcessor; + } + + /** + * Gets the minimum value the axis will show + * + * @return double The minumum value + * @access private + */ + function _getMinimum() + { + return $this->_minimum; + } + + /** + * Gets the maximum value the axis will show + * + * @return double The maximum value + * @access private + */ + function _getMaximum() + { + return $this->_maximum; + } + + /** + * Sets the minimum value the axis will show + * + * @param double $minimum The minumum value to use on the axis + * @access private + */ + function _setMinimum($minimum) + { + if ($this->_minimum === false) { + $this->forceMinimum($minimum, false); + } else { + $this->forceMinimum(min($this->_minimum, $minimum), false); + } + } + + /** + * Sets the maximum value the axis will show + * + * @param double $maximum The maximum value to use on the axis + * @access private + */ + function _setMaximum($maximum) + { + if ($this->_maximum === false) { + $this->forceMaximum($maximum, false); + } else { + $this->forceMaximum(max($this->_maximum, $maximum), false); + } + } + + /** + * Forces the minimum value of the axis + * + * @param double $minimum The minumum value to use on the axis + * @param bool $userEnforce This value should not be set, used internally + */ + function forceMinimum($minimum, $userEnforce = true) + { + if (($userEnforce) || (!$this->_minimumSet)) { + $this->_minimum = $minimum; + $this->_minimumSet = $userEnforce; + } + $this->_calcLabelInterval(); + } + + /** + * Forces the maximum value of the axis + * + * @param double $maximum The maximum value to use on the axis + * @param bool $userEnforce This value should not be set, used internally + */ + function forceMaximum($maximum, $userEnforce = true) + { + if (($userEnforce) || (!$this->_maximumSet)) { + $this->_maximum = $maximum; + $this->_maximumSet = $userEnforce; + } + $this->_calcLabelInterval(); + } + + /** + * Show an arrow head on the 'end' of the axis + */ + function showArrow() + { + $this->_showArrow = true; + } + + /** + * Do not show an arrow head on the 'end' of the axis (default) + */ + function hideArrow() + { + $this->_showArrow = false; + } + + /** + * Return the label distance. + * + * @param int $level The label level to return the distance of + * @return int The distance between 2 adjacent labels + * @access private + */ + function _labelDistance($level = 1) + { + $l1 = $this->_getNextLabel(false, $level); + $l2 = $this->_getNextLabel($l1, $level);; + return abs($this->_point($l2) - $this->_point($l1)); + } + + /** + * Sets an interval for when labels are shown on the axis. + * + * By default 'auto' is used, forcing the axis to calculate a approximate + * best label interval to be used. Specify an array to use user-defined + * values for labels. + * + * @param mixed $labelInterval The interval with which labels are shown + * @param int $level The label level to set the interval on + */ + function setLabelInterval($labelInterval = 'auto', $level = 1) + { + if (!isset($this->_labelOptions[$level])) { + $this->_labelOptions[$level] = array(); + } + + if ($labelInterval === 'auto') { + $this->_labelOptions[$level]['type'] = 'auto'; + $this->_calcLabelInterval(); + } else { + $this->_labelOptions[$level]['type'] = 'manual'; + $this->_labelOptions[$level]['interval'] = $labelInterval; + } + } + + /** + * Sets options for the label at a specific level. + * + * Possible options are: + * + * 'showtext' true or false whether label text should be shown or not + * + * 'showoffset' should the label be shown at an offset, i.e. should the + * label be shown at a position so that it does not overlap with prior + * levels. Only applies to multilevel labels with text + * + * 'font' The font options as an associated array + * + * 'position' The position at which the labels are written ('inside' or + * 'outside' the axis). NB! This relative position only applies to the + * default location of the axis, i.e. if an x-axis is inverted then + * 'outside' still refers to the "left" side of a normal y-axis (since this + * is normally 'outside') but the actual output will be labels on the + * "inside"! + * + * 'format' To format the label text according to a sprintf statement + * + * 'dateformat' To format the label as a date, fx. j. M Y = 29. Jun 2005 + * + * @param string $option The label option name (see detailed description + * for possible values) + * @param mixed $value The value for the option + * @param int $level The label level to set the interval on + */ + function setLabelOption($option, $value, $level = 1) + { + if (!isset($this->_labelOptions[$level])) { + $this->_labelOptions[$level] = array('type' => 'auto'); + } + + $this->_labelOptions[$level][$option] = $value; + } + + /** + * Sets options for the label at a specific level. + * + * The possible options are specified in {@link Image_Graph_Axis:: + * setLabelOption()}. + * + * @param array $options An assciated array with label options + * @param int $level The label level to set the interval on + */ + function setLabelOptions($options, $level = 1) + { + if (is_array($options)) { + if (isset($this->_labelOptions[$level])) { + $this->_labelOptions[$level] = array_merge($this->_labelOptions[$level], $options); + } else { + $this->_labelOptions[$level] = $options; + } + + } + } + + /** + * Sets the title of this axis. + * + * This is used as an alternative (maybe better) method, than using layout's + * for axis-title generation. + * + * To use the current propagated font, but just set it vertically, simply + * pass 'vertical' as second parameter for vertical alignment down-to-up or + * 'vertical2' for up-to-down alignment. + * + * @param string $title The title of this axis + * @param Image_Graph_Font $font The font used for the title + * @since 0.3.0dev2 + */ + function setTitle($title, $font = false) + { + $this->_title = $title; + if ($font === 'vertical') { + $this->_titleFont = array('vertical' => true, 'angle' => 90); + } elseif ($font === 'vertical2') { + $this->_titleFont = array('vertical' => true, 'angle' => 270); + } else { + $this->_titleFont =& $font; + } + } + + /** + * Sets a fixed "size" for the axis. + * + * If the axis is any type of y-axis the size relates to the width of the + * axis, if an x-axis is concerned the size is the height. + * + * @param int $size The fixed size of the axis + * @since 0.3.0dev5 + */ + function setFixedSize($size) + { + $this->_fixedSize = $size; + } + + /** + * Preprocessor for values, ie for using logarithmic axis + * + * @param double $value The value to preprocess + * @return double The preprocessed value + * @access private + */ + function _value($value) + { + return $value - $this->_getMinimum() + ($this->_pushValues ? 0.5 : 0); + } + + /** + * Apply the dataset to the axis + * + * @param Image_Graph_Dataset $dataset The dataset + * @access private + */ + function _applyDataset(&$dataset) + { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + $this->_setMinimum($dataset->minimumX()); + $this->_setMaximum($dataset->maximumX()); + } else { + $this->_setMinimum($dataset->minimumY()); + $this->_setMaximum($dataset->maximumY()); + } + } + + /** + * Get the pixel position represented by a value on the canvas + * + * @param double $value the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _point($value) + { + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + if ($this->_invert) { + return max($this->_left, $this->_right - $this->_axisPadding['high'] - $this->_delta * $this->_value($value)); + } else { + return min($this->_right, $this->_left + $this->_axisPadding['low'] + $this->_delta * $this->_value($value)); + } + } else { + if ($this->_invert) { + return min($this->_bottom, $this->_top + $this->_axisPadding['high'] + $this->_delta * $this->_value($value)); + } else { + return max($this->_top, $this->_bottom - $this->_axisPadding['low'] - $this->_delta * $this->_value($value)); + } + } + } + + + /** + * Get the axis intersection pixel position + * + * This is only to be called prior to output! I.e. between the user + * invokation of Image_Graph::done() and any actual output is performed. + * This is because it can change the axis range. + * + * @param double $value the intersection value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _intersectPoint($value) + { + + if (($value === 'min') || ($value < $this->_getMinimum())) { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + if ($this->_invert) { + return ($this->_transpose ? $this->_top : $this->_right); + } else { + return ($this->_transpose ? $this->_bottom : $this->_left); + } + } else { + if ($this->_invert) { + return ($this->_transpose ? $this->_right : $this->_top); + } else { + return ($this->_transpose ? $this->_left : $this->_bottom); + } + } + } elseif (($value === 'max') || ($value > $this->_getMaximum())) { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + if ($this->_invert) { + return ($this->_transpose ? $this->_bottom : $this->_left); + } else { + return ($this->_transpose ? $this->_top : $this->_right); + } + } else { + if ($this->_invert) { + return ($this->_transpose ? $this->_left : $this->_bottom); + } else { + return ($this->_transpose ? $this->_right : $this->_top); + } + } + } + + return $this->_point($value); + } + + /** + * Calculate the delta value (the number of pixels representing one unit + * on the axis) + * + * @return double The label interval + * @access private + */ + function _calcDelta() + { + if ($this->_axisValueSpan == 0) { + $this->_delta = false; + } elseif ($this->_type == IMAGE_GRAPH_AXIS_X) { + $this->_delta = (($this->_transpose ? $this->height() : $this->width()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / ($this->_axisValueSpan + ($this->_pushValues ? 1 : 0)); + } else { + $this->_delta = (($this->_transpose ? $this->width() : $this->height()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / ($this->_axisValueSpan + ($this->_pushValues ? 1 : 0)); + } + } + + /** + * Calculate the label interval + * + * If explicitly defined this will be calucated to an approximate best. + * + * @return double The label interval + * @access private + */ + function _calcLabelInterval() + { + $min = $this->_getMinimum(); + $max = $this->_getMaximum(); + + $this->_axisValueSpan = $this->_axisSpan = abs($max - $min); + + if ((!empty($min)) && (!empty($max)) && ($min > $max)) { + $this->_labelOptions[1]['interval'] = 1; + return true; + } + + $span = 0; + foreach($this->_labelOptions as $level => $labelOptions) { + if ((!isset($labelOptions['type'])) || ($labelOptions['type'] !== 'auto')) { + $span = false; + } elseif ($level == 1) { + $span = $this->_axisValueSpan; + } else { + $l1 = $this->_getNextLabel(false, $level - 1); + $l2 = $this->_getNextLabel($l1, $level - 1); + if ((!is_numeric($l1)) || (!is_numeric($l2))) { + $span == false; + } else { + $span = $l2 - $l1; + } + } + + if ($span !== false) { + $interval = pow(10, floor(log10($span))); + + if ($interval == 0) { + $interval = 1; + } + + if ((($span) / $interval) < 3) { + $interval = $interval / 4; + } elseif ((($span) / $interval) < 5) { + $interval = $interval / 2; + } elseif ((($span) / $interval) > 10) { + $interval = $interval * 2; + } + + if (($interval -floor($interval) == 0.5) && ($interval != 0.5)) { + $interval = floor($interval); + } + + // just to be 100% sure that an interval of 0 is not returned some + // additional checks are performed + if ($interval == 0) { + $interval = ($span) / 5; + } + + if ($interval == 0) { + $interval = 1; + } + + $this->_labelOptions[$level]['interval'] = $interval; + } + } + } + + /** + * Get next label point + * + * @param doubt $currentLabel The current label, if omitted or false, the + * first is returned + * @param int $level The label level to get the next label from + * @return double The next label point + * @access private + */ + function _getNextLabel($currentLabel = false, $level = 1) + { + if (!isset($this->_labelOptions[$level])) { + return false; + } + + if (is_array($this->_labelOptions[$level]['interval'])) { + if ($currentLabel === false) { + reset($this->_labelOptions[$level]['interval']); + } + + if (list(, $label) = each($this->_labelOptions[$level]['interval'])) { + return $label; + } else { + return false; + } + } else { + $li = $this->_labelInterval($level); + if (($this->_axisSpan == 0) || ($this->_axisValueSpan == 0) || + ($li == 0) + ) { + return false; + } + + $labelInterval = $this->_axisSpan / ($this->_axisValueSpan / $li); + + if ($labelInterval == 0) { + return false; + } + + if ($currentLabel === false) { + $label = ((int) ($this->_getMinimum() / $labelInterval)) * + $labelInterval - $labelInterval; + while ($label < $this->_getMinimum()) { + $label += $labelInterval; + } + return $label; + } else { + if ($currentLabel + $labelInterval > $this->_getMaximum()) { + return false; + } else { + return $currentLabel + $labelInterval; + } + } + } + } + + /** + * Get the interval with which labels are shown on the axis. + * + * If explicitly defined this will be calucated to an approximate best. + * + * @param int $level The label level to get the label interval for + * @return double The label interval + * @access private + */ + function _labelInterval($level = 1) + { + if ((!isset($this->_labelOptions[$level])) || + (!isset($this->_labelOptions[$level]['interval'])) + ) { + return 1; + } + + return (is_array($this->_labelOptions[$level]['interval']) + ? 1 + : $this->_labelOptions[$level]['interval'] + ); + } + + /** + * Get the size in pixels of the axis. + * + * For an x-axis this is the width of the axis including labels, and for an + * y-axis it is the corrresponding height + * + * @return int The size of the axis + * @access private + */ + function _size() + { + if (!$this->_visible) { + return 0; + } + + if ($this->_fixedSize !== false) { + return $this->_fixedSize; + } + + krsort($this->_labelOptions); + + $totalMaxSize = 0; + + foreach ($this->_labelOptions as $level => $labelOptions) { + if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) { + $this->_labelOptions[$level]['offset'] += $totalMaxSize; + } elseif (!isset($this->_labelOptions[$level]['offset'])) { + $this->_labelOptions[$level]['offset'] = 0; + } + if ( + (isset($labelOptions['showtext'])) && + ($labelOptions['showtext'] === true) && + ( + (!isset($labelOptions['position'])) || + ($labelOptions['position'] == 'outside') + ) + ) { + if (isset($labelOptions['font'])) { + $font = $this->_getFont($labelOptions['font']); + } else { + if ($this->_defaultFontOptions !== false) { + $font = $this->_defaultFontOptions; + } else { + $font = $this->_getFont(); + } + } + $this->_canvas->setFont($font); + + $value = false; + $maxSize = 0; + while (($value = $this->_getNextLabel($value, $level)) !== false) { + if ((abs($value) > 0.0001) && ($value > $this->_getMinimum()) && + ($value < $this->_getMaximum())) + { + if (is_object($this->_dataPreProcessor)) { + $labelText = $this->_dataPreProcessor->_process($value); + } elseif (isset($labelOptions['format'])) { + $labelText = sprintf($labelOptions['format'], $value); + } elseif (isset($labelOptions['dateformat'])) { + $labelText = date($labelOptions['dateformat'], $value); + } else { + $labelText = $value; + } + + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + $maxSize = max($maxSize, $this->_canvas->textHeight($labelText)); + } else { + $maxSize = max($maxSize, $this->_canvas->textWidth($labelText)); + } + } + } + if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) { + $totalMaxSize += $maxSize; + } else { + $totalMaxSize = max($totalMaxSize, $maxSize); + } + } + } + + if ($this->_title) { + $this->_canvas->setFont($this->_getTitleFont()); + + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + $totalMaxSize += $this->_canvas->textHeight($this->_title); + } else { + $totalMaxSize += $this->_canvas->textWidth($this->_title); + } + $totalMaxSize += 10; + } + + return $totalMaxSize + 3; + } + + /** + * Adds a mark to the axis at the specified value + * + * @param double $value The value + * @param double $value2 The second value (for a ranged mark) + */ + function addMark($value, $value2 = false, $text = false) + { + if ($value2 === false) { + $this->_marks[] = $value; + } else { + $this->_marks[] = array($value, $value2); + } + } + + /** + * Is the axis numeric or not? + * + * @return bool True if numeric, false if not + * @access private + */ + function _isNumeric() + { + return true; + } + + /** + * Set the major tick appearance. + * + * The positions are specified in pixels relative to the axis, meaning that + * a value of -1 for start will draw the major tick 'line' starting at 1 + * pixel outside (negative) value the axis (i.e. below an x-axis and to the + * left of a normal y-axis). + * + * @param int $start The start position relative to the axis + * @param int $end The end position relative to the axis + * @param int $level The label level to set the tick options for + * @since 0.3.0dev2 + */ + function setTickOptions($start, $end, $level = 1) + { + if (!isset($this->_labelOptions[$level])) { + $this->_labelOptions[$level] = array(); + } + + $this->_labelOptions[$level]['tick'] = array( + 'start' => $start, + 'end' => $end + ); + } + + /** + * Invert the axis direction + * + * If the minimum values are normally displayed fx. at the bottom setting + * axis inversion to true, will cause the minimum values to be displayed at + * the top and maximum at the bottom. + * + * @param bool $invert True if the axis is to be inverted, false if not + * @since 0.3.0dev3 + */ + function setInverted($invert) + { + $this->_invert = $invert; + } + + /** + * Set axis intersection. + * + * Sets the value at which the axis intersects other axis, fx. at which Y- + * value the x-axis intersects the y-axis (normally at 0). + * + * Possible values are 'default', 'min', 'max' or a number between axis min + * and max (the value will automatically be limited to this range). + * + * For a coordinate system with 2 y-axis, the x-axis can either intersect + * the primary or the secondary y-axis. To make the x-axis intersect the + * secondary y-axis at a given value pass IMAGE_GRAPH_AXIS_Y_SECONDARY as + * second parameter. + * + * @param mixed $intersection The value at which the axis intersect the + * 'other' axis + * @param mixed $axis The axis to intersect. Only applies to x-axis with + * both a primary and secondary y-axis available. + * @since 0.3.0dev2 + */ + function setAxisIntersection($intersection, $axis = 'default') + { + if ($axis == 'x') { + $axis = IMAGE_GRAPH_AXIS_X; + } elseif ($axis == 'y') { + $axis = IMAGE_GRAPH_AXIS_Y; + } elseif ($axis == 'ysec') { + $axis = IMAGE_GRAPH_AXIS_Y_SECONDARY; + } + $this->_intersect = array( + 'value' => $intersection, + 'axis' => $axis + ); + } + + /** + * Get axis intersection data. + * + * @return array An array with the axis intersection data. + * @since 0.3.0dev2 + * @access private + */ + function _getAxisIntersection() + { + $value = $this->_intersect['value']; + $axis = $this->_intersect['axis']; + if (($this->_type == IMAGE_GRAPH_AXIS_Y) + || ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) + ) { + $axis = IMAGE_GRAPH_AXIS_X; + } elseif ($axis == 'default') { + $axis = IMAGE_GRAPH_AXIS_Y; + } + + if ($value === 'default') { + switch ($this->_type) { + case IMAGE_GRAPH_AXIS_Y: + $value = 'min'; + break; + case IMAGE_GRAPH_AXIS_Y_SECONDARY: + $value = 'max'; + break; + case IMAGE_GRAPH_AXIS_X: + $value = 0; + break; + } + } + + return array('value' => $value, 'axis' => $axis); + } + + /** + * Resets the elements + * + * @access private + */ + function _reset() + { + parent::_reset(); + $this->_labelText = array(); + } + + /** + * Output an axis tick mark. + * + * @param int $value The value to output + * @param int $level The label level to draw the tick for + * @access private + */ + function _drawTick($value, $level = 1) + { + if (isset($this->_labelOptions[$level])) { + $labelOptions = $this->_labelOptions[$level]; + $labelPosition = $this->_point($value); + + if (isset($labelOptions['offset'])) { + $offset = $labelOptions['offset']; + } else { + $offset = 0; + } + + if ((isset($labelOptions['showtext'])) && ($labelOptions['showtext'] === true)) { + if (is_object($this->_dataPreProcessor)) { + $labelText = $this->_dataPreProcessor->_process($value); + } elseif (isset($labelOptions['format'])) { + $labelText = sprintf($labelOptions['format'], $value); + } elseif (isset($labelOptions['dateformat'])) { + $labelText = date($labelOptions['dateformat'], $value); + } else { + $labelText = $value; + } + + if (!in_array($labelText, $this->_labelText)) { + $this->_labelText[] = $labelText; + + if (isset($labelOptions['font'])) { + $font = $this->_getFont($labelOptions['font']); + } else { + if ($this->_defaultFontOptions !== false) { + $font = $this->_defaultFontOptions; + } else { + $font = $this->_getFont(); + } + } + $this->_canvas->setFont($font); + + if ( + (isset($labelOptions['position'])) && + ($labelOptions['position'] == 'inside') + ) { + $labelInside = true; + } else { + $labelInside = false; + } + + if ($this->_type == IMAGE_GRAPH_AXIS_Y) { + if ($this->_transpose) { + if ($labelInside) { + $this->write( + $labelPosition, + $this->_top - 3 - $offset, + $labelText, + IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, + $font + ); + } else { + $this->write( + $labelPosition, + $this->_top + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1), + $labelText, + IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, + $font + ); + } + } + else { + if ($labelInside) { + $this->write( + $this->_right + 3 + $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, + $font + ); + } else { + $this->write( + $this->_right - 3 - $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT, + $font + ); + } + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + if ($this->_transpose) { + if ($labelInside) { + $this->write( + $labelPosition, + $this->_bottom + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1), + $labelText, + IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, + $font + ); + } else { + $this->write( + $labelPosition, + $this->_bottom - 3 - $offset, + $labelText, + IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, + $font + ); + } + } + else { + if ($labelInside) { + $this->write( + $this->_left - 3 - $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT, + $font + ); + } else { + $this->write( + $this->_left + 3 + $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, + $font + ); + } + } + } else { + if ($this->_transpose) { + if ($labelInside) { + $this->write( + $this->_right + 3 + $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, + $font + ); + } else { + $this->write( + $this->_right - 3 - $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT, + $font + ); + } + } + else { + if ($labelInside === true) { + $this->write( + $labelPosition, + $this->_top - 3 - $offset, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_BOTTOM, + $font + ); + } else { + $this->write( + $labelPosition, + $this->_top + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1), + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_BOTTOM, + $font + ); + } + } + } + } + } + + $tickColor = false; + if (isset($this->_labelOptions[$level]['tick'])) { + if (isset($this->_labelOptions[$level]['tick']['start'])) { + $tickStart = $this->_labelOptions[$level]['tick']['start']; + } else { + $tickStart = false; + } + + if (isset($this->_labelOptions[$level]['tick']['end'])) { + $tickEnd = $this->_labelOptions[$level]['tick']['end']; + } else { + $tickEnd = false; + } + + if ((isset($this->_labelOptions[$level]['tick']['color'])) && ($this->_labelOptions[$level]['tick']['color'] !== false)) { + $tickColor = $this->_labelOptions[$level]['tick']['color']; + } + } + + if ($tickStart === false) { + $tickStart = -2; + } + + if ($tickEnd === false) { + $tickEnd = 2; + } + + if ($tickColor !== false) { + $this->_canvas->setLineColor($tickColor); + } + else { + $this->_getLineStyle(); + } + + if ($this->_type == IMAGE_GRAPH_AXIS_Y) { + if ($tickStart === 'auto') { + $tickStart = -$offset; + } + if ($this->_transpose) { + $this->_canvas->line( + array( + 'x0' => $labelPosition, + 'y0' => $this->_top + $tickStart, + 'x1' => $labelPosition, + 'y1' => $this->_top + $tickEnd + ) + ); + } + else { + $this->_canvas->line( + array( + 'x0' => $this->_right + $tickStart, + 'y0' => $labelPosition, + 'x1' => $this->_right + $tickEnd, + 'y1' => $labelPosition + ) + ); + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + if ($tickStart === 'auto') { + $tickStart = $offset; + } + if ($this->_transpose) { + $this->_canvas->line( + array( + 'x0' => $labelPosition, + 'y0' => $this->_bottom - $tickStart, + 'x1' => $labelPosition, + 'y1' => $this->_bottom - $tickEnd + ) + ); + } + else { + $this->_canvas->line( + array( + 'x0' => $this->_left - $tickStart, + 'y0' => $labelPosition, + 'x1' => $this->_left - $tickEnd, + 'y1' => $labelPosition + ) + ); + } + } else { + if ($tickStart === 'auto') { + $tickStart = $offset; + } + if ($this->_transpose) { + $this->_canvas->line( + array( + 'x0' => $this->_right + $tickStart, + 'y0' => $labelPosition, + 'x1' => $this->_right + $tickEnd, + 'y1' => $labelPosition + ) + ); + } + else { + $this->_canvas->line( + array( + 'x0' => $labelPosition, + 'y0' => $this->_top - $tickStart, + 'x1' => $labelPosition, + 'y1' => $this->_top - $tickEnd + ) + ); + } + } + } + } + + /** + * Draws axis lines. + * + * @access private + */ + function _drawAxisLines() + { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + $this->_getLineStyle(); + $this->_getFillStyle(); + + if ($this->_transpose) { + $data = array( + 'x0' => $this->_right, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ); + } else { + $data = array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_top + ); + } + + if ($this->_showArrow) { + if ($this->_getMaximum() <= 0) { + $data['end0'] = 'arrow2'; + $data['size0'] = 7; + } + else { + $data['end1'] = 'arrow2'; + $data['size1'] = 7; + } + } + + $this->_canvas->line($data); + + if ($this->_title) { + if (!$this->_transpose) { + $y = $this->_bottom; + $x = $this->_left + $this->width() / 2; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont()); + } + else { + $y = $this->_top + $this->height() / 2; + $x = $this->_left; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont()); + } + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + $this->_getLineStyle(); + $this->_getFillStyle(); + + if ($this->_transpose) { + $data = array( + 'x0' => $this->_left, + 'y0' => $this->_bottom, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ); + } else { + $data = array( + 'x0' => $this->_left, + 'y0' => $this->_bottom, + 'x1' => $this->_left, + 'y1' => $this->_top + ); + } + if ($this->_showArrow) { + if ($this->_getMaximum() <= 0) { + $data['end0'] = 'arrow2'; + $data['size0'] = 7; + } + else { + $data['end1'] = 'arrow2'; + $data['size1'] = 7; + } + } + $this->_canvas->line($data); + + if ($this->_title) { + if ($this->_transpose) { + $y = $this->_top; + $x = $this->_left + $this->width() / 2; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_TOP, $this->_getTitleFont()); + } + else { + $y = $this->_top + $this->height() / 2; + $x = $this->_right; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont()); + } + } + } else { + $this->_getLineStyle(); + $this->_getFillStyle(); + + if ($this->_transpose) { + $data = array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_top + ); + } else { + $data = array( + 'x0' => $this->_right, + 'y0' => $this->_bottom, + 'x1' => $this->_right, + 'y1' => $this->_top + ); + } + if ($this->_showArrow) { + if ($this->_getMaximum() <= 0) { + $data['end0'] = 'arrow2'; + $data['size0'] = 7; + } + else { + $data['end1'] = 'arrow2'; + $data['size1'] = 7; + } + } + $this->_canvas->line($data); + + if ($this->_title) { + if ($this->_transpose) { + $y = $this->_bottom; + $x = $this->_left + $this->width() / 2; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont()); + } + else { + $y = $this->_top + $this->height() / 2; + $x = $this->_left; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont()); + } + } + } + } + + /** + * Causes the object to update all sub elements coordinates + * + * (Image_Graph_Common, does not itself have coordinates, this is basically + * an abstract method) + * + * @access private + */ + function _updateCoords() + { + parent::_updateCoords(); + $this->_calcDelta(); + } + + /** + * Output the axis + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $this->_canvas->startGroup(get_class($this)); + + if (parent::_done() === false) { + return false; + } + + $this->_drawAxisLines(); + + $this->_canvas->startGroup(get_class($this) . '_ticks'); + ksort($this->_labelOptions); + foreach ($this->_labelOptions as $level => $labelOption) { + $value = false; + while (($value = $this->_getNextLabel($value, $level)) !== false) { + if ((((abs($value) > 0.0001) || ($this->_showLabelZero)) && + (($value > $this->_getMinimum()) || ($this->_showLabelMinimum)) && + (($value < $this->_getMaximum()) || ($this->_showLabelMaximum))) && + ($value >= $this->_getMinimum()) && ($value <= $this->_getMaximum()) + ) { + $this->_drawTick($value, $level); + } + } + } + $this->_canvas->endGroup(); + + $tickStart = -3; + $tickEnd = 2; + + foreach ($this->_marks as $mark) { + if (is_array($mark)) { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + if ($this->_transpose) { + $x0 = $this->_right + $tickStart; + $y0 = $this->_point($mark[1]); + $x1 = $this->_right + $tickEnd; + $y1 = $this->_point($mark[0]); + } + else { + $x0 = $this->_point($mark[0]); + $y0 = $this->_top + $tickStart; + $x1 = $this->_point($mark[1]); + $y1 = $this->_top + $tickEnd; + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) { + if ($this->_transpose) { + $x0 = $this->_point($mark[0]); + $y0 = $this->_top + $tickStart; + $x1 = $this->_point($mark[1]); + $y1 = $this->_top + $tickEnd; + } + else { + $x0 = $this->_right + $tickStart; + $y0 = $this->_point($mark[1]); + $x1 = $this->_right + $tickEnd; + $y1 = $this->_point($mark[0]); + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + if ($this->_transpose) { + $x0 = $this->_point($mark[0]); + $y0 = $this->_bottom + $tickStart; + $x1 = $this->_point($mark[1]); + $y1 = $this->_bottom + $tickEnd; + } + else { + $x0 = $this->_left + $tickStart; + $y0 = $this->_point($mark[1]); + $x1 = $this->_left + $tickEnd; + $y1 = $this->_point($mark[0]); + } + } + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1)); + } else { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + if ($this->_transpose) { + $x0 = $this->_right + 5; + $y0 = $this->_point($mark); + $x1 = $this->_right + 15; + $y1 = $y0; + } + else { + $x0 = $this->_point($mark); + $y0 = $this->_top - 5; + $x1 = $x0; + $y1 = $this->_top - 15; + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) { + if ($this->_transpose) { + $x0 = $this->_point($mark); + $y0 = $this->_top - 5; + $x1 = $x0; + $y1 = $this->_top - 15; + } + else { + $x0 = $this->_right + 5; + $y0 = $this->_point($mark); + $x1 = $this->_right + 15; + $y1 = $y0; + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + if ($this->_transpose) { + $x0 = $this->_point($mark); + $y0 = $this->_bottom + 5; + $x1 = $x0; + $y1 = $this->_bottom + 15; + } + else { + $x0 = $this->_left - 5; + $y0 = $this->_point($mark); + $x1 = $this->_left - 15; + $y1 = $y0; + } + } + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x0, + 'y0' => $y0, + 'x1' => $x1, + 'y1' => $y1, + 'end0' => 'arrow2', + 'size0' => 5 + ) + ); + } + } + $this->_canvas->endGroup(); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Axis/Category.php b/packages/dspam/pear/Image/Graph/Axis/Category.php new file mode 100644 index 00000000..b6451496 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Axis/Category.php @@ -0,0 +1,437 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Axis.php + */ +require_once 'Image/Graph/Axis.php'; + +/** + * A normal axis thats displays labels with a 'interval' of 1. + * This is basically a normal axis where the range is + * the number of labels defined, that is the range is explicitly defined + * when constructing the axis. + * + * @category Images + * @package Image_Graph + * @subpackage Axis + * @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/package/Image_Graph + */ +class Image_Graph_Axis_Category extends Image_Graph_Axis +{ + + /** + * The labels shown on the axis + * @var array + * @access private + */ + var $_labels = false; + + /** + * Image_Graph_Axis_Category [Constructor]. + * + * @param int $type The type (direction) of the Axis + */ + function Image_Graph_Axis_Category($type = IMAGE_GRAPH_AXIS_X) + { + parent::Image_Graph_Axis($type); + $this->_labels = array(); + $this->setlabelInterval(1); + } + + /** + * Gets the minimum value the axis will show. + * + * This is always 0 + * + * @return double The minumum value + * @access private + */ + function _getMinimum() + { + return 0; + } + + /** + * Gets the maximum value the axis will show. + * + * This is always the number of labels passed to the constructor. + * + * @return double The maximum value + * @access private + */ + function _getMaximum() + { + return count($this->_labels) - 1; + } + + /** + * Sets the minimum value the axis will show. + * + * A minimum cannot be set on a SequentialAxis, it is always 0. + * + * @param double Minimum The minumum value to use on the axis + * @access private + */ + function _setMinimum($minimum) + { + } + + /** + * Sets the maximum value the axis will show + * + * A maximum cannot be set on a SequentialAxis, it is always the number + * of labels passed to the constructor. + * + * @param double Maximum The maximum value to use on the axis + * @access private + */ + function _setMaximum($maximum) + { + } + + /** + * Forces the minimum value of the axis + * + * A minimum cannot be set on this type of axis + * + * To modify the labels which are displayed on the axis, instead use + * setLabelInterval($labels) where $labels is an array containing the + * values/labels the axis should display. Note! Only values in + * this array will then be displayed on the graph! + * + * @param double $minimum A minimum cannot be set on this type of axis + */ + function forceMinimum($minimum, $userEnforce = true) + { + } + + /** + * Forces the maximum value of the axis + * + * A maximum cannot be set on this type of axis + * + * To modify the labels which are displayed on the axis, instead use + * setLabelInterval($labels) where $labels is an array containing the + * values/labels the axis should display. Note! Only values in + * this array will then be displayed on the graph! + * + * @param double $maximum A maximum cannot be set on this type of axis + */ + function forceMaximum($maximum, $userEnforce = true) + { + } + + /** + * Sets an interval for where labels are shown on the axis. + * + * The label interval is rounded to nearest integer value. + * + * @param double $labelInterval The interval with which labels are shown + */ + function setLabelInterval($labelInterval = 'auto', $level = 1) + { + if (is_array($labelInterval)) { + parent::setLabelInterval($labelInterval); + } elseif ($labelInterval == 'auto') { + parent::setLabelInterval(1); + } else { + parent::setLabelInterval(round($labelInterval)); + } + } + + /** + * Preprocessor for values, ie for using logarithmic axis + * + * @param double $value The value to preprocess + * @return double The preprocessed value + * @access private + */ + function _value($value) + { +// $the_value = array_search($value, $this->_labels); + if (isset($this->_labels[$value])) { + $the_value = $this->_labels[$value]; + if ($the_value !== false) { + return $the_value + ($this->_pushValues ? 0.5 : 0); + } else { + return 0; + } + } + } + + + /** + * Get the minor label interval with which axis label ticks are drawn. + * + * For a sequential axis this is always disabled (i.e false) + * + * @return double The minor label interval, always false + * @access private + */ + function _minorLabelInterval() + { + return false; + } + + /** + * Get the size in pixels of the axis. + * + * For an x-axis this is the width of the axis including labels, and for an + * y-axis it is the corrresponding height + * + * @return int The size of the axis + * @access private + */ + function _size() + { + if (!$this->_visible) { + return 0; + } + + $this->_canvas->setFont($this->_getFont()); + + $maxSize = 0; + foreach($this->_labels as $label => $id) { + $labelPosition = $this->_point($label); + + if (is_object($this->_dataPreProcessor)) { + $labelText = $this->_dataPreProcessor->_process($label); + } else { + $labelText = $label; + } + + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + $maxSize = max($maxSize, $this->_canvas->textHeight($labelText)); + } else { + $maxSize = max($maxSize, $this->_canvas->textWidth($labelText)); + } + } + + if ($this->_title) { + $this->_canvas->setFont($this->_getTitleFont()); + + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + $maxSize += $this->_canvas->textHeight($this->_title); + } else { + $maxSize += $this->_canvas->textWidth($this->_title); + } + $maxSize += 10; + } + return $maxSize +3; + } + + /** + * Apply the dataset to the axis. + * + * This calculates the order of the categories, which is very important + * for fx. line plots, so that the line does not "go backwards", consider + * these X-sets:

+ * 1: (1, 2, 3, 4, 5, 6)
+ * 2: (0, 1, 2, 3, 4, 5, 6, 7)

+ * If they are not ordered, but simply appended, the categories on the axis + * would be:

+ * X: (1, 2, 3, 4, 5, 6, 0, 7)

+ * Which would render the a line for the second plot to show incorrectly. + * Instead this algorithm, uses and 'value- is- before' method to see that + * the 0 is before a 1 in the second set, and that it should also be before + * a 1 in the X set. Hence:

+ * X: (0, 1, 2, 3, 4, 5, 6, 7) + * + * @param Image_Graph_Dataset $dataset The dataset + * @access private + */ + function _applyDataset(&$dataset) + { + $newLabels = array(); + $allLabels = array(); + + $dataset->_reset(); + $count = 0; + $count_new = 0; + while ($point = $dataset->_next()) { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + $data = $point['X']; + } else { + $data = $point['Y']; + } + if (!isset($this->_labels[$data])) { + $newLabels[$data] = $count_new++; + //$this->_labels[] = $data; + } + $allLabels[$data] = $count++; + } + + if (count($this->_labels) == 0) { + $this->_labels = $newLabels; + } elseif ((is_array($newLabels)) && (count($newLabels) > 0)) { + // get all intersecting labels + $intersect = array_intersect(array_keys($allLabels), array_keys($this->_labels)); + // traverse all new and find their relative position withing the + // intersec, fx value X0 is before X1 in the intersection, which + // means that X0 should be placed before X1 in the label array + foreach($newLabels as $newLabel => $id) { + $key = $allLabels[$newLabel]; + reset($intersect); + $this_value = false; + // intersect indexes are the same as in allLabels! + $first = true; + while ((list($id, $value) = each($intersect)) && + ($this_value === false)) + { + if (($first) && ($id > $key)) { + $this_value = $value; + } elseif ($id >= $key) { + $this_value = $value; + } + $first = false; + } + + if ($this_value === false) { + // the new label was not found before anything in the + // intersection -> append it + $this->_labels[$newLabel] = count($this->_labels); + } else { + // the new label was found before $this_value in the + // intersection, insert the label before this position in + // the label array +// $key = $this->_labels[$this_value]; + $keys = array_keys($this->_labels); + $key = array_search($this_value, $keys); + $pre = array_slice($keys, 0, $key); + $pre[] = $newLabel; + $post = array_slice($keys, $key); + $this->_labels = array_flip(array_merge($pre, $post)); + } + } + unset($keys); + } + + $labels = array_keys($this->_labels); + $i = 0; + foreach ($labels as $label) { + $this->_labels[$label] = $i++; + } + +// $this->_labels = array_values(array_unique($this->_labels)); + $this->_calcLabelInterval(); + } + + /** + * Return the label distance. + * + * @return int The distance between 2 adjacent labels + * @access private + */ + function _labelDistance($level = 1) + { + reset($this->_labels); + list($l1) = each($this->_labels); + list($l2) = each($this->_labels); + return abs($this->_point($l2) - $this->_point($l1)); + } + + /** + * Get next label point + * + * @param doubt $point The current point, if omitted or false, the first is + * returned + * @return double The next label point + * @access private + */ + function _getNextLabel($currentLabel = false, $level = 1) + { + if ($currentLabel === false) { + reset($this->_labels); + } + $result = false; + $count = ($currentLabel === false ? $this->_labelInterval() - 1 : 0); + while ($count < $this->_labelInterval()) { + $result = (list($label) = each($this->_labels)); + $count++; + } + if ($result) { + return $label; + } else { + return false; + } + } + + /** + * Is the axis numeric or not? + * + * @return bool True if numeric, false if not + * @access private + */ + function _isNumeric() + { + return false; + } + + /** + * Output the axis + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $result = true; + if (Image_Graph_Element::_done() === false) { + $result = false; + } + + $this->_canvas->startGroup(get_class($this)); + + $this->_drawAxisLines(); + + $this->_canvas->startGroup(get_class($this) . '_ticks'); + $label = false; + while (($label = $this->_getNextLabel($label)) !== false) { + $this->_drawTick($label); + } + $this->_canvas->endGroup(); + + $this->_canvas->endGroup(); + + return $result; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Axis/Logarithmic.php b/packages/dspam/pear/Image/Graph/Axis/Logarithmic.php new file mode 100644 index 00000000..2675ee4c --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Axis/Logarithmic.php @@ -0,0 +1,152 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Axis.php + */ +require_once 'Image/Graph/Axis.php'; + +/** + * Diplays a logarithmic axis (either X- or Y-axis). + * + * @category Images + * @package Image_Graph + * @subpackage Axis + * @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/package/Image_Graph + */ +class Image_Graph_Axis_Logarithmic extends Image_Graph_Axis +{ + + /** + * Image_Graph_AxisLogarithmic [Constructor]. + * + * Normally a manual creation should not be necessary, axis are + * created automatically by the {@link Image_Graph_Plotarea} constructor + * unless explicitly defined otherwise + * + * @param int $type The type (direction) of the Axis, use IMAGE_GRAPH_AXIS_X + * for an X-axis (default, may be omitted) and IMAGE_GRAPH_AXIS_Y for Y- + * axis) + */ + function Image_Graph_Axis_Logarithmic($type = IMAGE_GRAPH_AXIS_X) + { + parent::Image_Graph_Axis($type); + $this->showLabel(IMAGE_GRAPH_LABEL_MINIMUM + IMAGE_GRAPH_LABEL_MAXIMUM); + $this->_minimum = 1; + $this->_minimumSet = true; + } + + /** + * Calculate the label interval + * + * If explicitly defined this will be calucated to an approximate best. + * + * @return double The label interval + * @access private + */ + function _calcLabelInterval() + { + $result = parent::_calcLabelInterval(); + $this->_axisValueSpan = $this->_value($this->_axisSpan); + return $result; + } + + /** + * Preprocessor for values, ie for using logarithmic axis + * + * @param double $value The value to preprocess + * @return double The preprocessed value + * @access private + */ + function _value($value) + { + return log10($value) - log10($this->_minimum); + } + + /** + * Get next label point + * + * @param doubt $point The current point, if omitted or false, the first is + * returned + * @return double The next label point + * @access private + */ + function _getNextLabel($currentLabel = false, $level = 1) + { + if (is_array($this->_labelOptions[$level]['interval'])) { + return parent::_getNextLabel($currentLabel, $level); + } + + if ($currentLabel !== false) { + $value = log10($currentLabel); + $base = floor($value); + $frac = $value - $base; + for ($i = 2; $i < 10; $i++) { + if ($frac <= (log10($i)-0.01)) { + $label = pow(10, $base)*$i; + if ($label > $this->_getMaximum()) { + return false; + } else { + return $label; + } + } + } + return pow(10, $base+1); + } + + return max(1, $this->_minimum); + } + + /** + * Get the axis intersection pixel position + * + * This is only to be called prior to output! I.e. between the user + * invokation of Image_Graph::done() and any actual output is performed. + * This is because it can change the axis range. + * + * @param double $value the intersection value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _intersectPoint($value) + { + if (($value <= 0) && ($value !== 'max') && ($value !== 'min')) { + $value = 1; + } + return parent::_intersectPoint($value); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Axis/Marker/Area.php b/packages/dspam/pear/Image/Graph/Axis/Marker/Area.php new file mode 100644 index 00000000..1931ab48 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Axis/Marker/Area.php @@ -0,0 +1,156 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display a grid + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @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/package/Image_Graph + */ +class Image_Graph_Axis_Marker_Area extends Image_Graph_Grid +{ + + /** + * The lower bound + * @var double + * @access private + */ + var $_lower = false; + + /** + * The upper bound + * @var double + * @access private + */ + var $_upper = false; + + /** + * [Constructor] + */ + function Image_Graph_Axis_Marker_Area() + { + parent::Image_Graph_Grid(); + $this->_lineStyle = false; + } + + /** + * Sets the lower bound of the area (value on the axis) + * + * @param double $lower the lower bound + */ + function setLowerBound($lower) + { + $this->_lower = $lower; + } + + /** + * Sets the upper bound of the area (value on the axis) + * + * @param double $upper the upper bound + */ + function setUpperBound($upper) + { + $this->_upper = $upper; + } + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $i = 0; + + $this->_lower = max($this->_primaryAxis->_getMinimum(), $this->_lower); + $this->_upper = min($this->_primaryAxis->_getMaximum(), $this->_upper); + + $secondaryPoints = $this->_getSecondaryAxisPoints(); + + reset($secondaryPoints); + list ($id, $previousSecondaryValue) = each($secondaryPoints); + while (list ($id, $secondaryValue) = each($secondaryPoints)) { + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) { + $p1 = array ('Y' => $secondaryValue, 'X' => $this->_lower); + $p2 = array ('Y' => $previousSecondaryValue, 'X' => $this->_lower); + $p3 = array ('Y' => $previousSecondaryValue, 'X' => $this->_upper); + $p4 = array ('Y' => $secondaryValue, 'X' => $this->_upper); + } else { + $p1 = array ('X' => $secondaryValue, 'Y' => $this->_lower); + $p2 = array ('X' => $previousSecondaryValue, 'Y' => $this->_lower); + $p3 = array ('X' => $previousSecondaryValue, 'Y' => $this->_upper); + $p4 = array ('X' => $secondaryValue, 'Y' => $this->_upper); + } + + $this->_canvas->addVertex(array('x' => $this->_pointX($p1), 'y' => $this->_pointY($p1))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p2), 'y' => $this->_pointY($p2))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p3), 'y' => $this->_pointY($p3))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p4), 'y' => $this->_pointY($p4))); + + $previousSecondaryValue = $secondaryValue; + + $this->_getLineStyle(); + $this->_getFillStyle(); + $this->_canvas->polygon(array('connect' => true)); + } + + $this->_canvas->endGroup(); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Axis/Marker/Line.php b/packages/dspam/pear/Image/Graph/Axis/Marker/Line.php new file mode 100644 index 00000000..0c46c144 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Axis/Marker/Line.php @@ -0,0 +1,124 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display a grid + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @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/package/Image_Graph + */ +class Image_Graph_Axis_Marker_Line extends Image_Graph_Grid +{ + + /** + * The value + * @var double + * @access private + */ + var $_value = false; + + /** + * Sets the value of the line marker (value on the axis) + * + * @param double $value the value + */ + function setValue($value) + { + $this->_value = $value; + } + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $i = 0; + + $this->_value = min($this->_primaryAxis->_getMaximum(), max($this->_primaryAxis->_getMinimum(), $this->_value)); + + $secondaryPoints = $this->_getSecondaryAxisPoints(); + + reset($secondaryPoints); + list ($id, $previousSecondaryValue) = each($secondaryPoints); + while (list ($id, $secondaryValue) = each($secondaryPoints)) { + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) { + $p1 = array ('X' => $this->_value, 'Y' => $secondaryValue); + $p2 = array ('X' => $this->_value, 'Y' => $previousSecondaryValue); + } else { + $p1 = array ('X' => $secondaryValue, 'Y' => $this->_value); + $p2 = array ('X' => $previousSecondaryValue, 'Y' => $this->_value); + } + + $x1 = $this->_pointX($p1); + $y1 = $this->_pointY($p1); + $x2 = $this->_pointX($p2); + $y2 = $this->_pointY($p2); + + $previousSecondaryValue = $secondaryValue; + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x1, 'y0' => $y1, 'x1' => $x2, 'y1' => $y2)); + } + + $this->_canvas->endGroup(); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Axis/Radar.php b/packages/dspam/pear/Image/Graph/Axis/Radar.php new file mode 100644 index 00000000..7348254c --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Axis/Radar.php @@ -0,0 +1,204 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Axis/Category.php + */ +require_once 'Image/Graph/Axis/Category.php'; + +/** + * Displays an 'X'-axis in a radar plot chart. + * + * This axis maps the number of elements in the dataset to a angle (from 0- + * 360 degrees). Displaying the axis consist of drawing a number of lines from + * center to the edge of the 'circle' than encloses the radar plot. The labels + * are drawn on the 'ends' of these radial lines. + * + * @category Images + * @package Image_Graph + * @subpackage Axis + * @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/package/Image_Graph + */ +class Image_Graph_Axis_Radar extends Image_Graph_Axis_Category +{ + + /** + * Specifies the number of pixels, the labels is offsetted from the end of + * the axis + * + * @var int + * @access private + */ + var $_distanceFromEnd = 5; + + /** + * Gets the minimum value the axis will show. + * + * This is always 0 + * + * @return double The minumum value + * @access private + */ + function _getMinimum() + { + return 0; + } + + /** + * Gets the maximum value the axis will show. + * + * This is always the number of labels passed to the constructor. + * + * @return double The maximum value + * @access private + */ + function _getMaximum() + { + return count($this->_labels); + } + + /** + * Calculate the delta value (the number of pixels representing one unit + * on the axis) + * + * @return double The label interval + * @access private + */ + function _calcDelta() + { + if (abs($this->_getMaximum() - $this->_getMinimum()) == 0) { + $this->_delta = false; + } else { + $this->_delta = 360 / ($this->_getMaximum() - $this->_getMinimum()); + } + } + + /** + * Get the pixel position represented by a value on the canvas + * + * @param double $value the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _point($value) + { + return (90 + (int) ($this->_value($value) * $this->_delta)) % 360; + } + + /** + * Get the size in pixels of the axis. + * + * For a radar plot this is always 0 + * + * @return int The size of the axis + * @access private + */ + function _size() + { + return 0; + } + + /** + * Sets the distance from the end of the category lines to the label. + * + * @param int $distance The distance in pixels + */ + function setDistanceFromEnd($distance = 5) + { + $this->_distanceFromEnd = $distance; + } + + /** + * Draws axis lines. + * + * @access private + */ + function _drawAxisLines() + { + } + + /** + * Output an axis tick mark. + * + * @param int $value The value to output + * @access private + */ + function _drawTick($value, $level = 1) + { + $centerX = (int) (($this->_left + $this->_right) / 2); + $centerY = (int) (($this->_top + $this->_bottom) / 2); + + $radius = min($this->height(), $this->width()) / 2; + + $endPoint = array ('X' => $value, 'Y' => '#max#'); + $dX = $this->_pointX($endPoint); + $dY = $this->_pointY($endPoint); + + $offX = ($dX - $centerX); + $offY = ($dY - $centerY); + + $hyp = sqrt($offX*$offX + $offY*$offY); + if ($hyp != 0) { + $scale = $this->_distanceFromEnd / $hyp; + } else { + $scale = 1; + } + + $adX = $dX + $offX * $scale; + $adY = $dY + $offY * $scale; + + if (is_object($this->_dataPreProcessor)) { + $labelText = $this->_dataPreProcessor->_process($value); + } else { + $labelText = $value; + } + + if ((abs($dX - $centerX) < 1.5) && ($dY < $centerY)) { + $align = IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_CENTER_X; + } elseif ((abs($dX - $centerX) < 1.5) && ($dY > $centerY)) { + $align = IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_CENTER_X; + } elseif ($dX < $centerX) { + $align = IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_CENTER_Y; + } else { + $align = IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y; + } + $this->write($adX, $adY, $labelText, $align); + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $centerX, 'y0' => $centerY, 'x1' => $dX, 'y1' => $dY)); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Common.php b/packages/dspam/pear/Image/Graph/Common.php new file mode 100644 index 00000000..f695cb58 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Common.php @@ -0,0 +1,313 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +if (!function_exists('is_a')) { + + /** + * Check if an object is of a given class, this function is available as of PHP 4.2.0, so if it exist it will not be declared + * + * @link http://www.php.net/manual/en/function.is-a.php PHP.net Online Manual for function is_a() + * @param object $object The object to check class for + * @param string $class_name The name of the class to check the object for + * @return bool Returns TRUE if the object is of this class or has this class as one of its parents + */ + function is_a($object, $class_name) + { + if (empty ($object)) { + return false; + } + $object = is_object($object) ? get_class($object) : $object; + if (strtolower($object) == strtolower($class_name)) { + return true; + } + return is_a(get_parent_class($object), $class_name); + } +} + +/** + * Include file Image/Canvas.php + */ +require_once 'Image/Canvas.php'; + +/** + * The ultimate ancestor of all Image_Graph classes. + * + * This class contains common functionality needed by all Image_Graph classes. + * + * @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: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Common +{ + + /** + * The parent container of the current Image_Graph object + * + * @var Image_Graph_Common + * @access private + */ + var $_parent = null; + + /** + * The sub-elements of the current Image_Graph container object + * + * @var array + * @access private + */ + var $_elements; + + /** + * The canvas for output. + * + * Enables support for multiple output formats. + * + * @var Image_Canvas + * @access private + */ + var $_canvas = null; + + /** + * Is the object visible? + * + * @var bool + * @access private + */ + var $_visible = true; + + /** + * Constructor [Image_Graph_Common] + */ + function Image_Graph_Common() + { + } + + /** + * Resets the elements + * + * @access private + */ + function _reset() + { + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + if (is_object($this->_elements[$key])) { + $this->_elements[$key]->_setParent($this); + $result =& $this->_elements[$key]->_reset(); + if (PEAR::isError($result)) { + return $result; + } + } + } + unset($keys); + } + return true; + } + + /** + * Sets the parent. The parent chain should ultimately be a GraPHP object + * + * @see Image_Graph_Common + * @param Image_Graph_Common $parent The parent + * @access private + */ + function _setParent(& $parent) + { + $this->_parent =& $parent; + $this->_canvas =& $this->_parent->_getCanvas(); + + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + if (is_object($this->_elements[$key])) { + $this->_elements[$key]->_setParent($this); + } + } + unset($keys); + } + } + + /** + * Hide the element + */ + function hide() + { + $this->_visible = false; + } + + /** + * Get the canvas + * + * @return Image_Canvas The canvas + * @access private + */ + function &_getCanvas() + { + if (($this->_canvas !== null) || ($this->_canvas !== false)) { + return $this->_canvas; + } elseif (is_a($this->_parent, 'Image_Graph_Common')) { + $this->_canvas =& $this->_parent->_getCanvas(); + return $this->_canvas; + } else { + $this->_error('Invalid canvas'); + $result = null; + return $result; + } + } + + /** + * Adds an element to the objects element list. + * + * The new Image_Graph_elements parent is automatically set. + * + * @param Image_Graph_Common $element The new Image_Graph_element + * @return Image_Graph_Common The new Image_Graph_element + */ + function &add(& $element) + { + if (!is_a($element, 'Image_Graph_Font')) { + $this->_elements[] = &$element; + } + $element->_setParent($this); + return $element; + } + + /** + * Creates an object from the class and adds it to the objects element list. + * + * Creates an object from the class specified and adds it to the objects + * element list. 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. + * + * @see Image_Graph::factory() + * @param string $class The class for the object + * @param mixed $params The paramaters to pass to the constructor + * @return Image_Graph_Common The new Image_Graph_element + */ + function &addNew($class, $params = null, $additional = false) + { + include_once 'Image/Graph.php'; + $element =& Image_Graph::factory($class, $params); + if ($additional === false) { + $obj =& $this->add($element); + } else { + $obj =& $this->add($element, $additional); + } + return $obj; + } + + /** + * Shows an error message box on the canvas + * + * @param string $text The error text + * @param array $params An array containing error specific details + * @param int $error_code Error code + * @access private + */ + function _error($text, $params = false, $error_code = IMAGE_GRAPH_ERROR_GENERIC) + { + if ((is_array($params)) && (count($params) > 0)) { + foreach ($params as $name => $key) { + if (isset($parameters)) { + $parameters .= ' '; + } + else { + $parameters = ''; + } + $parameters .= $name . '=' . $key; + } + } + $error =& PEAR::raiseError( + $text . + ($error_code != IMAGE_GRAPH_ERROR_GENERIC ? ' error:' . IMAGE_GRAPH_ERROR_GENERIC : '') . + (isset($parameters) ? ' parameters:[' . $parameters . ']' : '') + ); + } + + /** + * Causes the object to update all sub elements coordinates + * + * (Image_Graph_Common, does not itself have coordinates, this is basically + * an abstract method) + * + * @access private + */ + function _updateCoords() + { + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + if (is_object($this->_elements[$key])) { + $this->_elements[$key]->_updateCoords(); + } + } + unset($keys); + } + return true; + } + + /** + * Causes output to canvas + * + * The last method to call. Calling Done causes output to the canvas. All + * sub elements done() method will be invoked + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (($this->_canvas == null) || (!is_a($this->_canvas, 'Image_Canvas'))) { + return false; + } + + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + if (($this->_elements[$key]->_visible) && ($this->_elements[$key]->_done() === false)) { + return false; + } + } + unset($keys); + } + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Config.php b/packages/dspam/pear/Image/Graph/Config.php new file mode 100644 index 00000000..ece8a91b --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Config.php @@ -0,0 +1,30 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Constants.php b/packages/dspam/pear/Image/Graph/Constants.php new file mode 100644 index 00000000..f03674ba --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Constants.php @@ -0,0 +1,225 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Font.php + */ +require_once 'Image/Graph/Font.php'; + +// Constant declarations + +/** + * Defines an X (horizontal) axis + */ +define('IMAGE_GRAPH_AXIS_X', 1); + +/** + * Defines an Y (vertical) axis + */ +define('IMAGE_GRAPH_AXIS_Y', 2); + +/** + * Defines an Y (vertical) axis + */ +define('IMAGE_GRAPH_AXIS_Y_SECONDARY', 3); + +/** + * Defines an horizontal (X) axis + */ +define('IMAGE_GRAPH_AXIS_HORIZONTAL', 1); + +/** + * Defines an vertical (Y) axis + */ +define('IMAGE_GRAPH_AXIS_VERTICAL', 2); + +/** + * Define if label should be shown for axis minimum value + */ +define('IMAGE_GRAPH_LABEL_MINIMUM', 1); + +/** + * Define if label should be shown for axis 0 (zero) value + */ +define('IMAGE_GRAPH_LABEL_ZERO', 2); + +/** + * Define if label should be shown for axis maximum value + */ +define('IMAGE_GRAPH_LABEL_MAXIMUM', 4); + +/** + * Defines a horizontal gradient fill + */ +define('IMAGE_GRAPH_GRAD_HORIZONTAL', 1); + +/** + * Defines a vertical gradient fill + */ +define('IMAGE_GRAPH_GRAD_VERTICAL', 2); + +/** + * Defines a horizontally mirrored gradient fill + */ +define('IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED', 3); + +/** + * Defines a vertically mirrored gradient fill + */ +define('IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED', 4); + +/** + * Defines a diagonal gradient fill from top-left to bottom-right + */ +define('IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR', 5); + +/** + * Defines a diagonal gradient fill from bottom-left to top-right + */ +define('IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR', 6); + +/** + * Defines a radial gradient fill + */ +define('IMAGE_GRAPH_GRAD_RADIAL', 7); + +/** + * Defines the default builtin font + */ +define('IMAGE_GRAPH_FONT', 1); + +/** + * Defines a X value should be used + */ +define('IMAGE_GRAPH_VALUE_X', 0); + +/** + * Defines a Y value should be used + */ +define('IMAGE_GRAPH_VALUE_Y', 1); + +/** + * Defines a min X% value should be used + */ +define('IMAGE_GRAPH_PCT_X_MIN', 2); + +/** + * Defines a max X% value should be used + */ +define('IMAGE_GRAPH_PCT_X_MAX', 3); + +/** + * Defines a min Y% value should be used + */ +define('IMAGE_GRAPH_PCT_Y_MIN', 4); + +/** + * Defines a max Y% value should be used + */ +define('IMAGE_GRAPH_PCT_Y_MAX', 5); + +/** + * Defines a total Y% value should be used + */ +define('IMAGE_GRAPH_PCT_Y_TOTAL', 6); + +/** + * Defines a ID value should be used + */ +define('IMAGE_GRAPH_POINT_ID', 7); + +/** + * Align text left + */ +define('IMAGE_GRAPH_ALIGN_LEFT', 0x1); + +/** + * Align text right + */ +define('IMAGE_GRAPH_ALIGN_RIGHT', 0x2); + +/** + * Align text center x (horizontal) + */ +define('IMAGE_GRAPH_ALIGN_CENTER_X', 0x4); + +/** + * Align text top + */ +define('IMAGE_GRAPH_ALIGN_TOP', 0x8); + +/** + * Align text bottom + */ +define('IMAGE_GRAPH_ALIGN_BOTTOM', 0x10); + +/** + * Align text center y (vertical) + */ +define('IMAGE_GRAPH_ALIGN_CENTER_Y', 0x20); + +/** + * Align text center (both x and y) + */ +define('IMAGE_GRAPH_ALIGN_CENTER', IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_CENTER_Y); + +/** + * Align text top left + */ +define('IMAGE_GRAPH_ALIGN_TOP_LEFT', IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_LEFT); + +/** + * Align text top right + */ +define('IMAGE_GRAPH_ALIGN_TOP_RIGHT', IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_RIGHT); + +/** + * Align text bottom left + */ +define('IMAGE_GRAPH_ALIGN_BOTTOM_LEFT', IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_LEFT); + +/** + * Align text bottom right + */ +define('IMAGE_GRAPH_ALIGN_BOTTOM_RIGHT', IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_RIGHT); + +/** + * Align vertical + */ +define('IMAGE_GRAPH_ALIGN_VERTICAL', IMAGE_GRAPH_ALIGN_TOP); + +/** + * Align horizontal + */ +define('IMAGE_GRAPH_ALIGN_HORIZONTAL', IMAGE_GRAPH_ALIGN_LEFT); + +// Error codes +define('IMAGE_GRAPH_ERROR_GENERIC', 0); + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataPreprocessor.php b/packages/dspam/pear/Image/Graph/DataPreprocessor.php new file mode 100644 index 00000000..f135d539 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataPreprocessor.php @@ -0,0 +1,74 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Data preprocessor used for preformatting a data. + * + * A data preprocessor is used in cases where a value from a dataset or label must be + * displayed in another format or way than entered. This could for example be the need + * to display X-values as a date instead of 1, 2, 3, .. or even worse unix-timestamps. + * It could also be when a {@link Image_Graph_Marker_Value} needs to display values as percentages + * with 1 decimal digit instead of the default formatting (fx. 12.01271 -> 12.0%). + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @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/package/Image_Graph + * @abstract + */ +class Image_Graph_DataPreprocessor +{ + + /** + * Image_Graph_DataPreprocessor [Constructor]. + */ + function Image_Graph_DataPreprocessor() + { + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + return $value; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataPreprocessor/Array.php b/packages/dspam/pear/Image/Graph/DataPreprocessor/Array.php new file mode 100644 index 00000000..08e62378 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataPreprocessor/Array.php @@ -0,0 +1,103 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Format data as looked up in an array. + * + * ArrayData is useful when a numercal value is to be translated to + * something thats cannot directly be calculated from this value, this could for + * example be a dataset meant to plot population of various countries. Since x- + * values are numerical and they should really be country names, but there is no + * linear correlation between the number and the name, we use an array to 'map' + * the numbers to the name, i.e. $array[0] = 'Denmark'; $array[1] = 'Sweden'; + * ..., where the indexes are the numerical values from the dataset. This is NOT + * usefull when the x-values are a large domain, i.e. to map unix timestamps to + * date-strings for an x-axis. This is because the x-axis will selecte arbitrary + * values for labels, which would in principle require the ArrayData to hold + * values for every unix timestamp. However ArrayData can still be used to solve + * such a situation, since one can use another value for X-data in the dataset + * and then map this (smaller domain) value to a date. That is we for example + * instead of using the unix-timestamp we use value 0 to represent the 1st date, + * 1 to represent the next date, etc. + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @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/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Array extends Image_Graph_DataPreprocessor +{ + + /** + * The data label array + * @var array + * @access private + */ + var $_dataArray; + + /** + * Image_Graph_ArrayData [Constructor]. + * + * @param array $array The array to use as a lookup table + */ + function Image_Graph_DataPreprocessor_Array($array) + { + parent::Image_Graph_DataPreprocessor(); + $this->_dataArray = $array; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + if ((is_array($this->_dataArray)) && (isset ($this->_dataArray[$value]))) { + return $this->_dataArray[$value]; + } else { + return $value; + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataPreprocessor/Currency.php b/packages/dspam/pear/Image/Graph/DataPreprocessor/Currency.php new file mode 100644 index 00000000..2d3b5e2f --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataPreprocessor/Currency.php @@ -0,0 +1,66 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor/Formatted.php + */ +require_once 'Image/Graph/DataPreprocessor/Formatted.php'; + +/** + * Format data as a currency. + * + * Uses the {@link Image_Graph_DataPreprocessor_Formatted} to represent the + * values as a currency, i.e. 10 => € 10.00 + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @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/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Currency extends Image_Graph_DataPreprocessor_Formatted +{ + + /** + * Image_Graph_CurrencyData [Constructor]. + * + * @param string $currencySymbol The symbol representing the currency + */ + function Image_Graph_DataPreprocessor_Currency($currencySymbol) + { + parent::Image_Graph_DataPreprocessor_Formatted("$currencySymbol %0.2f"); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataPreprocessor/Date.php b/packages/dspam/pear/Image/Graph/DataPreprocessor/Date.php new file mode 100644 index 00000000..74695264 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataPreprocessor/Date.php @@ -0,0 +1,90 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Formats Unix timestamp as a date using specified format. + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @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/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Date extends Image_Graph_DataPreprocessor +{ + + /** + * The format of the Unix time stamp. + * See PHP + * Manual for a description + * @var string + * @access private + */ + var $_format; + + /** + * Create a DateData preprocessor [Constructor] + * + * @param string $format See {@link http://www.php.net/manual/en/function.date.php + * PHP Manual} for a description + */ + function Image_Graph_DataPreprocessor_Date($format) + { + parent::Image_Graph_DataPreprocessor(); + $this->_format = $format; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + if (!$value) { + return false; + } else { + return date($this->_format, $value); + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataPreprocessor/Formatted.php b/packages/dspam/pear/Image/Graph/DataPreprocessor/Formatted.php new file mode 100644 index 00000000..ff7335a0 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataPreprocessor/Formatted.php @@ -0,0 +1,90 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Format data using a (s)printf pattern. + * + * This method is useful when data must displayed using a simple (s) printf + * pattern as described in the {@link http://www.php. net/manual/en/function. + * sprintf.php PHP manual} + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @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/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Formatted extends Image_Graph_DataPreprocessor +{ + + /** + * A (s)printf format string. + * See {@link http://www.php.net/manual/en/function.sprintf.php PHP Manual} + * for a description + * @var string + * @access private + */ + var $_format; + + /** + * Create a (s)printf format data preprocessor + * + * @param string $format See {@link http://www.php.net/manual/en/function.sprintf.php + * PHP Manual} for a description + */ + function Image_Graph_DataPreprocessor_Formatted($format) + { + parent::Image_Graph_DataPreprocessor(); + $this->_format = $format; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + return sprintf($this->_format, $value); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataPreprocessor/Function.php b/packages/dspam/pear/Image/Graph/DataPreprocessor/Function.php new file mode 100644 index 00000000..b23a718d --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataPreprocessor/Function.php @@ -0,0 +1,92 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Formatting a value using a userdefined function. + * + * Use this method to convert/format a value to a 'displayable' lable using a (perhaps) + * more complex function. An example could be (not very applicable though) if one would + * need for values to be displayed on the reverse order, i.e. 1234 would be displayed as + * 4321, then this method can solve this by creating the function that converts the value + * and use the FunctionData datapreprocessor to make Image_Graph use this function. + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @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/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Function extends Image_Graph_DataPreprocessor +{ + + /** + * The name of the PHP function + * @var string + * @access private + */ + var $_dataFunction; + + /** + * Create a FunctionData preprocessor + * + * @param string $function The name of the PHP function to use as + * a preprocessor, this function must take a single parameter and return a + * formatted version of this parameter + */ + function Image_Graph_DataPreprocessor_Function($function) + { + parent::Image_Graph_DataPreprocessor(); + $this->_dataFunction = $function; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + $function = $this->_dataFunction; + return call_user_func($function, $value); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataPreprocessor/NumberText.php b/packages/dspam/pear/Image/Graph/DataPreprocessor/NumberText.php new file mode 100644 index 00000000..a7d6874e --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataPreprocessor/NumberText.php @@ -0,0 +1,89 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Formatting a number as its written in languages supported by Numbers_Words. + * + * Used to display values as text, i.e. 123 is displayed as one hundred and twenty three. + * Requires Numbers_Words + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @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/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_NumberText extends Image_Graph_DataPreprocessor +{ + + /** + * The language identifier + * @var string + * @access private + */ + var $_language; + + /** + * Image_Graph_NumberText [Constructor]. + * + * Supported languages see {@link http://pear.php.net/package/Numbers_Words Numbers_Words} + * + * @param string $langugage The language identifier for the language. + */ + function Image_Graph_DataPreprocessor_NumberText($language = 'en_US') + { + parent::Image_Graph_DataPreprocessor(); + $this->_language = $language; + require_once 'Numbers/Words.php'; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + return Numbers_Words::toWords($value, $this->_language); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataPreprocessor/RomanNumerals.php b/packages/dspam/pear/Image/Graph/DataPreprocessor/RomanNumerals.php new file mode 100644 index 00000000..0bfcdb62 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataPreprocessor/RomanNumerals.php @@ -0,0 +1,79 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Formatting a value as a roman numerals. + * + * Values are formatted as roman numeral, i.e. 1 = I, 2 = II, 9 = IX, 2004 = MMIV. + * Requires Numbers_Roman + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @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/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_RomanNumerals extends Image_Graph_DataPreprocessor +{ + + /** + * Create a RomanNumerals preprocessor + * + * See {@link http://pear.php.net/package/Numbers_Roman Numbers_Roman} + */ + function Image_Graph_DataPreprocessor_RomanNumerals() + { + parent::Image_Graph_DataPreprocessor(); + include_once 'Numbers/Roman.php'; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + return Numbers_Roman::toNumeral($value); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataPreprocessor/Sequential.php b/packages/dspam/pear/Image/Graph/DataPreprocessor/Sequential.php new file mode 100644 index 00000000..248f0be9 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataPreprocessor/Sequential.php @@ -0,0 +1,67 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor/Array.php + */ +require_once 'Image/Graph/DataPreprocessor/Array.php'; + +/** + * Formatting values using a sequential data label array, ie. returning the + * 'next label' when asked for any label. + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @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/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Sequential extends Image_Graph_DataPreprocessor_Array +{ + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + list ($id, $value) = each($this->_dataArray); + return $value; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataSelector.php b/packages/dspam/pear/Image/Graph/DataSelector.php new file mode 100644 index 00000000..0a81716c --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataSelector.php @@ -0,0 +1,67 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Filter used for selecting which data to show as markers + * + * @category Images + * @package Image_Graph + * @subpackage DataSelector + * @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/package/Image_Graph + */ +class Image_Graph_DataSelector +{ + + /** + * Image_Graph_DataSelector [Constructor] + */ + function Image_Graph_DataSelector() + { + } + + /** + * Check if a specified value should be 'selected', ie shown as a marker + * + * @param array $values The values to check + * @return bool True if the Values should cause a marker to be shown, false if not + * @access private + */ + function _select($values) + { + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataSelector/EveryNthPoint.php b/packages/dspam/pear/Image/Graph/DataSelector/EveryNthPoint.php new file mode 100644 index 00000000..62581222 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataSelector/EveryNthPoint.php @@ -0,0 +1,97 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataSelector.php + */ +require_once 'Image/Graph/DataSelector.php'; + +/** + * Filter out all points except every Nth point. + * + * Use this dataselector if you have a large number of datapoints, but only want to + * show markers for a small number of them, say every 10th. + * + * @category Images + * @package Image_Graph + * @subpackage DataSelector + * @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/package/Image_Graph + */ +class Image_Graph_DataSelector_EveryNthPoint extends Image_Graph_DataSelector +{ + + /** + * The number of points checked + * @var int + * @access private + */ + var $_pointNum = 0; + + /** + * The number of points between every 'show', default: 10 + * @var int + * @access private + */ + var $_pointInterval = 10; + + /** + * EvertNthPoint [Constructor] + * + * @param int $pointInterval The number of points between every 'show', + * default: 10 + */ + function Image_Graph_DataSelector_EveryNthpoint($pointInterval = 10) + { + parent::Image_Graph_DataSelector(); + $this->_pointInterval = $pointInterval; + } + + /** + * Check if a specified value should be 'selected', ie shown as a marker + * + * @param array $values The values to check + * @return bool True if the Values should cause a marker to be shown, + * false if not + * @access private + */ + function _select($values) + { + $oldPointNum = $this->_pointNum; + $this->_pointNum++; + return (($oldPointNum % $this->_pointInterval) == 0); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataSelector/NoZeros.php b/packages/dspam/pear/Image/Graph/DataSelector/NoZeros.php new file mode 100644 index 00000000..f32b918e --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataSelector/NoZeros.php @@ -0,0 +1,68 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataSelector.php + */ +require_once 'Image/Graph/DataSelector.php'; + +/** + * Filter out all zero's. + * + * Display all Y-values as markers, except those with Y = 0 + * + * @category Images + * @package Image_Graph + * @subpackage DataSelector + * @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/package/Image_Graph + */ +class Image_Graph_DataSelector_NoZeros extends Image_Graph_DataSelector +{ + + /** + * Check if a specified value should be 'selected', ie shown as a marker + * + * @param array $values The values to check + * @return bool True if the Values should cause a marker to be shown, false + * if not + * @access private + */ + function _select($values) + { + return ($values['Y'] != 0); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/DataSelector/Values.php b/packages/dspam/pear/Image/Graph/DataSelector/Values.php new file mode 100644 index 00000000..412e6ea9 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/DataSelector/Values.php @@ -0,0 +1,90 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataSelector.php + */ +require_once 'Image/Graph/DataSelector.php'; + +/** + * Filter out all but the specified values. + * + * @category Images + * @package Image_Graph + * @subpackage DataSelector + * @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/package/Image_Graph + */ +class Image_Graph_DataSelector_Values extends Image_Graph_DataSelector { + + /** + * The array with values that should be included + * @var array + * @access private + */ + var $_values; + + /** + * ValueArray [Constructor] + * + * @param array $valueArray The array to use as filter (default empty) + */ + function &Image_Graph_DataSelector_Values($values) + { + parent::Image_Graph_DataSelector(); + $this->_values = $values; + } + + /** + * Sets the array to use + */ + function setValueArray($values) + { + $this->_values = $values; + } + + /** + * Check if a specified value should be 'selected', ie shown as a marker + * + * @param array $values The values to check + * @return bool True if the Values should cause a marker to be shown, false + * if not + * @access private + */ + function _select($values) + { + return ( in_array($values['Y'], $this->_values) ); + } +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Dataset.php b/packages/dspam/pear/Image/Graph/Dataset.php new file mode 100644 index 00000000..4c349980 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Dataset.php @@ -0,0 +1,483 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + + +/** + * Data set used to represent a data collection to plot in a chart + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @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/package/Image_Graph + * @abstract + */ +class Image_Graph_Dataset +{ + + /** + * The pointer of the data set + * @var int + * @access private + */ + var $_posX = 0; + + /** + * The minimum X value of the dataset + * @var int + * @access private + */ + var $_minimumX = 0; + + /** + * The maximum X value of the dataset + * @var int + * @access private + */ + var $_maximumX = 0; + + /** + * The minimum Y value of the dataset + * @var int + * @access private + */ + var $_minimumY = 0; + + /** + * The maximum Y value of the dataset + * @var int + * @access private + */ + var $_maximumY = 0; + + /** + * The number of points in the dataset + * @var int + * @access private + */ + var $_count = 0; + + /** + * The name of the dataset, used for legending + * @var string + * @access private + */ + var $_name = ''; + + /** + * Image_Graph_Dataset [Constructor] + */ + function Image_Graph_Dataset() + { + } + + /** + * Sets the name of the data set, used for legending + * + * @param string $name The name of the dataset + */ + function setName($name) + { + $this->_name = $name; + } + + /** + * Add a point to the dataset + * + * $ID can contain either the ID of the point, i.e. 'DK', 123, 'George', etc. or it can contain + * values used for creation of the HTML image map. This is achieved using is an an associated array + * with the following values: + * + * 'url' The URL to create the link to + * + * 'alt' [optional] The alt text on the link + * + * 'target' [optional] The target of the link + * + * 'htmltags' [optional] An associated array with html tags (tag as key), fx. 'onMouseOver' => 'history.go(-1);', 'id' => 'thelink' + * + * @param int $x The X value to add + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($x, $y = false, $ID = false) + { + if ($y !== null) { + if (is_array($y)) { + $maxY = max($y); + $minY = min($y); + } else { + $maxY = $y; + $minY = $y; + } + } + + if ($this->_count) { + $this->_minimumX = min($x, $this->_minimumX); + $this->_maximumX = max($x, $this->_maximumX); + if ($y !== null) { + $this->_minimumY = min($minY, $this->_minimumY); + $this->_maximumY = max($maxY, $this->_maximumY); + } + } else { + $this->_minimumX = $x; + $this->_maximumX = $x; + if ($y !== null) { + $this->_minimumY = $minY; + $this->_maximumY = $maxY; + } + } + + $this->_count++; + } + + /** + * The number of values in the dataset + * + * @return int The number of values in the dataset + */ + function count() + { + return $this->_count; + } + + /** + * Gets a X point from the dataset + * + * @param var $x The variable to return an X value from, fx in a vector + * function data set + * @return var The X value of the variable + * @access private + */ + function _getPointX($x) + { + return $x; + } + + /** + * Gets a Y point from the dataset + * + * @param var $x The variable to return an Y value from, fx in a vector + * function data set + * @return var The Y value of the variable + * @access private + */ + function _getPointY($x) + { + return $x; + } + + /** + * Gets a ID from the dataset + * + * @param var $x The variable to return an Y value from, fx in a vector + * function data set + * @return var The ID value of the variable + * @access private + */ + function _getPointID($x) + { + return false; + } + + /** + * Gets point data from the dataset + * + * @param var $x The variable to return an Y value from, fx in a vector + * function data set + * @return array The data for the point + * @access private + */ + function _getPointData($x) + { + return false; + } + + /** + * The minimum X value + * + * @return var The minimum X value + */ + function minimumX() + { + return $this->_minimumX; + } + + /** + * The maximum X value + * + * @return var The maximum X value + */ + function maximumX() + { + return $this->_maximumX; + } + + /** + * The minimum Y value + * + * @return var The minimum Y value + */ + function minimumY() + { + return $this->_minimumY; + } + + /** + * The maximum Y value + * + * @return var The maximum Y value + */ + function maximumY() + { + return $this->_maximumY; + } + + /** + * The first point + * + * @return array The last point + */ + function first() + { + return array('X' => $this->minimumX(), 'Y' => $this->minimumY()); + } + + /** + * The last point + * + * @return array The first point + */ + function last() + { + return array('X' => $this->maximumX(), 'Y' => $this->maximumY()); + } + + /** + * The minimum X value + * + * @param var $value The minimum X value + * @access private + */ + function _setMinimumX($value) + { + $this->_minimumX = $value; + } + + /** + * The maximum X value + * + * @param var $value The maximum X value + * @access private + */ + function _setMaximumX($value) + { + $this->_maximumX = $value; + } + + /** + * The minimum Y value + * + * @param var $value The minimum X value + * @access private + */ + function _setMinimumY($value) + { + $this->_minimumY = $value; + } + + /** + * The maximum Y value + * + * @param var $value The maximum X value + * @access private + */ + function _setMaximumY($value) + { + $this->_maximumY = $value; + } + + /** + * The interval between 2 adjacent X values + * + * @return var The interval + * @access private + */ + function _stepX() + { + return 1; + } + + /** + * The interval between 2 adjacent Y values + * + * @return var The interval + * @access private + */ + function _stepY() + { + return 1; + } + + /** + * Reset the intertal dataset pointer + * + * @return var The first X value + * @access private + */ + function _reset() + { + $this->_posX = $this->_minimumX; + return $this->_posX; + } + + /** + * Get a point close to the internal pointer + * + * @param int Step Number of points next to the internal pointer, negative + * Step is towards lower X values, positive towards higher X values + * @return array The point + * @access private + */ + function _nearby($step = 0) + { + $x = $this->_getPointX($this->_posX + $this->_stepX() * $step); + $y = $this->_getPointY($this->_posX + $this->_stepX() * $step); + $ID = $this->_getPointID($this->_posX + $this->_stepX() * $step); + $data = $this->_getPointData($this->_posX + $this->_stepX() * $step); + if (($x === false) || ($y === false)) { + return false; + } else { + return array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); + } + } + + /** + * Get the next point the internal pointer refers to and advance the pointer + * + * @return array The next point + * @access private + */ + function _next() + { + if ($this->_posX > $this->_maximumX) { + return false; + } + + $x = $this->_getPointX($this->_posX); + $y = $this->_getPointY($this->_posX); + $ID = $this->_getPointID($this->_posX); + $data = $this->_getPointData($this->_posX); + $this->_posX += $this->_stepX(); + + return array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); + } + + /** + * Get the average of the dataset's Y points + * + * @return var The Y-average across the dataset + * @access private + */ + function _averageY() + { + $posX = $this->_minimumX; + $count = 0; + $total = 0; + while ($posX < $this->_maximumX) { + $count ++; + $total += $this->_getPointY($posX); + $posX += $this->_stepX(); + } + + if ($count != 0) { + return $total / $count; + } else { + return false; + } + } + + /** + * Get the median of the array passed Y points + * + * @param array $data The data-array to get the median from + * @param int $quartile The quartile to return the median from + * @return var The Y-median across the dataset from the specified quartile + * @access private + */ + function _median($data, $quartile = 'second') + { + sort($data); + $point = (count($data) - 1) / 2; + + if ($quartile == 'first') { + $lowPoint = 0; + $highPoint = floor($point); + } elseif ($quartile == 'third') { + $lowPoint = round($point); + $highPoint = count($data) - 1; + } else { + $lowPoint = 0; + $highPoint = count($data) - 1; + } + + $point = ($lowPoint + $highPoint) / 2; + + if (floor($point) != $point) { + $point = floor($point); + return ($data[$point] + $data[($point + 1)]) / 2; + } else { + return $data[$point]; + } + } + + /** + * Get the median of the datasets Y points + * + * @param int $quartile The quartile to return the median from + * @return var The Y-median across the dataset from the specified quartile + * @access private + */ + function _medianY($quartile = 'second') + { + $pointsY = array(); + $posX = $this->_minimumX; + while ($posX <= $this->_maximumX) { + $pointsY[] = $this->_getPointY($posX); + $posX += $this->_stepX(); + } + return $this->_median($pointsY, $quartile); + } + +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Dataset/Function.php b/packages/dspam/pear/Image/Graph/Dataset/Function.php new file mode 100644 index 00000000..08174b1d --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Dataset/Function.php @@ -0,0 +1,147 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset.php + */ +require_once 'Image/Graph/Dataset.php'; + +/** + * Function data set, points are generated by calling an external function. + * + * The function must be a single variable function and return a the result, + * builtin functions that are fx sin() or cos(). User defined function can be + * used if they are such, i.e: function myFunction($variable) + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @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/package/Image_Graph + */ +class Image_Graph_Dataset_Function extends Image_Graph_Dataset +{ + + /** + * The name of the function + * @var string + * @access private + */ + var $_dataFunction; + + /** + * Image_Graph_FunctionDataset [Constructor] + * + * @param double $minimumX The minimum X value + * @param double $maximumX The maximum X value + * @param string $function The name of the function, if must be a single + * parameter function like fx sin(x) or cos(x) + * @param int $points The number of points to create + */ + function Image_Graph_Dataset_Function($minimumX, $maximumX, $function, $points) + { + parent::Image_Graph_Dataset(); + $this->_minimumX = $minimumX; + $this->_maximumX = $maximumX; + $this->_dataFunction = $function; + $this->_count = $points; + $this->_calculateMaxima(); + } + + /** + * Add a point to the dataset. + * + * You can't add points to a function dataset + * + * @param int $x The X value to add + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($x, $y = false, $ID = false) + { + } + + /** + * Gets a Y point from the dataset + * + * @param var $x The variable to apply the function to + * @return var The function applied to the X value + * @access private + */ + function _getPointY($x) + { + $function = $this->_dataFunction; + return $function ($x); + } + + /** + * The number of values in the dataset + * + * @return int The number of values in the dataset + * @access private + */ + function _count() + { + return $this->_count; + } + + /** + * The interval between 2 adjacent Y values + * + * @return var The interval + * @access private + */ + function _stepX() + { + return ($this->_maximumX - $this->_minimumX) / $this->_count(); + } + + /** + * Calculates the Y extrema of the function + * + * @access private + */ + function _calculateMaxima() + { + $x = $this->_minimumX; + while ($x <= $this->_maximumX) { + $y = $this->_getPointY($x); + $this->_minimumY = min($y, $this->_minimumY); + $this->_maximumY = max($y, $this->_maximumY); + $x += $this->_stepX(); + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Dataset/Random.php b/packages/dspam/pear/Image/Graph/Dataset/Random.php new file mode 100644 index 00000000..0b2d7c68 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Dataset/Random.php @@ -0,0 +1,77 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset/Trivial.php + */ +require_once 'Image/Graph/Dataset/Trivial.php'; + +/** + * Random data set, points are generated by random. + * + * This dataset is mostly (if not solely) used for demo-purposes. + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @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/package/Image_Graph + */ +class Image_Graph_Dataset_Random extends Image_Graph_Dataset_Trivial +{ + + /** + * RandomDataset [Constructor] + * + * @param int $count The number of points to create + * @param double $minimum The minimum value the random set can be + * @param double $maximum The maximum value the random set can be + * @param bool $includeZero Whether 0 should be included or not as an X + * value, may be omitted, default: false + */ + function Image_Graph_Dataset_Random($count, $minimum, $maximum, $includeZero = false) + { + parent::Image_Graph_Dataset_Trivial(); + $i = 0; + while ($i < $count) { + $this->addPoint( + $ixc = ($includeZero ? $i : $i +1), + rand($minimum, $maximum) + ); + $i ++; + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Dataset/Sequential.php b/packages/dspam/pear/Image/Graph/Dataset/Sequential.php new file mode 100644 index 00000000..2605c409 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Dataset/Sequential.php @@ -0,0 +1,114 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset/Trivial.php + */ +require_once 'Image/Graph/Dataset/Trivial.php'; + +/** + * Sequential data set, simply add points (y) 1 by 1. + * + * This is a single point (1D) dataset, all points are of the type (0, y1), (1, + * y2), (2, y3)... Where the X-value is implicitly incremented. This is useful + * for example for barcharts, where you could fx. use an {@link + * Image_Graph_Dataset_Array} datapreprocessor to make sence of the x-values. + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @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/package/Image_Graph + */ +class Image_Graph_Dataset_Sequential extends Image_Graph_Dataset_Trivial +{ + + /** + * Image_Graph_SequentialDataset [Constructor] + */ + function Image_Graph_Dataset_Sequential($dataArray = false) + { + parent::Image_Graph_Dataset_Trivial(); + if (is_array($dataArray)) { + reset($dataArray); + foreach ($dataArray as $value) { + $this->addPoint($value); + } + } + } + + /** + * Add a point to the dataset + * + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($y, $ID = false) + { + parent::addPoint($this->count(), $y); + } + + /** + * Gets a X point from the dataset + * + * @param var $x The variable to return an X value from, fx in a + * vector function data set + * @return var The X value of the variable + * @access private + */ + function _getPointX($x) + { + return ((int) $x); + } + + /** + * The minimum X value + * @return var The minimum X value + */ + function minimumX() + { + return 0; + } + + /** + * The maximum X value + * @return var The maximum X value + */ + function maximumX() + { + return $this->count(); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Dataset/Trivial.php b/packages/dspam/pear/Image/Graph/Dataset/Trivial.php new file mode 100644 index 00000000..84af1c4b --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Dataset/Trivial.php @@ -0,0 +1,260 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset.php + */ +require_once 'Image/Graph/Dataset.php'; + +/** + * Trivial data set, simply add points (x, y) 1 by 1 + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @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/package/Image_Graph + */ +class Image_Graph_Dataset_Trivial extends Image_Graph_Dataset +{ + + /** + * Data storage + * @var array + * @access private + */ + var $_data; + + /** + * Image_Graph_Dataset_Trivial [Constructor] + * + * Pass an associated array ($data[$x] = $y) to the constructor for easy + * data addition. Alternatively (if multiple entries with same x value is + * required) pass an array with (x, y) values: $data[$id] = array('x' => $x, + * 'y' => $y); + * + * NB! If passing the 1st type array at this point, the x-values will also + * be used for ID tags, i.e. when using {@link Image_Graph_Fill_Array}. In + * the 2nd type the key/index of the "outermost" array will be the id tag + * (i.e. $id in the example) + * + * @param array $dataArray An associated array with values to the dataset + */ + function Image_Graph_Dataset_Trivial($dataArray = false) + { + parent::Image_Graph_Dataset(); + $this->_data = array (); + if (is_array($dataArray)) { + reset($dataArray); + $keys = array_keys($dataArray); + foreach ($keys as $x) { + $y =& $dataArray[$x]; + if ((is_array($y)) && (isset($y['x'])) && (isset($y['y']))) { + $this->addPoint($y['x'], $y['y'], (isset($y['id']) ? $y['id'] : $x)); + } else { + $this->addPoint($x, $y, $x); + } + } + } + } + + /** + * Add a point to the dataset + * + * $ID can contain either the ID of the point, i.e. 'DK', 123, 'George', etc. or it can contain + * values used for creation of the HTML image map. This is achieved using is an an associated array + * with the following values: + * + * 'url' The URL to create the link to + * + * 'alt' [optional] The alt text on the link + * + * 'target' [optional] The target of the link + * + * 'htmltags' [optional] An associated array with html tags (tag as key), fx. 'onMouseOver' => 'history.go(-1);', 'id' => 'thelink' + * + * @param int $x The X value to add + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($x, $y = false, $ID = false) + { + parent::addPoint($x, $y, $ID); + + if (is_array($ID)) { + $data = $ID; + $ID = (isset($data['id']) ? $data['id'] : false); + } else { + $data = false; + } + + $this->_data[] = array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); + if (!is_numeric($x)) { + $this->_maximumX = count($this->_data); + } + } + + /** + * The first point + * + * @return array The last point + */ + function first() + { + reset($this->_data); + return current($this->_data); + } + + /** + * The last point + * + * @return array The first point + */ + function last() + { + return end($this->_data); + } + + /** + * Gets a X point from the dataset + * + * @param var $x The variable to return an X value from, fx in a + * vector function data set + * @return var The X value of the variable + * @access private + */ + function _getPointX($x) + { + if (isset($this->_data[$x])) { + return $this->_data[$x]['X']; + } else { + return false; + } + } + + /** + * Gets a Y point from the dataset + * + * @param var $x The variable to return an Y value from, fx in a + * vector function data set + * @return var The Y value of the variable + * @access private + */ + function _getPointY($x) + { + if (isset($this->_data[$x])) { + return $this->_data[$x]['Y']; + } else { + return false; + } + } + + /** + * Gets a ID from the dataset + * + * @param var $x The variable to return an Y value from, fx in a + * vector function data set + * @return var The ID value of the variable + * @access private + */ + function _getPointID($x) + { + if (isset($this->_data[$x])) { + return $this->_data[$x]['ID']; + } else { + return false; + } + } + + /** + * Gets point data from the dataset + * + * @param var $x The variable to return an Y value from, fx in a vector + * function data set + * @return array The data for the point + * @access private + */ + function _getPointData($x) + { + if (isset($this->_data[$x])) { + return $this->_data[$x]['data']; + } else { + return false; + } + } + + /** + * The number of values in the dataset + * + * @return int The number of values in the dataset + */ + function count() + { + return count($this->_data); + } + + /** + * Reset the intertal dataset pointer + * + * @return var The first X value + * @access private + */ + function _reset() + { + $this->_posX = 0; + return $this->_posX; + } + + /** + * Get the next point the internal pointer refers to and advance the pointer + * + * @return array The next point + * @access private + */ + function _next() + { + if ($this->_posX >= $this->count()) { + return false; + } + $x = $this->_getPointX($this->_posX); + $y = $this->_getPointY($this->_posX); + $ID = $this->_getPointID($this->_posX); + $data = $this->_getPointData($this->_posX); + $this->_posX += $this->_stepX(); + + return array('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Dataset/VectorFunction.php b/packages/dspam/pear/Image/Graph/Dataset/VectorFunction.php new file mode 100644 index 00000000..4250bbc0 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Dataset/VectorFunction.php @@ -0,0 +1,185 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset.php + */ +require_once 'Image/Graph/Dataset.php'; + +/** + * Vector Function data set. + * + * Points are generated by calling 2 external functions, fx. x = sin(t) and y = + * cos(t) + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @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/package/Image_Graph + */ +class Image_Graph_Dataset_VectorFunction extends Image_Graph_Dataset +{ + + /** + * The name of the X function + * @var string + * @access private + */ + var $_functionX; + + /** + * The name of the Y function + * @var string + * @access private + */ + var $_functionY; + + /** + * The minimum of the vector function variable + * @var double + * @access private + */ + var $_minimumT; + + /** + * The maximum of the vector function variable + * @var double + * @access private + */ + var $_maximumT; + + /** + * Image_Graph_VectorFunctionDataset [Constructor] + * + * @param double $minimumT The minimum value of the vector function variable + * @param double $maximumT The maximum value of the vector function variable + * @param string $functionX The name of the X function, if must be a single + * parameter function like fx sin(x) or cos(x) + * @param string $functionY The name of the Y function, if must be a single + * parameter function like fx sin(x) or cos(x) + * @param int $points The number of points to create + */ + function Image_Graph_Dataset_VectorFunction($minimumT, $maximumT, $functionX, $functionY, $points) + { + parent::Image_Graph_Dataset(); + $this->_minimumT = $minimumT; + $this->_maximumT = $maximumT; + $this->_functionX = $functionX; + $this->_functionY = $functionY; + $this->_count = $points; + $this->_calculateMaxima(); + } + + /** + * Add a point to the dataset + * + * @param int $x The X value to add + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($x, $y = false, $ID = false) + { + } + + /** + * Gets a X point from the dataset + * + * @param var $x The variable to apply the X function to + * @return var The X function applied to the X value + * @access private + */ + function _getPointX($x) + { + $functionX = $this->_functionX; + return $functionX ($x); + } + + /** + * Gets a Y point from the dataset + * + * @param var $x The variable to apply the Y function to + * @return var The Y function applied to the X value + * @access private + */ + function _getPointY($x) + { + $functionY = $this->_functionY; + return $functionY ($x); + } + + /** + * Reset the intertal dataset pointer + * + * @return var The first T value + * @access private + */ + function _reset() + { + $this->_posX = $this->_minimumT; + return $this->_posX; + } + + /** + * The interval between 2 adjacent T values + * + * @return var The interval + * @access private + */ + function _stepX() + { + return ($this->_maximumT - $this->_minimumT) / $this->count(); + } + + /** + * Calculates the X and Y extrema of the functions + * + * @access private + */ + function _calculateMaxima() + { + $t = $this->_minimumT; + while ($t <= $this->_maximumT) { + $x = $this->_getPointX($t); + $y = $this->_getPointY($t); + $this->_minimumX = min($x, $this->_minimumX); + $this->_maximumX = max($x, $this->_maximumX); + $this->_minimumY = min($y, $this->_minimumY); + $this->_maximumY = max($y, $this->_maximumY); + $t += $this->_stepX(); + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Element.php b/packages/dspam/pear/Image/Graph/Element.php new file mode 100644 index 00000000..7c352ee5 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Element.php @@ -0,0 +1,763 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Common.php + */ +require_once 'Image/Graph/Common.php'; + +/** + * Representation of a element. + * + * The Image_Graph_Element can be drawn on the canvas, ie it has coordinates, + * {@link Image_Graph_Line}, {@link Image_Graph_Fill}, border and background - + * although not all of these may apply to all children. + * + * @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: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Element extends Image_Graph_Common +{ + + /** + * 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 rightmost pixel of the element on the canvas + * @var int + * @access private + */ + var $_right = 0; + + /** + * The bottommost pixel of the element on the canvas + * @var int + * @access private + */ + var $_bottom = 0; + + /** + * Background of the element. Default: None + * @var FillStyle + * @access private + */ + var $_background = null; + + /** + * Borderstyle of the element. Default: None + * @var LineStyle + * @access private + */ + var $_borderStyle = null; + + /** + * Line style of the element. Default: None + * @var LineStyle + * @access private + */ + var $_lineStyle = 'black'; + + /** + * Fill style of the element. Default: None + * @var FillStyle + * @access private + */ + var $_fillStyle = 'white'; + + /** + * Font of the element. Default: Standard font - FONT + * @var Font + * @access private + * @see $IMAGE_GRAPH_FONT + */ + var $_font = null; + + /** + * Font options + * @var array + * @access private + */ + var $_fontOptions = array(); + + /** + * Default font options + * + * This option is included for performance reasons. The value is calculated + * before output and reused in default cases to avoid unnecessary recursive + * calls. + * + * @var array + * @access private + */ + var $_defaultFontOptions = false; + + /** + * Shadows options of the element + * @var mixed + * @access private + */ + var $_shadow = false; + + /** + * The padding displayed on the element + * @var int + * @access private + */ + var $_padding = array('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0); + + /** + * Sets the background fill style of the element + * + * @param Image_Graph_Fill $background The background + * @see Image_Graph_Fill + */ + function setBackground(& $background) + { + if (!is_a($background, 'Image_Graph_Fill')) { + $this->_error( + 'Could not set background for ' . get_class($this) . ': ' . + get_class($background), array('background' => &$background) + ); + } else { + $this->_background =& $background; + $this->add($background); + } + } + + /** + * Shows shadow on the element + */ + function showShadow($color = 'black@0.2', $size = 5) + { + $this->_shadow = array( + 'color' => $color, + 'size' => $size + ); + } + + /** + * Sets the background color of the element. + * + * See colors.txt in the docs/ folder for a list of available named colors. + * + * @param mixed $color The color + */ + function setBackgroundColor($color) + { + $this->_background = $color; + } + + /** + * Gets the background fill style of the element + * + * @return int A GD fillstyle representing the background style + * @see Image_Graph_Fill + * @access private + */ + function _getBackground() + { + if (is_object($this->_background)) { + $this->_canvas->setFill($this->_background->_getFillStyle()); + } elseif ($this->_background != null) { + $this->_canvas->setFill($this->_background); + } else { + return false; + } + return true; + } + + /** + * Sets the border line style of the element + * + * @param Image_Graph_Line $borderStyle The line style of the border + * @see Image_Graph_Line + */ + function setBorderStyle(& $borderStyle) + { + if (!is_a($borderStyle, 'Image_Graph_Line')) { + $this->_error( + 'Could not set border style for ' . get_class($this) . ': ' . + get_class($borderStyle), array('borderstyle' => &$borderStyle) + ); + } else { + $this->_borderStyle =& $borderStyle; + $this->add($borderStyle); + } + } + + /** + * Sets the border color of the element. + * + * See colors.txt in the docs/ folder for a list of available named colors. + * @param mixed $color The color + */ + function setBorderColor($color) + { + $this->_borderStyle = $color; + } + + /** + * Gets the border line style of the element + * + * @return int A GD linestyle representing the borders line style + * @see Image_Graph_Line + * @access private + */ + function _getBorderStyle() + { + if (is_object($this->_borderStyle)) { + $result = $this->_borderStyle->_getLineStyle(); + $this->_canvas->setLineThickness($result['thickness']); + $this->_canvas->setLineColor($result['color']); + } elseif ($this->_borderStyle != null) { + $this->_canvas->setLineThickness(1); + $this->_canvas->setLineColor($this->_borderStyle); + } else { + return false; + } + return true; + } + + /** + * Sets the line style of the element + * + * @param Image_Graph_Line $lineStyle The line style of the element + * @see Image_Graph_Line + */ + function setLineStyle(& $lineStyle) + { + if (!is_object($lineStyle)) { + $this->_error( + 'Could not set line style for ' . get_class($this) . ': ' . + get_class($lineStyle), array('linestyle' => &$lineStyle) + ); + } else { + $this->_lineStyle =& $lineStyle; + $this->add($lineStyle); + } + } + + /** + * Sets the line color of the element. + * + * See colors.txt in the docs/ folder for a list of available named colors. + * + * @param mixed $color The color + */ + function setLineColor($color) + { + $this->_lineStyle = $color; + } + + /** + * Gets the line style of the element + * + * @return int A GD linestyle representing the line style + * @see Image_Graph_Line + * @access private + */ + function _getLineStyle($ID = false) + { + if (is_object($this->_lineStyle)) { + $result = $this->_lineStyle->_getLineStyle($ID); + if (is_array($result)) { + $this->_canvas->setLineThickness($result['thickness']); + $this->_canvas->setLineColor($result['color']); + } else { + $this->_canvas->setLineThickness(1); + $this->_canvas->setLineColor($result); + } + } elseif ($this->_lineStyle != null) { + $this->_canvas->setLineThickness(1); + $this->_canvas->setLineColor($this->_lineStyle); + } else { + return false; + } + return true; + } + + /** + * Sets the fill style of the element + * + * @param Image_Graph_Fill $fillStyle The fill style of the element + * @see Image_Graph_Fill + */ + function setFillStyle(& $fillStyle) + { + if (!is_a($fillStyle, 'Image_Graph_Fill')) { + $this->_error( + 'Could not set fill style for ' . get_class($this) . ': ' . + get_class($fillStyle), array('fillstyle' => &$fillStyle) + ); + } else { + $this->_fillStyle =& $fillStyle; + $this->add($fillStyle); + } + } + + /** + * Sets the fill color of the element. + * + * See colors.txt in the docs/ folder for a list of available named colors. + * + * @param mixed $color The color + */ + function setFillColor($color) + { + $this->_fillStyle = $color; + } + + + /** + * Gets the fill style of the element + * + * @return int A GD filestyle representing the fill style + * @see Image_Graph_Fill + * @access private + */ + function _getFillStyle($ID = false) + { + if (is_object($this->_fillStyle)) { + $this->_canvas->setFill($this->_fillStyle->_getFillStyle($ID)); + } elseif ($this->_fillStyle != null) { + $this->_canvas->setFill($this->_fillStyle); + } else { + return false; + } + return true; + } + + /** + * Gets the font of the element. + * + * If not font has been set, the parent font is propagated through it's + * children. + * + * @return array An associated array used for canvas + * @access private + */ + function _getFont($options = false) + { + if (($options === false) && ($this->_defaultFontOptions !== false)) { + return $this->_defaultFontOptions; + } + + if ($options === false) { + $saveDefault = true; + } else { + $saveDefault = false; + } + + if ($options === false) { + $options = $this->_fontOptions; + } else { + $options = array_merge($this->_fontOptions, $options); + } + + if ($this->_font == null) { + $result = $this->_parent->_getFont($options); + } else { + $result = $this->_font->_getFont($options); + } + + if ((isset($result['size'])) && (isset($result['size_rel']))) { + $result['size'] += $result['size_rel']; + unset($result['size_rel']); + } + + if ($saveDefault) { + $this->_defaultFontOptions = $result; + } + + return $result; + } + + /** + * Sets the font of the element + * + * @param Image_Graph_Font $font The font of the element + * @see Image_Graph_Font + */ + function setFont(& $font) + { + if (!is_a($font, 'Image_Graph_Font')) { + $this->_error('Invalid font set on ' . get_class($this)); + } else { + $this->_font =& $font; + $this->add($font); + } + } + + /** + * Sets the font size + * + * @param int $size The size of the font + */ + function setFontSize($size) + { + $this->_fontOptions['size'] = $size; + } + + /** + * Sets the font angle + * + * @param int $angle The angle of the font + */ + function setFontAngle($angle) + { + if ($angle == 'vertical') { + $this->_fontOptions['vertical'] = true; + $this->_fontOptions['angle'] = 90; + } else { + $this->_fontOptions['angle'] = $angle; + } + } + + /** + * Sets the font color + * + * @param mixed $color The color of the font + */ + function setFontColor($color) + { + $this->_fontOptions['color'] = $color; + } + + /** + * Clip the canvas to the coordinates of the element + * + * @param $enable bool Whether clipping should be enabled or disabled + * @access protected + */ + function _clip($enable) + { + $this->_canvas->setClipping( + ($enable ? + array( + 'x0' => min($this->_left, $this->_right), + 'y0' => min($this->_top, $this->_bottom), + 'x1' => max($this->_left, $this->_right), + 'y1' => max($this->_top, $this->_bottom) + ) + : false + ) + ); + } + + /** + * Sets the coordinates of the element + * + * @param int $left The leftmost pixel of the element on the canvas + * @param int $top The topmost pixel of the element on the canvas + * @param int $right The rightmost pixel of the element on the canvas + * @param int $bottom The bottommost pixel of the element on the canvas + * @access private + */ + function _setCoords($left, $top, $right, $bottom) + { + if ($left === false) { + $left = $this->_left; + } + + if ($top === false) { + $top = $this->_top; + } + + if ($right === false) { + $right = $this->_right; + } + + if ($bottom === false) { + $bottom = $this->_bottom; + } + + $this->_left = min($left, $right); + $this->_top = min($top, $bottom); + $this->_right = max($left, $right); + $this->_bottom = max($top, $bottom); + } + + /** + * Moves the element + * + * @param int $deltaX Number of pixels to move the element to the right + * (negative values move to the left) + * @param int $deltaY Number of pixels to move the element downwards + * (negative values move upwards) + * @access private + */ + function _move($deltaX, $deltaY) + { + $this->_left += $deltaX; + $this->_right += $deltaX; + $this->_top += $deltaY; + $this->_bottom += $deltaY; + } + + /** + * Sets the width of the element relative to the left side + * + * @param int $width Number of pixels the element should be in width + * @access private + */ + function _setWidth($width) + { + $this->_right = $this->_left + $width; + } + + /** + * Sets the height of the element relative to the top + * + * @param int $width Number of pixels the element should be in height + * @access private + */ + function _setHeight($height) + { + $this->_bottom = $this->_top + $height; + } + + /** + * Sets padding of the element + * + * @param mixed $padding Number of pixels the element should be padded with + * or an array of paddings (left, top, right and bottom as index) + */ + function setPadding($padding) + { + if (is_array($padding)) { + $this->_padding = array(); + $this->_padding['left'] = (isset($padding['left']) ? $padding['left'] : 0); + $this->_padding['top'] = (isset($padding['top']) ? $padding['top'] : 0); + $this->_padding['right'] = (isset($padding['right']) ? $padding['right'] : 0); + $this->_padding['bottom'] = (isset($padding['bottom']) ? $padding['bottom'] : 0); + } + else { + $this->_padding = array( + 'left' => $padding, + 'top' => $padding, + 'right' => $padding, + 'bottom' => $padding + ); + } + } + + /** + * The width of the element on the canvas + * + * @return int Number of pixels representing the width of the element + */ + function width() + { + return abs($this->_right - $this->_left) + 1; + } + + /** + * The height of the element on the canvas + * + * @return int Number of pixels representing the height of the element + */ + function height() + { + return abs($this->_bottom - $this->_top) + 1; + } + + /** + * Left boundary of the background fill area + * + * @return int Leftmost position on the canvas + * @access private + */ + function _fillLeft() + { + return $this->_left + $this->_padding['left']; + } + + /** + * Top boundary of the background fill area + * + * @return int Topmost position on the canvas + * @access private + */ + function _fillTop() + { + return $this->_top + $this->_padding['top']; + } + + /** + * Right boundary of the background fill area + * + * @return int Rightmost position on the canvas + * @access private + */ + function _fillRight() + { + return $this->_right - $this->_padding['right']; + } + + /** + * Bottom boundary of the background fill area + * + * @return int Bottommost position on the canvas + * @access private + */ + function _fillBottom() + { + return $this->_bottom - $this->_padding['bottom']; + } + + /** + * Returns the filling width of the element on the canvas + * + * @return int Filling width + * @access private + */ + function _fillWidth() + { + return $this->_fillRight() - $this->_fillLeft() + 1; + } + + /** + * Returns the filling height of the element on the canvas + * + * @return int Filling height + * @access private + */ + function _fillHeight() + { + return $this->_fillBottom() - $this->_fillTop() + 1; + } + + /** + * Draws a shadow 'around' the element + * + * Not implemented yet. + * + * @access private + */ + function _displayShadow() + { + if (is_array($this->_shadow)) { + $this->_canvas->startGroup(get_class($this) . '_shadow'); + $this->_canvas->setFillColor($this->_shadow['color']); + $this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_top + $this->_shadow['size'])); + $this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_top + $this->_shadow['size'])); + $this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size'])); + $this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size'])); + $this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + 1)); + $this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_bottom + 1)); + $this->_canvas->polygon(array('connect' => true)); + $this->_canvas->endGroup(); + } + } + + /** + * Writes text to the canvas. + * + * @param int $x The x position relative to alignment + * @param int $y The y position relative to alignment + * @param string $text The text + * @param int $alignmen The text alignment (both vertically and horizontally) + */ + function write($x, $y, $text, $alignment = false, $font = false) + { + if (($font === false) && ($this->_defaultFontOptions !== false)) { + $font = $this->_defaultFontOptions; + } else { + $font = $this->_getFont($font); + } + + if ($alignment === false) { + $alignment = IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_TOP; + } + + $align = array(); + + if (($alignment & IMAGE_GRAPH_ALIGN_TOP) != 0) { + $align['vertical'] = 'top'; + } else if (($alignment & IMAGE_GRAPH_ALIGN_BOTTOM) != 0) { + $align['vertical'] = 'bottom'; + } else { + $align['vertical'] = 'center'; + } + + if (($alignment & IMAGE_GRAPH_ALIGN_LEFT) != 0) { + $align['horizontal'] = 'left'; + } else if (($alignment & IMAGE_GRAPH_ALIGN_RIGHT) != 0) { + $align['horizontal'] = 'right'; + } else { + $align['horizontal'] = 'center'; + } + + $this->_canvas->setFont($font); + $this->_canvas->addText(array('x' => $x, 'y' => $y, 'text' => $text, 'alignment' => $align)); + } + + /** + * Output the element to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @see Image_Graph_Common + * @access private + */ + function _done() + { + $background = $this->_getBackground(); + $border = $this->_getBorderStyle(); + if (($background) || ($border)) { + $this->_canvas->rectangle(array('x0' => $this->_left, 'y0' => $this->_top, 'x1' => $this->_right, 'y1' => $this->_bottom)); + } + + $result = parent::_done(); + + if ($this->_shadow !== false) { + $this->_displayShadow(); + } + + return $result; + } + +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Figure/Circle.php b/packages/dspam/pear/Image/Graph/Figure/Circle.php new file mode 100644 index 00000000..a3f1652e --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Figure/Circle.php @@ -0,0 +1,64 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Figure/Ellipse.php + */ +require_once 'Image/Graph/Figure/Ellipse.php'; + +/** + * Circle to draw on the canvas + * + * @category Images + * @package Image_Graph + * @subpackage Figure + * @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/package/Image_Graph + */ +class Image_Graph_Figure_Circle extends Image_Graph_Figure_Ellipse +{ + + /** + * Image_Graph_Circle [Constructor] + * + * @param int $x The center pixel of the circle on the canvas + * @param int $y The center pixel of the circle on the canvas + * @param int $radius The radius in pixels of the circle + */ + function Image_Graph_Figure_Circle($x, $y, $radius) + { + parent::Image_Graph_Ellipse($x, $y, $radius, $radius); + } + +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Figure/Ellipse.php b/packages/dspam/pear/Image/Graph/Figure/Ellipse.php new file mode 100644 index 00000000..8e42f2b1 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Figure/Ellipse.php @@ -0,0 +1,97 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Ellipse to draw on the canvas + * + * @category Images + * @package Image_Graph + * @subpackage Figure + * @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/package/Image_Graph + */ +class Image_Graph_Figure_Ellipse extends Image_Graph_Element +{ + + /** + * Ellipse [Constructor] + * + * @param int $x The center pixel of the ellipse on the canvas + * @param int $y The center pixel of the ellipse on the canvas + * @param int $radiusX The width in pixels of the box on the canvas + * @param int $radiusY The height in pixels of the box on the canvas + */ + function Image_Graph_Figure_Ellipse($x, $y, $radiusX, $radiusY) + { + parent::Image_Graph_Element(); + $this->_setCoords($x - $radiusX, $y - $radiusY, $x + $radiusX, $y + $radiusY); + } + + /** + * Output the ellipse + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->ellipse( + array( + 'x' => ($this->_left + $this->_right) / 2, + 'y' => ($this->_top + $this->_bottom) / 2, + 'rx' => $this->width(), + 'ry' => $this->height() + ) + ); + + $this->_canvas->endGroup(); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Figure/Polygon.php b/packages/dspam/pear/Image/Graph/Figure/Polygon.php new file mode 100644 index 00000000..5b78f635 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Figure/Polygon.php @@ -0,0 +1,94 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Polygon to draw on the canvas + * + * @category Images + * @package Image_Graph + * @subpackage Figure + * @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/package/Image_Graph + */ +class Image_Graph_Figure_Polygon extends Image_Graph_Element +{ + + /** + * Polygon vertices + * + * @var array + * @access private + */ + var $_polygon = array (); + + /** + * Add a vertex to the polygon + * + * @param int $x X-coordinate + * @param int $y Y-coordinate + */ + function addVertex($x, $y) + { + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + + /** + * Output the polygon + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->polygon(array('connect' => true)); + + $this->_canvas->endGroup(); + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Figure/Rectangle.php b/packages/dspam/pear/Image/Graph/Figure/Rectangle.php new file mode 100644 index 00000000..dbca58e0 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Figure/Rectangle.php @@ -0,0 +1,96 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Rectangle to draw on the canvas + * + * @category Images + * @package Image_Graph + * @subpackage Figure + * @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/package/Image_Graph + */ +class Image_Graph_Figure_Rectangle extends Image_Graph_Element +{ + + /** + * Rectangle [Construcor] + * + * @param int $x The leftmost pixel of the box on the canvas + * @param int $y The topmost pixel of the box on the canvas + * @param int $width The width in pixels of the box on the canvas + * @param int $height The height in pixels of the box on the canvas + */ + function Image_Graph_Figure_Rectangle($x, $y, $width, $height) + { + parent::Image_Graph_Element(); + $this->_setCoords($x, $y, $x + $width, $y + $height); + } + + /** + * Output the box + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ) + ); + + $this->_canvas->endGroup(); + + return true; + } + +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Fill.php b/packages/dspam/pear/Image/Graph/Fill.php new file mode 100644 index 00000000..f1cd36d7 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Fill.php @@ -0,0 +1,63 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Style used for filling elements. + * + * @category Images + * @package Image_Graph + * @subpackage Fill + * @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/package/Image_Graph + * @abstract + */ +class Image_Graph_Fill extends Image_Graph_Common +{ + + /** + * Resets the fillstyle + * + * @access private + */ + function _reset() + { + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Fill/Array.php b/packages/dspam/pear/Image/Graph/Fill/Array.php new file mode 100644 index 00000000..8d0b2dfa --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Fill/Array.php @@ -0,0 +1,137 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Fill.php + */ +require_once 'Image/Graph/Fill.php'; + +/** + * A sequential array of fillstyles. + * + * This is used for filling multiple objects within the same element with + * different styles. This is done by adding multiple fillstyles to a FillArrray + * structure. The fillarray will then when requested return the 'next' fillstyle + * in sequential order. It is possible to specify ID tags to each fillstyle, + * which is used to make sure some data uses a specific fillstyle (i.e. in a + * multiple-/stackedbarchart you name the {@link Image_Graph_Dataset}s and uses + * this name as ID tag when adding the dataset's associated fillstyle to the + * fillarray. + * + * @category Images + * @package Image_Graph + * @subpackage Fill + * @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/package/Image_Graph + */ +class Image_Graph_Fill_Array extends Image_Graph_Fill +{ + + /** + * The fill array + * @var array + * @access private + */ + var $_fillStyles = array (); + + /** + * Resets the fillstyle + * + * @access private + */ + function _reset() + { + reset($this->_fillStyles); + } + + /** + * Add a fill style to the array + * + * @param Image_Graph_Fill $style The style to add + * @param string $id The id or name of the style + */ + function &add(& $style, $id = '') + { + if ($id == '') { + $this->_fillStyles[] =& $style; + } else { + $this->_fillStyles[$id] =& $style; + } + reset($this->_fillStyles); + return $style; + } + + /** + * Add a color to the array + * + * @param int $color The color + * @param string $id The id or name of the color + */ + function addColor($color, $id = false) + { + if ($id !== false) { + $this->_fillStyles[$id] = $color; + } else { + $this->_fillStyles[] = $color; + } + reset($this->_fillStyles); + } + + /** + * Return the fillstyle + * + * @return int A GD fillstyle + * @access private + */ + function _getFillStyle($ID = false) + { + if (($ID === false) || (!isset($this->_fillStyles[$ID]))) { + $ID = key($this->_fillStyles); + if (!next($this->_fillStyles)) { + reset($this->_fillStyles); + } + } + $fillStyle =& $this->_fillStyles[$ID]; + + if (is_object($fillStyle)) { + return $fillStyle->_getFillStyle($ID); + } elseif ($fillStyle !== null) { + return $fillStyle; + } else { + return parent::_getFillStyle($ID); + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Fill/Gradient.php b/packages/dspam/pear/Image/Graph/Fill/Gradient.php new file mode 100644 index 00000000..9cf23a6b --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Fill/Gradient.php @@ -0,0 +1,149 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Fill/Image.php + */ +require_once 'Image/Graph/Fill/Image.php'; + +/** + * Fill using a gradient color. + * This creates a scaled fillstyle with colors flowing gradiently between 2 + * specified RGB values. Several directions are supported: + * + * 1 Vertically (IMAGE_GRAPH_GRAD_VERTICAL) + * + * 2 Horizontally (IMAGE_GRAPH_GRAD_HORIZONTAL) + * + * 3 Mirrored vertically (the color grades from a- b-a vertically) + * (IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED) + * + * 4 Mirrored horizontally (the color grades from a-b-a horizontally) + * IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED + * + * 5 Diagonally from top-left to right-bottom + * (IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR) + * + * 6 Diagonally from bottom-left to top-right + * (IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR) + * + * 7 Radially (concentric circles in the center) (IMAGE_GRAPH_GRAD_RADIAL) + * + * @category Images + * @package Image_Graph + * @subpackage Fill + * @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/package/Image_Graph + */ +class Image_Graph_Fill_Gradient extends Image_Graph_Fill //Image_Graph_Fill_Image +{ + + /** + * The direction of the gradient + * @var int + * @access private + */ + var $_direction; + + /** + * The first color to gradient + * @var mixed + * @access private + */ + var $_startColor; + + /** + * The last color to gradient + * @var mixed + * @access private + */ + var $_endColor; + + /** + * Image_Graph_GradientFill [Constructor] + * + * @param int $direction The direction of the gradient + * @param mixed $startColor The value of the starting color + * @param mixed $endColor The value of the ending color + */ + function Image_Graph_Fill_Gradient($direction, $startColor, $endColor) + { + parent::Image_Graph_Fill(); + $this->_direction = $direction; + $this->_startColor = $startColor; + $this->_endColor = $endColor; + } + + /** + * Return the fillstyle + * + * @return int A GD fillstyle + * @access private + */ + function _getFillStyle($ID = false) + { + switch ($this->_direction) { + case IMAGE_GRAPH_GRAD_HORIZONTAL: + $direction = 'horizontal'; + break; + case IMAGE_GRAPH_GRAD_VERTICAL: + $direction = 'vertical'; + break; + case IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED: + $direction = 'horizontal_mirror'; + break; + case IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED: + $direction = 'vertical_mirror'; + break; + case IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR: + $direction = 'diagonal_tl_br'; + break; + case IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR: + $direction = 'diagonal_bl_tr'; + break; + case IMAGE_GRAPH_GRAD_RADIAL: + $direction = 'radial'; + break; + } + + return array( + 'type' => 'gradient', + 'start' => $this->_startColor, + 'end' => $this->_endColor, + 'direction' => $direction + ); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Fill/Image.php b/packages/dspam/pear/Image/Graph/Fill/Image.php new file mode 100644 index 00000000..9b1fb142 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Fill/Image.php @@ -0,0 +1,97 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Fill.php + */ +require_once 'Image/Graph/Fill.php'; + +/** + * Fill using an image. + * + * @category Images + * @package Image_Graph + * @subpackage Fill + * @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/package/Image_Graph + */ +class Image_Graph_Fill_Image extends Image_Graph_Fill +{ + + /** + * The file name + * @var stirng + * @access private + */ + var $_filename; + + /** + * The GD Image resource + * @var resource + * @access private + */ + var $_image; + + /** + * Resize the image to the bounding box of the area to fill + * @var bool + * @access private + */ + var $_resize = true; + + /** + * Image_Graph_ImageFill [Constructor] + * + * @param string $filename The filename and path of the image to use for filling + */ + function Image_Graph_Fill_Image($filename) + { + parent::Image_Graph_Fill(); + $this->_filename = $filename; + } + + /** + * Return the fillstyle + * + * @param (something) $ID (Add description) + * @return int A GD fillstyle + * @access private + */ + function _getFillStyle($ID = false) + { + return $this->_filename; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Font.php b/packages/dspam/pear/Image/Graph/Font.php new file mode 100644 index 00000000..ad018a27 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Font.php @@ -0,0 +1,158 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Common.php + */ +require_once 'Image/Graph/Common.php'; + +/** + * A font. + * + * @category Images + * @package Image_Graph + * @subpackage Text + * @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/package/Image_Graph + * @abstract + */ +class Image_Graph_Font extends Image_Graph_Common +{ + + /** + * The name of the font + * @var string + * @access private + */ + var $_name = false; + + /** + * The angle of the output + * @var int + * @access private + */ + var $_angle = false; + + /** + * The size of the font + * @var int + * @access private + */ + var $_size = 11; + + /** + * The color of the font + * @var Color + * @access private + */ + var $_color = 'black'; + + /** + * Image_Graph_Font [Constructor] + */ + function Image_Graph_Font($name = false, $size = false) + { + parent::Image_Graph_Common(); + if ($name !== false) { + $this->_name = $name; + } + if ($size !== false) { + $this->_size = $size; + } + } + + /** + * Set the color of the font + * + * @param mixed $color The color object of the Font + */ + function setColor($color) + { + $this->_color = $color; + } + + /** + * Set the angle slope of the output font. + * + * 0 = normal, 90 = bottom and up, 180 = upside down, 270 = top and down + * + * @param int $angle The angle in degrees to slope the text + */ + function setAngle($angle) + { + $this->_angle = $angle; + } + + /** + * Set the size of the font + * + * @param int $size The size in pixels of the font + */ + function setSize($size) + { + $this->_size = $size; + } + + /** + * Get the font 'array' + * + * @return array The font 'summary' to pass to the canvas + * @access private + */ + function _getFont($options = false) + { + if ($options === false) { + $options = array(); + } + + if ($this->_name !== false) { + $options['name'] = $this->_name; + } + + if (!isset($options['color'])) { + $options['color'] = $this->_color; + } + + if (!isset($options['size'])) { + $options['size'] = $this->_size; + } + + if ((!isset($options['angle'])) && ($this->_angle !== false)) { + $options['angle'] = $this->_angle; + } + return $options; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Grid.php b/packages/dspam/pear/Image/Graph/Grid.php new file mode 100644 index 00000000..4406dbdd --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Grid.php @@ -0,0 +1,175 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * A grid displayed on the plotarea. + * + * A grid is associated with a primary and a secondary axis. The grid is + * displayed in context of the primary axis' label interval - meaning that a + * grid for an Y-axis displays a grid for every label on the y-axis (fx. a {@link + * Image_Graph_Grid_Lines}, which displays horizontal lines for every label on + * the y-axis from the x-axis minimum to the x-axis maximum). You should always + * add the grid as one of the first elements to the plotarea. This is due to the + * fact that elements are 'outputted' in the order they are added, i.e. if an + * grid is added *after* a chart, the grid will be displayed on top of the chart + * which is (probably) not desired. + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @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/package/Image_Graph + * @abstract + */ +class Image_Graph_Grid extends Image_Graph_Plotarea_Element +{ + + /** + * The primary axis: the grid 'refers' to + * @var Axis + * @access private + */ + var $_primaryAxis = null; + + /** + * The secondary axis + * @var Axis + * @access private + */ + var $_secondaryAxis = null; + + /** + * Set the primary axis: the grid should 'refer' to + * + * @param Image_Graph_Axis $axis The axis + * @access private + */ + function _setPrimaryAxis(& $axis) + { + $this->_primaryAxis =& $axis; + } + + /** + * Set the secondary axis + * + * @param Image_Graph_Axis $axis The axis + * @access private + */ + function _setSecondaryAxis(& $axis) + { + $this->_secondaryAxis =& $axis; + } + + /** + * Get the points on the secondary axis that the grid should 'connect' + * + * @return array The secondary data values that should mark the grid 'end points' + * @access private + */ + function _getSecondaryAxisPoints() + { + if (is_a($this->_secondaryAxis, 'Image_Graph_Axis_Radar')) { + $secondaryValue = false; + $firstValue = $secondaryValue; + while (($secondaryValue = $this->_secondaryAxis->_getNextLabel($secondaryValue)) !== false) { + $secondaryAxisPoints[] = $secondaryValue; + } + $secondaryAxisPoints[] = $firstValue; + } else { + $secondaryAxisPoints = array ('#min#', '#max#'); + } + return $secondaryAxisPoints; + } + + /** + * Get the X pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($point) + { + if (($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) || + ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY)) + { + $point['AXIS_Y'] = $this->_primaryAxis->_type; + } else { + $point['AXIS_Y'] = $this->_secondaryAxis->_type; + } + return parent::_pointX($point); + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($point) + { + if (($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) || + ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY)) + { + $point['AXIS_Y'] = $this->_primaryAxis->_type; + } else { + $point['AXIS_Y'] = $this->_secondaryAxis->_type; + } + return parent::_pointY($point); + } + + /** + * Causes the object to update all sub elements coordinates. + * + * @access private + */ + function _updateCoords() + { + $this->_setCoords( + $this->_parent->_plotLeft, + $this->_parent->_plotTop, + $this->_parent->_plotRight, + $this->_parent->_plotBottom + ); + parent::_updateCoords(); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Grid/Bars.php b/packages/dspam/pear/Image/Graph/Grid/Bars.php new file mode 100644 index 00000000..a75782f2 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Grid/Bars.php @@ -0,0 +1,117 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display alternating bars on the plotarea. + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @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/package/Image_Graph + */ +class Image_Graph_Grid_Bars extends Image_Graph_Grid +{ + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $i = 0; + $value = false; + + $previousValue = 0; + + $secondaryPoints = $this->_getSecondaryAxisPoints(); + + while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) { + if ($i == 1) { + reset($secondaryPoints); + list ($id, $previousSecondaryValue) = each($secondaryPoints); + while (list ($id, $secondaryValue) = each($secondaryPoints)) { + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) { + $p1 = array ('Y' => $secondaryValue, 'X' => $value); + $p2 = array ('Y' => $previousSecondaryValue, 'X' => $value); + $p3 = array ('Y' => $previousSecondaryValue, 'X' => $previousValue); + $p4 = array ('Y' => $secondaryValue, 'X' => $previousValue); + } else { + $p1 = array ('X' => $secondaryValue, 'Y' => $value); + $p2 = array ('X' => $previousSecondaryValue, 'Y' => $value); + $p3 = array ('X' => $previousSecondaryValue, 'Y' => $previousValue); + $p4 = array ('X' => $secondaryValue, 'Y' => $previousValue); + } + + $this->_canvas->addVertex(array('x' => $this->_pointX($p1), 'y' => $this->_pointY($p1))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p2), 'y' => $this->_pointY($p2))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p3), 'y' => $this->_pointY($p3))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p4), 'y' => $this->_pointY($p4))); + + $this->_getFillStyle(); + $this->_canvas->polygon(array('connect' => true)); + + $previousSecondaryValue = $secondaryValue; + } + } + $i = 1 - $i; + $previousValue = $value; + } + + $this->_canvas->endGroup(); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Grid/Lines.php b/packages/dspam/pear/Image/Graph/Grid/Lines.php new file mode 100644 index 00000000..805778ee --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Grid/Lines.php @@ -0,0 +1,114 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display a line grid on the plotarea. + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @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/package/Image_Graph + */ +class Image_Graph_Grid_Lines extends Image_Graph_Grid +{ + + /** + * GridLines [Constructor] + */ + function Image_Graph_Grid_Lines() + { + parent::Image_Graph_Grid(); + $this->_lineStyle = 'lightgrey'; + } + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $value = false; + + $secondaryPoints = $this->_getSecondaryAxisPoints(); + + while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) { + reset($secondaryPoints); + list ($id, $previousSecondaryValue) = each($secondaryPoints); + while (list ($id, $secondaryValue) = each($secondaryPoints)) { + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) { + $p1 = array ('X' => $secondaryValue, 'Y' => $value); + $p2 = array ('X' => $previousSecondaryValue, 'Y' => $value); + } else { + $p1 = array ('X' => $value, 'Y' => $secondaryValue); + $p2 = array ('X' => $value, 'Y' => $previousSecondaryValue); + } + + $x1 = $this->_pointX($p1); + $y1 = $this->_pointY($p1); + $x2 = $this->_pointX($p2); + $y2 = $this->_pointY($p2); + + $previousSecondaryValue = $secondaryValue; + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x1, 'y0' => $y1, 'x1' => $x2, 'y1' => $y2)); + } + } + + $this->_canvas->endGroup(); + + return true; + } + +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Grid/Polar.php b/packages/dspam/pear/Image/Graph/Grid/Polar.php new file mode 100644 index 00000000..03b1b916 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Grid/Polar.php @@ -0,0 +1,111 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display a line grid on the plotarea. + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @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/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Grid_Polar extends Image_Graph_Grid +{ + + /** + * GridLines [Constructor] + */ + function Image_Graph_Grid_Polar() + { + parent::Image_Graph_Grid(); + $this->_lineStyle = 'lightgrey'; + } + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $value = false; + + $p0 = array ('X' => '#min#', 'Y' => '#min#'); + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) { + $p1 = array ('X' => '#min#', 'Y' => '#max#'); + $r0 = abs($this->_pointY($p1) - $this->_pointY($p0)); + } else { + $p1 = array ('X' => '#max#', 'Y' => '#min#'); + $r0 = abs($this->_pointX($p1) - $this->_pointX($p0)); + } + + $cx = $this->_pointX($p0); + $cy = $this->_pointY($p0); + + $span = $this->_primaryAxis->_axisSpan; + + while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) { + $r = $r0 * ($value - $this->_primaryAxis->_getMinimum()) / $span; + + $this->_getLineStyle(); + $this->_canvas->ellipse(array('x' => $cx, 'y' => $cy, 'rx' => $r, 'ry' => $r)); + } + + $this->_canvas->endGroup(); + + return true; + } + +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Images/Icons/pinpoint.png b/packages/dspam/pear/Image/Graph/Images/Icons/pinpoint.png new file mode 100644 index 00000000..d23f0b7d Binary files /dev/null and b/packages/dspam/pear/Image/Graph/Images/Icons/pinpoint.png differ diff --git a/packages/dspam/pear/Image/Graph/Images/Icons/pinpointr.png b/packages/dspam/pear/Image/Graph/Images/Icons/pinpointr.png new file mode 100644 index 00000000..2455e09b Binary files /dev/null and b/packages/dspam/pear/Image/Graph/Images/Icons/pinpointr.png differ diff --git a/packages/dspam/pear/Image/Graph/Images/Maps/README b/packages/dspam/pear/Image/Graph/Images/Maps/README new file mode 100644 index 00000000..1b984bbb --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Images/Maps/README @@ -0,0 +1,17 @@ +In this folder the files for the Image_Graph_Plot_Map are located. They should be the +following format: + +[map name].png +[map name].txt + +The [map name].png (fx. europe.png) is the actual image presenting the map. The +[map name].txt file is the location -> (x,y) conversion table. In this file the +named locations is written on every line with the x and y coordinates after the +name (with a TAB), i.e.: + +Denmark 10 30 +England 4 30 + +Where Denmark will be 'located' on (10, 30) on the map, and England at (4, 30). + +No maps are released by default due to we want to avoid possible copyright issues. \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Layout.php b/packages/dspam/pear/Image/Graph/Layout.php new file mode 100644 index 00000000..1561aafa --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Layout.php @@ -0,0 +1,219 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea/Element.php + */ +require_once 'Image/Graph/Plotarea/Element.php'; + +/** + * Defines an area of the graph that can be layout'ed. + * + * Any class that extends this abstract class can be used within a layout on the canvas. + * + * @category Images + * @package Image_Graph + * @subpackage Layout + * @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/package/Image_Graph + * @abstract + */ +class Image_Graph_Layout extends Image_Graph_Plotarea_Element +{ + + /** + * Has the coordinates already been updated? + * @var bool + * @access private + */ + var $_updated = false; + + /** + * Alignment of the area for each vertice (left, top, right, bottom) + * @var array + * @access private + */ + var $_alignSize = array ('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0); + + /** + * Image_Graph_Layout [Constructor] + */ + function Image_Graph_Layout() + { + parent::Image_Graph_Element(); + $this->_padding = array('left' => 2, 'top' => 2, 'right' => 2, 'bottom' => 2); + } + + /** + * Resets the elements + * + * @access private + */ + function _reset() + { + parent::_reset(); + $this->_updated = false; + } + + /** + * Calculate the edge offset for a specific edge + * @param array $alignSize The alignment of the edge + * @param int $offset The offset/posision of the at 0% edge + * @param int $total The total size (width or height) of the element + * @param int $multiplier +/- 1 if the edge should pushed either toward more + * negative or positive values + * @since 0.3.0dev2 + * @access private + */ + function _calcEdgeOffset($alignSize, $offset, $total, $multiplier) + { + if ($alignSize['unit'] == 'percentage') { + return $offset + $multiplier * ($total * $alignSize['value'] / 100); + } elseif ($alignSize['unit'] == 'pixels') { + if (($alignSize['value'] == 'auto_part1') || ($alignSize['value'] == 'auto_part2')) { + $alignSize['value'] = $multiplier * $this->_parent->_getAbsolute($alignSize['value']); + } + if ($alignSize['value'] < 0) { + return $offset + $multiplier * ($total + $alignSize['value']); + } else { + return $offset + $multiplier * $alignSize['value']; + } + } + return $offset; + } + + /** + * Calculate the edges + * + * @access private + */ + function _calcEdges() + { + if ((is_array($this->_alignSize)) && (!$this->_updated)) { + $left = $this->_calcEdgeOffset( + $this->_alignSize['left'], + $this->_parent->_fillLeft(), + $this->_parent->_fillWidth(), + +1 + ); + $top = $this->_calcEdgeOffset( + $this->_alignSize['top'], + $this->_parent->_fillTop(), + $this->_parent->_fillHeight(), + +1 + ); + $right = $this->_calcEdgeOffset( + $this->_alignSize['right'], + $this->_parent->_fillRight(), + $this->_parent->_fillWidth(), + -1 + ); + $bottom = $this->_calcEdgeOffset( + $this->_alignSize['bottom'], + $this->_parent->_fillBottom(), + $this->_parent->_fillHeight(), + -1 + ); + + $this->_setCoords( + $left + $this->_padding['left'], + $top + $this->_padding['top'], + $right - $this->_padding['right'], + $bottom - $this->_padding['bottom'] + ); + } + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + $this->_calcEdges(); + parent::_updateCoords(); + } + + /** + * Pushes an edge of area a specific distance 'into' the canvas + * + * @param int $edge The edge of the canvas to align relative to + * @param int $size The number of pixels or the percentage of the canvas total size to occupy relative to the selected alignment edge + * @access private + */ + function _push($edge, $size = '100%') + { + $result = array(); + if (ereg("([0-9]*)\%", $size, $result)) { + $this->_alignSize[$edge] = array( + 'value' => min(100, max(0, $result[1])), + 'unit' => 'percentage' + ); + } else { + $this->_alignSize[$edge] = array( + 'value' => $size, + 'unit' => 'pixels' + ); + } + } + + /** + * Sets the coordinates of the element + * + * @param int $left The leftmost pixel of the element on the canvas + * @param int $top The topmost pixel of the element on the canvas + * @param int $right The rightmost pixel of the element on the canvas + * @param int $bottom The bottommost pixel of the element on the canvas + * @access private + */ + function _setCoords($left, $top, $right, $bottom) + { + parent::_setCoords($left, $top, $right, $bottom); + $this->_updated = true; + } + + /** + * Returns the calculated "auto" size + * + * @return int The calculated auto size + * @access private + */ + function _getAutoSize() + { + return false; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Layout/Horizontal.php b/packages/dspam/pear/Image/Graph/Layout/Horizontal.php new file mode 100644 index 00000000..414a168c --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Layout/Horizontal.php @@ -0,0 +1,186 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Layout for displaying two elements side by side. + * + * This splits the area contained by this element in two, side by side by + * a specified percentage (relative to the left side). A layout can be nested. + * Fx. a HorizontalLayout can layout two {@link Image_Graph_Layout_Vertical}s to + * make a 2 by 2 matrix of 'element-areas'. + * + * @category Images + * @package Image_Graph + * @subpackage Layout + * @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/package/Image_Graph + */ +class Image_Graph_Layout_Horizontal extends Image_Graph_Layout +{ + + /** + * Part1 of the layout + * @var GraPHPElemnt + * @access private + */ + var $_part1 = false; + + /** + * Part2 of the layout + * @var GraPHPElemnt + * @access private + */ + var $_part2 = false; + + /** + * The percentage of the graph where the split occurs + * @var int + * @access private + */ + var $_percentage; + + /** + * An absolute position where the split occurs + * @var int + * @access private + */ + var $_absolute; + + /** + * HorizontalLayout [Constructor] + * + * @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 + */ + function Image_Graph_Layout_Horizontal(& $part1, & $part2, $percentage = 50) + { + parent::Image_Graph_Layout(); + if (!is_a($part1, 'Image_Graph_Layout')) { + $this->_error( + 'Cannot create layout on non-layouable parts: ' . get_class($part1), + array('part1' => &$part1, 'part2' => &$part2) + ); + } elseif (!is_a($part2, 'Image_Graph_Layout')) { + $this->_error( + 'Cannot create layout on non-layouable parts: ' . get_class($part2), + array('part1' => &$part1, 'part2' => &$part2) + ); + } else { + $this->_part1 =& $part1; + $this->_part2 =& $part2; + $this->add($this->_part1); + $this->add($this->_part2); + }; + if ($percentage === 'auto') { + $this->_percentage = false; + $this->_absolute = 'runtime'; + } else { + $this->_absolute = false; + $this->_percentage = max(0, min(100, $percentage)); + } + $this->_split(); + $this->_padding = array('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0); + } + + /** + * Gets the absolute size of one of the parts. + * + * @param string $part The name of the part - auto_part(1|2) + * @return int The number of pixels the edge should be pushed + * @since 0.3.0dev2 + * @access private + */ + function _getAbsolute(&$part) + { + $part1Size = $this->_part1->_getAutoSize(); + $part2Size = $this->_part2->_getAutoSize(); + $this->_percentage = false; + if (($part1Size !== false) and ($part2Size !== false)) { + $width = $this->_fillWidth() * $part1Size / ($part1Size + $part2Size); + } elseif ($part1Size !== false) { + $width = $part1Size; + } elseif ($part2Size !== false) { + $width = -$part2Size; + } else { + $width = $this->_fillWidth() / 2; + } + if ($part == 'auto_part2') { + $width = -$width; + } + + return $width; + } + + /** + * Splits the layout between the parts, by the specified percentage + * + * @access private + */ + function _split() + { + if (($this->_part1) && ($this->_part2)) { + if ($this->_percentage !== false) { + $split1 = 100 - $this->_percentage; + $split2 = $this->_percentage; + $this->_part1->_push('right', "$split1%"); + $this->_part2->_push('left', "$split2%"); + } else { + $this->_part1->_push('right', 'auto_part1'); + $this->_part2->_push('left', 'auto_part2'); + } + } + } + + /** + * Output the layout to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (($this->_part1) && ($this->_part2)) { + return (($this->_part1->_done()) && ($this->_part2->_done())); + } + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Layout/Matrix.php b/packages/dspam/pear/Image/Graph/Layout/Matrix.php new file mode 100644 index 00000000..8acec871 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Layout/Matrix.php @@ -0,0 +1,201 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Layout for displaying elements in a matix. + * + * @category Images + * @package Image_Graph + * @subpackage Layout + * @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/package/Image_Graph + */ +class Image_Graph_Layout_Matrix extends Image_Graph_Layout +{ + + /** + * Layout matrix + * @var array + * @access private + */ + var $_matrix = false; + + /** + * The number of rows + * @var int + * @access private + */ + var $_rows = false; + + /** + * The number of columns + * @var int + * @access private + */ + var $_cols = false; + + /** + * Image_Graph_Layout_Matrix [Constructor] + * + * @param int $rows The number of rows + * @param int $cols The number of cols + * @param bool $autoCreate Specifies whether the matrix should automatically + * be filled with newly created Image_Graph_Plotares objects, or they will + * be added manually + */ + function Image_Graph_Layout_Matrix($rows, $cols, $autoCreate = true) + { + parent::Image_Graph_Layout(); + + $this->_rows = $rows; + $this->_cols = $cols; + if (($this->_rows > 0) && ($this->_cols > 0)) { + $this->_matrix = array(array()); + for ($i = 0; $i < $this->_rows; $i++) { + for ($j = 0; $j < $this->_cols; $j++) { + if ($autoCreate) { + $this->_matrix[$i][$j] =& $this->addNew('plotarea'); + $this->_pushEdges($i, $j); + } else { + $this->_matrix[$i][$j] = false; + } + } + } + } + } + + /** + * Pushes the edges on the specified position in the matrix + * + * @param int $row The row + * @param int $col The column + * @access private + */ + function _pushEdges($row, $col) + { + if ((isset($this->_matrix[$row])) && (isset($this->_matrix[$row][$col]))) { + $height = 100/$this->_rows; + $width = 100/$this->_cols; + if ($col > 0) { + $this->_matrix[$row][$col]->_push('left', round($col*$width) . '%'); + } + if ($col+1 < $this->_cols) { + $this->_matrix[$row][$col]->_push('right', round(100-($col+1)*$width) . '%'); + } + if ($row > 0) { + $this->_matrix[$row][$col]->_push('top', round($row*$height) . '%'); + } + if ($row+1 < $this->_rows) { + $this->_matrix[$row][$col]->_push('bottom', round(100-($row+1)*$height) . '%'); + } + } + } + + /** + * Get the area on the specified position in the matrix + * + * @param int $row The row + * @param int $col The column + * @return Image_Graph_Layout The element of position ($row, $col) in the + * matrix + */ + function &getEntry($row, $col) + { + if ((isset($this->_matrix[$row])) && (isset($this->_matrix[$row][$col]))) { + return $this->_matrix[$row][$col]; + } else { + $result = null; + return $result; + } + } + + /** + * Get the area on the specified position in the matrix + * + * @param int $row The row + * @param int $col The column + * @param Image_Graph_Layout $element The element to set in the position + * ($row, $col) in the matrix + */ + function setEntry($row, $col, &$element) + { + $this->_matrix[$row][$col] =& $element; + $this->_pushEdges($row, $col); + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + for ($i = 0; $i < $this->_rows; $i++) { + for ($j = 0; $j < $this->_cols; $j++) { + $element =& $this->getEntry($i, $j); + $this->add($element); + } + } + parent::_updateCoords(); + } + + /** + * Output the layout to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $result = true; + for ($i = 0; $i < $this->_rows; $i++) { + for ($j = 0; $j < $this->_cols; $j++) { + $element =& $this->getEntry($i, $j); + if ($element) { + if (!$element->_done()) { + $result = false; + } + } + } + } + return $result; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Layout/Vertical.php b/packages/dspam/pear/Image/Graph/Layout/Vertical.php new file mode 100644 index 00000000..2dc6f945 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Layout/Vertical.php @@ -0,0 +1,108 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout/Horizontal.php + */ +require_once 'Image/Graph/Layout/Horizontal.php'; + +/** + * Layout for displaying two elements on top of each other. + * + * This splits the area contained by this element in two on top of each other + * by a specified percentage (relative to the top). A layout can be nested. + * Fx. a {@link Image_Graph_Layout_Horizontal} can layout two VerticalLayout's to + * make a 2 by 2 matrix of 'element-areas'. + * + * @category Images + * @package Image_Graph + * @subpackage Layout + * @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/package/Image_Graph + */ +class Image_Graph_Layout_Vertical extends Image_Graph_Layout_Horizontal +{ + + /** + * Gets the absolute size of one of the parts. + * + * @param string $part The name of the part - auto_part(1|2) + * @return int The number of pixels the edge should be pushed + * @since 0.3.0dev2 + * @access private + */ + function _getAbsolute(&$part) + { + $part1Size = $this->_part1->_getAutoSize(); + $part2Size = $this->_part2->_getAutoSize(); + $this->_percentage = false; + if (($part1Size !== false) and ($part2Size !== false)) { + $height = $this->_fillHeight() * $part1Size / ($part1Size + $part2Size); + } elseif ($part1Size !== false) { + $height = $part1Size; + } elseif ($part2Size !== false) { + $height = -$part2Size; + } else { + $height = $this->_fillHeight() / 2; + } + + if ($part == 'auto_part2') { +// $height = $this->_fillHeight() - $height; + } + + return $height; + } + + /** + * Splits the layout between the parts, by the specified percentage + * + * @access private + */ + function _split() + { + if (($this->_part1) && ($this->_part2)) { + if ($this->_percentage !== false) { + $split1 = 100 - $this->_percentage; + $split2 = $this->_percentage; + $this->_part1->_push('bottom', "$split1%"); + $this->_part2->_push('top', "$split2%"); + } else { + $this->_part1->_push('bottom', 'auto_part1'); + $this->_part2->_push('top', 'auto_part2'); + } + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Legend.php b/packages/dspam/pear/Image/Graph/Legend.php new file mode 100644 index 00000000..d853dad5 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Legend.php @@ -0,0 +1,385 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Displays a legend for a plotarea. + * + * A legend can be displayed in two ways: + * + * 1 As an overlayed box within the plotarea + * + * 2 Layout'ed on the canvas smewhere next to the plotarea. + * + * @category Images + * @package Image_Graph + * @subpackage Legend + * @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/package/Image_Graph + */ +class Image_Graph_Legend extends Image_Graph_Layout +{ + + /** + * Alignment of the text + * @var int + * @access private + */ + var $_alignment = false; + + /** + * The plotarea(s) to show the legend for + * @var array + * @access private + */ + var $_plotareas = array(); + + /** + * Should markers be shown or not on this legend + * @var bool + * @access private + */ + var $_showMarker = false; + + /** + * Image_Graph_Legend [Constructor] + */ + function Image_Graph_Legend() + { + parent::Image_Graph_Layout(); + $this->_padding = array('left' => 5, 'top' => 5, 'right' => 5, 'bottom' => 5); + } + + /** + * The number of actual plots in the plot area + * + * @return int The number of plotes + * @access private + */ + function _plotCount() + { + $count = 0; + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + if (is_a($plotarea, 'Image_Graph_Plotarea')) { + $keys2 = array_keys($plotarea->_elements); + foreach ($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $count ++; + } + } + unset($keys2); + } + } + unset($keys); + return $count; + } + + /** + * Get a default parameter array for legendSamples + * @param bool $simulate Whether the array should be used for simulation or + * not + * @return array Default parameter array + * @access private + */ + function _parameterArray($simulate = false) + { + $param['left'] = $this->_left + $this->_padding['left']; + $param['top'] = $this->_top + $this->_padding['top']; + $param['right'] = $this->_right - $this->_padding['right']; + $param['bottom'] = $this->_bottom - $this->_padding['bottom']; + $param['align'] = $this->_alignment; + $param['x'] = $this->_left + $this->_padding['left']; + $param['y'] = $this->_top + $this->_padding['top']; + $param['width'] = 16; + $param['height'] = 16; + $param['show_marker'] = $this->_showMarker; + $param['maxwidth'] = 0; + $param['font'] = $this->_getFont(); + if ($simulate) { + $param['simulate'] = true; + } + + return $param; + } + + /** + * The height of the element on the canvas + * + * @return int Number of pixels representing the height of the element + * @access private + */ + function _height() + { + $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent); + + if (strtolower($parent) == 'image_graph_plotarea') { + $param = $this->_parameterArray(true); + $param['align'] = IMAGE_GRAPH_ALIGN_VERTICAL; + $param0 = $param; + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param); + } + } + unset($keys2); + } + unset($keys); + return abs($param['y'] - $param0['y']) + $this->_padding['top'] + $this->_padding['bottom']; + } else { + return parent::height(); + } + } + + /** + * The width of the element on the canvas + * + * @return int Number of pixels representing the width of the element + * @access private + */ + function _width() + { + $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent); + + if (strtolower($parent) == 'image_graph_plotarea') { + $param = $this->_parameterArray(true); + $param['align'] = IMAGE_GRAPH_ALIGN_VERTICAL; + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param); + } + } + unset($keys2); + } + unset($keys); + return $param['maxwidth']; + } else { + return parent::width(); + } + } + + /** + * Set the alignment of the legend + * + * @param int $alignment The alignment + */ + function setAlignment($alignment) + { + $this->_alignment = $alignment; + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + parent::_updateCoords(); + + $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent); + + if (strtolower($parent) == 'image_graph_plotarea') { + $w = $this->_width(); + $h = $this->_height(); + + if ($this->_alignment === false) { + $this->_alignment = IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_RIGHT; + } + + if (($this->_alignment & IMAGE_GRAPH_ALIGN_BOTTOM) != 0) { + $y = $this->_parent->_fillBottom() - $h - $this->_padding['bottom']; + } else { + $y = $this->_parent->_fillTop() + $this->_padding['top']; + } + + if (($this->_alignment & IMAGE_GRAPH_ALIGN_LEFT) != 0) { + $x = $this->_parent->_fillLeft() + $this->_padding['left']; + } else { + $x = $this->_parent->_fillRight() - $w - $this->_padding['right']; + } + + $this->_setCoords($x, $y, $x + $w, $y + $h); + } + } + + /** + * Sets Plotarea + * + * @param Image_Graph_Plotarea $plotarea The plotarea + */ + function setPlotarea(& $plotarea) + { + if (is_a($plotarea, 'Image_Graph_Plotarea')) { + $this->_plotareas[] =& $plotarea; + } + } + + /** + * Sets the parent. The parent chain should ultimately be a GraPHP object + * + * @see Image_Graph + * @param Image_Graph_Common $parent The parent + * @access private + */ + function _setParent(& $parent) + { + parent::_setParent($parent); + if (count($this->_plotareas) == 0) { + $this->setPlotarea($parent); + } + } + + /** + * Set if this legends should show markers + * + * @param bool $showMarker True if markers are to be shown, false is not + */ + function setShowMarker($showMarker) + { + $this->_showMarker = $showMarker; + } + + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + + if (Image_Graph_Element::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $param = $this->_parameterArray(); + + $parent = (is_object($this->_parent) ? + get_class($this->_parent) : + $this->_parent + ); + + if (strtolower($parent) == 'image_graph_plotarea') { + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ) + ); + + $param = $this->_parameterArray(); + + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param); + } + } + unset($keys2); + } + unset($keys); + } else { + $param0 = $param; + $param0['simulate'] = true; + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param0); + } + } + unset($keys2); + } + unset($keys); + if (($this->_alignment & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + if ($param0['x'] == $param['x']) { + $param['y'] = $param['y'] + ($this->_height() - ($param0['y'] - $param['y']))/2; + } + } else { + if ($param0['y'] == $param['y']) { + $param['x'] = $param['x'] + ($this->_width() - ($param0['x'] - $param['x']))/2; + } + } + + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param); + } + } + unset($keys2); + } + unset($keys); + } + + $this->_canvas->endGroup(); + + return true; + } +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Line/Array.php b/packages/dspam/pear/Image/Graph/Line/Array.php new file mode 100644 index 00000000..5d542141 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Line/Array.php @@ -0,0 +1,129 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Common.php + */ +require_once 'Image/Graph/Common.php'; + +/** + * A sequential array of linestyles. + * + * This is used for multiple objects within the same element with different line + * styles. This is done by adding multiple line styles to a LineArrray + * structure. The linearray will then when requested return the 'next' linestyle + * in sequential order. It is possible to specify ID tags to each linestyle, + * which is used to make sure some data uses a specific linestyle (i.e. in a + * multiple-/stackedbarchart you name the {@link Image_Graph_Dataset}s and uses + * this name as ID tag when adding the dataset's associated linestyle to the + * linearray. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @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/package/Image_Graph + */ +class Image_Graph_Line_Array extends Image_Graph_Common +{ + + /** + * The fill array + * @var array + * @access private + */ + var $_lineStyles = array (); + + /** + * Add a line style to the array + * + * @param Image_Graph_Line $style The style to add + */ + function add(& $style, $id = false) + { + if (is_a($style, 'Image_Graph_Element')) { + parent::add($style); + } + if ($id === false) { + $this->_lineStyles[] =& $style; + } else { + $this->_lineStyles[$id] =& $style; + } + reset($this->_lineStyles); + + } + + /** + * Add a color to the array + * + * @param int $color The color + * @param string $id The id or name of the color + */ + function addColor($color, $id = false) + { + if ($id !== false) { + $this->_lineStyles[$id] = $color; + } else { + $this->_lineStyles[] = $color; + } + reset($this->_lineStyles); + } + + /** + * Return the linestyle + * + * @return int A GD Linestyle + * @access private + */ + function _getLineStyle($ID = false) + { + if (($ID === false) || (!isset($this->_lineStyles[$ID]))) { + $ID = key($this->_lineStyles); + if (!next($this->_lineStyles)) { + reset($this->_lineStyles); + } + } + $lineStyle =& $this->_lineStyles[$ID]; + + if (is_object($lineStyle)) { + return $lineStyle->_getLineStyle($ID); + } elseif ($lineStyle !== null) { + return $lineStyle; + } else { + return parent::_getLineStyle($ID); + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Line/Dashed.php b/packages/dspam/pear/Image/Graph/Line/Dashed.php new file mode 100644 index 00000000..448fb218 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Line/Dashed.php @@ -0,0 +1,76 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Line/Formatted.php + */ +require_once 'Image/Graph/Line/Formatted.php'; + +/** + * Dashed line style. + * + * This style displays as a short line with a shorter space afterwards, i.e + * 4px color1, 2px color2, 4px color1, etc. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @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/package/Image_Graph + */ +class Image_Graph_Line_Dashed extends Image_Graph_Line_Formatted +{ + + /** + * Image_Graph_DashedLine [Constructor] + * + * @param mixed $color1 The color for the 'dashes' + * @param mixed $color2 The color for the 'spaces' + */ + function Image_Graph_Line_Dashed($color1, $color2) + { + parent::Image_Graph_Line_Formatted( + array( + $color1, + $color1, + $color1, + $color1, + $color2, + $color2 + ) + ); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Line/Dotted.php b/packages/dspam/pear/Image/Graph/Line/Dotted.php new file mode 100644 index 00000000..8574f8da --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Line/Dotted.php @@ -0,0 +1,67 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Line/Formatted.php + */ +require_once 'Image/Graph/Line/Formatted.php'; + +/** + * Dotted line style. + * + * This style displays as a short line with a shorter space afterwards, i.e + * 1px color1, 1px color2, 1px color1, etc. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @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/package/Image_Graph + */ +class Image_Graph_Line_Dotted extends Image_Graph_Line_Formatted +{ + + /** + * DottedLine [Constructor] + * + * @param mixed $color1 The color representing the dots + * @param mixed $color2 The color representing the spaces + */ + function Image_Graph_Line_Dotted($color1, $color2) + { + parent::Image_Graph_Line_Formatted(array ($color1, $color2)); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Line/Formatted.php b/packages/dspam/pear/Image/Graph/Line/Formatted.php new file mode 100644 index 00000000..e6d0181b --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Line/Formatted.php @@ -0,0 +1,90 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Line/Solid.php + */ +require_once 'Image/Graph/Line/Solid.php'; + +/** + * Formatted user defined line style. + * + * Use this to create a user defined line style. Specify an array of colors that are to + * be used for displaying the line. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @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/package/Image_Graph + */ +class Image_Graph_Line_Formatted extends Image_Graph_Line_Solid +{ + + /** + * The style of the line + * + * @var array + * @access private + */ + var $_style; + + /** + * Image_Graph_FormattedLine [Constructor] + * + * @param array $style The style of the line + */ + function Image_Graph_Line_Formatted($style) + { + parent::Image_Graph_Line_Solid(reset($style)); + $this->_style = $style; + } + + /** + * Gets the line style of the element + * + * @return int A GD linestyle representing the line style + * @see Image_Graph_Line + * @access private + */ + function _getLineStyle() + { + return array( + 'color' => $this->_style, + 'thickness' => $this->_thickness + ); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Line/Solid.php b/packages/dspam/pear/Image/Graph/Line/Solid.php new file mode 100644 index 00000000..e77e62f1 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Line/Solid.php @@ -0,0 +1,105 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Common.php + */ +require_once 'Image/Graph/Common.php'; + +/** + * Simple colored line style. + * + * Use a color for line style. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @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/package/Image_Graph + */ +class Image_Graph_Line_Solid extends Image_Graph_Common +{ + + /** + * The thickness of the line (requires GD 2) + * @var int + * @access private + */ + var $_thickness = 1; + + /** + * The color of the line + * @var mixed + * @access private + */ + var $_color; + + /** + * Image_Graph_SolidLine [Constructor] + * + * @param mixed $color The color of the line + */ + function Image_Graph_Line_Solid($color) + { + parent::Image_Graph_Common(); + $this->_color = $color; + } + + /** + * Set the thickness of the linestyle + * + * @param int $thickness The line width in pixels + */ + function setThickness($thickness) + { + $this->_thickness = $thickness; + } + + /** + * Gets the line style of the element + * + * @return int A GD linestyle representing the line style + * @see Image_Graph_Line + * @access private + */ + function _getLineStyle() + { + return array( + 'color' => $this->_color, + 'thickness' => $this->_thickness + ); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Logo.php b/packages/dspam/pear/Image/Graph/Logo.php new file mode 100644 index 00000000..df5fe7e4 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Logo.php @@ -0,0 +1,153 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Displays a logo on the canvas. + * + * By default the logo is displayed in the top-right corner of the canvas. + * + * @category Images + * @package Image_Graph + * @subpackage Logo + * @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/package/Image_Graph + */ +class Image_Graph_Logo extends Image_Graph_Element +{ + + /** + * The file name + * @var stirng + * @access private + */ + var $_filename; + + /** + * The GD Image resource + * @var resource + * @access private + */ + var $_image; + + /** + * Alignment of the logo + * @var int + * @access private + */ + var $_alignment; + + /** + * Logo [Constructor] + * + * @param string $filename The filename and path of the image to use for logo + */ + function Image_Graph_Logo($filename, $alignment = IMAGE_GRAPH_ALIGN_TOP_RIGHT) + { + parent::Image_Graph_Element(); + $this->_filename = $filename; + $this->_alignment = $alignment; + } + + /** + * Sets the parent. The parent chain should ultimately be a GraPHP object + * + * @see Image_Graph + * @param Image_Graph_Common $parent The parent + * @access private + */ + function _setParent(& $parent) + { + parent::_setParent($parent); + $this->_setCoords( + $this->_parent->_left, + $this->_parent->_top, + $this->_parent->_right, + $this->_parent->_bottom + ); + } + + /** + * Output the logo + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $align = array(); + + if ($this->_alignment & IMAGE_GRAPH_ALIGN_LEFT) { + $x = $this->_parent->_left + 2; + $align['horizontal'] = 'left'; + } elseif ($this->_alignment & IMAGE_GRAPH_ALIGN_RIGHT) { + $x = $this->_parent->_right - 2; + $align['horizontal'] = 'right'; + } else { + $x = ($this->_parent->_left + $this->_parent->_right) / 2; + $align['horizontal'] = 'center'; + } + + if ($this->_alignment & IMAGE_GRAPH_ALIGN_TOP) { + $y = $this->_parent->_top + 2; + $align['vertical'] = 'top'; + } elseif ($this->_alignment & IMAGE_GRAPH_ALIGN_BOTTOM) { + $y = $this->_parent->_bottom - 2; + $align['vertical'] = 'bottom'; + } else { + $y = ($this->_parent->_top + $this->_parent->_bottom) / 2; + $align['vertical'] = 'center'; + } + + $this->_canvas->image( + array( + 'x' => $x, + 'y' => $y, + 'filename' => $this->_filename, + 'alignment' => $align + ) + ); + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker.php b/packages/dspam/pear/Image/Graph/Marker.php new file mode 100644 index 00000000..1c1926fe --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker.php @@ -0,0 +1,123 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea/Element.php + */ +require_once 'Image/Graph/Plotarea/Element.php'; + +/** + * Data point marker. + * + * The data point marker is used for marking the datapoints on a graph with some + * visual label, fx. a cross, a text box with the value or an icon. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + * @abstract + */ +class Image_Graph_Marker extends Image_Graph_Plotarea_Element +{ + + /** + * Secondary marker + * @var Marker + * @access private + */ + var $_secondaryMarker = false; + + /** + * The 'size' of the marker, the meaning depends on the specific Marker + * implementation + * @var int + * @access private + */ + var $_size = 6; + + /** + * Set the 'size' of the marker + * + * @param int $size The 'size' of the marker, the meaning depends on the + * specific Marker implementation + */ + function setSize($size) + { + $this->_size = $size; + } + + /** + * Set the secondary marker + * + * @param Marker $secondaryMarker The secondary marker + */ + function setSecondaryMarker(& $secondaryMarker) + { + $this->_secondaryMarker =& $secondaryMarker; + $this->_secondaryMarker->_setParent($this); + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if (is_a($this->_secondaryMarker, 'Image_Graph_Marker')) { + $this->_secondaryMarker->_drawMarker($x, $y, $values); + } + } + + /** + * Output to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Array.php b/packages/dspam/pear/Image/Graph/Marker/Array.php new file mode 100644 index 00000000..12fed66c --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Array.php @@ -0,0 +1,105 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * A sequential array of markers. + * + * This is used for displaying different markers for datapoints on a chart. + * This is done by adding multiple markers to a MarkerArrray structure. + * The marker array will then when requested return the 'next' marker in + * sequential order. It is possible to specify ID tags to each marker, which is + * used to make sure some data uses a specific marker. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Array extends Image_Graph_Marker +{ + + /** + * The marker array + * @var array + * @access private + */ + var $_markers = array (); + + /** + * Add a marker style to the array + * + * @param Marker $marker The marker to add + */ + function add(& $marker) + { + if (is_a($marker, 'Image_Graph_Element')) { + parent::add($marker); + } + $this->_markers[] =& $marker; + reset($this->_markers); + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $ID = key($this->_markers); + if (!next($this->_markers)) { + reset($this->_markers); + } + $marker =& $this->_markers[$ID]; + + if ($marker != null) { + $marker->_drawMarker($x, $y, $values); + } + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Asterisk.php b/packages/dspam/pear/Image/Graph/Marker/Asterisk.php new file mode 100644 index 00000000..effde5a5 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Asterisk.php @@ -0,0 +1,109 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as an asterisk (*) + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Asterisk extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x - $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x + $this->_size, + 'y1' => $y + $this->_size + ) + ); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x + $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x - $this->_size, + 'y1' => $y + $this->_size + ) + ); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x - $this->_size, + 'y0' => $y, + 'x1' => $x + $this->_size, + 'y1' => $y + ) + ); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x, + 'y0' => $y - $this->_size, + 'x1' => $x, + 'y1' => $y + $this->_size + ) + ); + + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Average.php b/packages/dspam/pear/Image/Graph/Marker/Average.php new file mode 100644 index 00000000..c4e3e7a4 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Average.php @@ -0,0 +1,91 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * A marker displaying the 'distance' to the datasets average value. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Average extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if ((isset($values['AVERAGE_Y'])) && + (is_a($this->_parent, 'Image_Graph_Plot'))) + { + $point = $this->_pointXY( + array( + 'X' => $values['APX'], + 'Y' => $values['AVERAGE_Y'] + ) + ); + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $point['X'], 'y1' => $point['Y'])); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $point['X'] - 2, + 'y0' => $point['Y'], + 'x1' => $point['X'] + 2, + 'y1' => $point['Y'] + ) + ); + } + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Box.php b/packages/dspam/pear/Image/Graph/Marker/Box.php new file mode 100644 index 00000000..5602c33d --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Box.php @@ -0,0 +1,76 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a box + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Box extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas + * @param array $values The values representing the data the marker 'points' to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $x - $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x + $this->_size, + 'y1' => $y + $this->_size + ) + ); + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Bubble.php b/packages/dspam/pear/Image/Graph/Marker/Bubble.php new file mode 100644 index 00000000..180ab4e3 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Bubble.php @@ -0,0 +1,91 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Circle.php + */ +require_once 'Image/Graph/Marker/Circle.php'; + +/** + * Display a circle with y-value percentage as radius (require GD2). + * + * This will display a circle centered on the datapoint with a radius calculated + * as a percentage of the maximum value. I.e. the radius depends on the y-value + * of the datapoint + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Bubble extends Image_Graph_Marker_Circle +{ + + /** + * The radius of the marker when 100% + * @var int + * @access private + */ + var $_size100Pct = 40; + + /** + * Sets the maximum radius the marker can occupy + * + * @param int $radius The new Image_Graph_max radius + */ + function setMaxRadius($radius) + { + $this->_size100Pct = $radius; + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_size = $this->_size100Pct*$values['PCT_MAX_Y']/100; + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Circle.php b/packages/dspam/pear/Image/Graph/Marker/Circle.php new file mode 100644 index 00000000..7eeb5cb6 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Circle.php @@ -0,0 +1,96 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as circle (require GD2) + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Circle extends Image_Graph_Marker +{ + + /** + * The 'size' of the marker, the meaning depends on the specific Marker + * implementation + * @var int + * @access private + */ + var $_size = 10; + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + + $dA = 2*pi()/($this->_size*2); + $angle = 0; + while ($angle < 2*pi()) { + $this->_canvas->addVertex(array('x' => + $x + $this->_size*cos($angle), 'y' => + $y - $this->_size*sin($angle) + )); + $angle += $dA; + } + + $this->_canvas->addVertex(array('x' => + $x + $this->_size*cos(0), 'y' => + $y - $this->_size*sin(0) + )); + + $this->_canvas->polygon(array('connect' => true)); + + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Cross.php b/packages/dspam/pear/Image/Graph/Marker/Cross.php new file mode 100644 index 00000000..720f3bb4 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Cross.php @@ -0,0 +1,114 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a cross. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Cross extends Image_Graph_Marker +{ + + /** + * The thickness of the plus in pixels (thickness is actually double this) + * @var int + * @access private + */ + var $_thickness = 2; + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas + * @param array $values The values representing the data the marker 'points' to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if ($this->_thickness > 0) { + $this->_getLineStyle(); + $this->_getFillStyle(); + + $d1 = round(0.7071067 * $this->_size); // cos/sin(45 de>) + $d2 = round(0.7071067 * $this->_thickness); // cos/sin(45 deg) + + $this->_canvas->addVertex(array('x' => $x - $d1 - $d2, 'y' => $y - $d1 + $d2)); + $this->_canvas->addVertex(array('x' => $x - $d1 + $d2, 'y' => $y - $d1 - $d2)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y - 2 * $d2)); + $this->_canvas->addVertex(array('x' => $x + $d1 - $d2, 'y' => $y - $d1 - $d2)); + $this->_canvas->addVertex(array('x' => $x + $d1 + $d2, 'y' => $y - $d1 + $d2)); + $this->_canvas->addVertex(array('x' => $x + 2 * $d2, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x + $d1 + $d2, 'y' => $y + $d1 - $d2)); + $this->_canvas->addVertex(array('x' => $x + $d1 - $d2, 'y' => $y + $d1 + $d2)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y + 2 * $d2)); + $this->_canvas->addVertex(array('x' => $x - $d1 + $d2, 'y' => $y + $d1 + $d2)); + $this->_canvas->addVertex(array('x' => $x - $d1 - $d2, 'y' => $y + $d1 - $d2)); + $this->_canvas->addVertex(array('x' => $x - 2 * $d2, 'y' => $y)); + $this->_canvas->polygon(array('connect' => true)); + } else { + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x - $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x + $this->_size, + 'y1' => $y + $this->_size + ) + ); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x + $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x - $this->_size, + 'y1' => $y + $this->_size + ) + ); + } + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Diamond.php b/packages/dspam/pear/Image/Graph/Marker/Diamond.php new file mode 100644 index 00000000..2a3d68c8 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Diamond.php @@ -0,0 +1,73 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a diamond. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Diamond extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas + * @param array $values The values representing the data the marker 'points' to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y + $this->_size)); + $this->_canvas->polygon(array('connect' => true)); + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Icon.php b/packages/dspam/pear/Image/Graph/Marker/Icon.php new file mode 100644 index 00000000..d9b9456f --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Icon.php @@ -0,0 +1,133 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker using an image as icon. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Icon extends Image_Graph_Marker +{ + + /** + * Filename of the image icon + * @var string + * @access private + */ + var $_filename; + + /** + * X Point of the icon to use as data 'center' + * @var int + * @access private + */ + var $_pointX = 0; + + /** + * Y Point of the icon to use as data 'center' + * @var int + * @access private + */ + var $_pointY = 0; + + /** + * Create an icon marker + * + * @param string $filename The filename of the icon + * @param int $width The 'new' width of the icon if it is to be resized + * @param int $height The 'new' height of the icon if it is to be resized + */ + function Image_Graph_Marker_Icon($filename, $width = 0, $height = 0) + { + parent::Image_Graph_Marker(); + $this->_filename = $filename; + } + + /** + * Set the X 'center' point of the marker + * + * @param int $x The X 'center' point of the marker + */ + function setPointX($x) + { + $this->_pointX = $x; + } + + /** + * Set the Y 'center' point of the marker + * + * @param int $y The Y 'center' point of the marker + */ + function setPointY($y) + { + $this->_pointY = $y; + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + parent::_drawMarker($x, $y, $values); + if ($this->_filename) { + $this->_canvas->image( + array( + 'x' => $x, + 'y' => $y, + 'filename' => $this->_filename, + 'alignment' => array('horizontal' => 'center', 'vertical' => 'center') + ) + ); + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Pinpoint.php b/packages/dspam/pear/Image/Graph/Marker/Pinpoint.php new file mode 100644 index 00000000..7b87f153 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Pinpoint.php @@ -0,0 +1,65 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Icon.php + */ +require_once 'Image/Graph/Marker/Icon.php'; + +/** + * Data marker using a pinpoint as marker. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Pinpoint extends Image_Graph_Marker_Icon +{ + + /** + * Create the marker as a pin point + */ + function Image_Graph_Marker_Pinpoint() + { + parent::Image_Graph_Marker_Icon( + dirname(__FILE__).'/../Images/Icons/pinpoint.png' + ); + $this->setPointX(0); + $this->setPointY(13); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Plus.php b/packages/dspam/pear/Image/Graph/Marker/Plus.php new file mode 100644 index 00000000..0a817cfc --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Plus.php @@ -0,0 +1,98 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a plus. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Plus extends Image_Graph_Marker +{ + + /** + * The thickness of the plus in pixels (thickness is actually double this) + * @var int + * @access private + */ + var $_thickness = 2; + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if ($this->_thickness > 0) { + $this->_getLineStyle(); + $this->_getFillStyle(); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y - $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y - $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y - $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y - $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y + $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y + $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y + $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y + $this->_thickness)); + $this->_canvas->polygon(array('connect' => true)); + } else { + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x - $this->_size, 'y0' => $y, 'x1' => $x + $this->_size, 'y1' => $y)); + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y - $this->_size, 'x1' => $x, 'y1' => $y + $this->_size)); + } + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Pointing.php b/packages/dspam/pear/Image/Graph/Marker/Pointing.php new file mode 100644 index 00000000..05ab94e4 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Pointing.php @@ -0,0 +1,140 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a 'pointing marker'. + * + * Points to the data using another marker (as start and/or end) + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Pointing extends Image_Graph_Marker +{ + + /** + * The starting marker + * @var Marker + * @access private + */ + var $_markerStart; + + /** + * The ending marker + * @var Marker + * @access private + */ + var $_markerEnd; + + /** + * The X offset from the 'data' + * @var int + * @access private + */ + var $_deltaX = -1; + + /** + * The Y offset from the 'data' + * @var int + * @access private + */ + var $_deltaY = -1; + + /** + * Create an pointing marker, ie a pin on a board + * + * @param int $deltaX The the X offset from the real 'data' point + * @param int $deltaY The the Y offset from the real 'data' point + * @param Marker $markerEnd The ending marker that represents 'the head of + * the pin' + */ + function Image_Graph_Marker_Pointing($deltaX, $deltaY, & $markerEnd) + { + parent::Image_Graph_Marker(); + $this->_deltaX = $deltaX; + $this->_deltaY = $deltaY; + $this->_markerStart = null; + $this->_markerEnd =& $markerEnd; + } + + /** + * Sets the starting marker, ie the tip of the pin on a board + * + * @param Marker $markerStart The starting marker that represents 'the tip + * of the pin' + */ + function setMarkerStart(& $markerStart) + { + $this->_markerStart =& $markerStart; + $this->_markerStart->_setParent($this); + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + parent::_drawMarker($x, $y, $values); + if ($this->_markerStart) { + $this->_markerStart->_setParent($this); + $this->_markerStart->_drawMarker($x, $y, $values); + } + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $this->_deltaX, 'y1' => $y + $this->_deltaY)); + $this->_markerEnd->_setParent($this); + $this->_markerEnd->_drawMarker( + $x + $this->_deltaX, + $y + $this->_deltaY, + $values + ); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Pointing/Angular.php b/packages/dspam/pear/Image/Graph/Marker/Pointing/Angular.php new file mode 100644 index 00000000..93b8b7cf --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Pointing/Angular.php @@ -0,0 +1,105 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Pointing.php + */ +require_once 'Image/Graph/Marker/Pointing.php'; + +/** + * Marker that points 'away' from the graph. + * + * Use this as a marker for displaying another marker pointing to the original + * point on the graph - where the 'pointer' is calculated as line orthogonal to + * a line drawn between the points neighbours to both sides (an approximate + * tangent). This should make an the pointer appear to point 'straight' out from + * the graph. The 'head' of the pointer is then another marker of any choice. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Pointing_Angular extends Image_Graph_Marker_Pointing +{ + + /** + * The length of the angular marker + * @var int + * @access private + */ + var $_radius; + + /** + * Image_Graph_AngularPointingMarker [Constructor] + * @param int $radius The 'length' of the pointer + * @param Marker $markerEnd The ending marker that represents 'the head of + * the pin' + */ + function Image_Graph_Marker_Pointing_Angular($radius, & $markerEnd) + { + parent::Image_Graph_Marker_Pointing(0, 0, $markerEnd); + $this->_radius = $radius; + } + + /** + * Draw the marker on the canvas + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if ((isset($values['LENGTH'])) && ($values['LENGTH'] != 0)) { + $this->_deltaX = - $values['AX'] * $this->_radius / $values['LENGTH']; + $this->_deltaY = - $values['AY'] * $this->_radius / $values['LENGTH']; + } + + if ((isset($values['NPY'])) && (isset($values['APY'])) && + (isset($values['PPY'])) && ($values['NPY'] > $values['APY']) && + ($values['PPY'] > $values['APY'])) + { + $this->_deltaX = - $this->_deltaX; + $this->_deltaY = - $this->_deltaY; + } + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Pointing/Radial.php b/packages/dspam/pear/Image/Graph/Marker/Pointing/Radial.php new file mode 100644 index 00000000..ce1a0aac --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Pointing/Radial.php @@ -0,0 +1,91 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Pointing.php + */ +require_once 'Image/Graph/Marker/Pointing.php'; + +/** + * A pointing marker in a random angle from the data + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Pointing_Radial extends Image_Graph_Marker_Pointing +{ + + /** + * The radius of the radial marker + * @var int + * @access private + */ + var $_radius; + + /** + * Create an radial pointing marker, ie a marker on a defined distance from + * the data + * @param int $radius The 'length' of the pointer + * @param Marker $markerEnd The ending marker that represents 'the head of + * the pin' + */ + function Image_Graph_Marker_Pointing_Radial($radius, & $markerEnd) + { + parent::Image_Graph_Marker_Pointing(0, 0, $markerEnd); + $this->_radius = $radius; + } + + /** + * Draw the marker on the canvas + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $angle = pi() * rand(0, 360) / 180; + $this->_deltaX = $this->_radius * cos($angle); + $this->_deltaY = $this->_radius * sin($angle); + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/ReversePinpoint.php b/packages/dspam/pear/Image/Graph/Marker/ReversePinpoint.php new file mode 100644 index 00000000..57e945ab --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/ReversePinpoint.php @@ -0,0 +1,65 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Icon.php + */ +require_once 'Image/Graph/Marker/Icon.php'; + +/** + * Data marker using a (reverse) pinpoint as marker. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_ReversePinpoint extends Image_Graph_Marker_Icon +{ + + /** + * Create the marker as a reverse pin point + */ + function Image_Graph_Marker_ReversePinpoint() + { + parent::Image_Graph_Marker_Icon( + dirname(__FILE__).'/../Images/Icons/pinpointr.png' + ); + $this->setPointX(10); + $this->setPointY(13); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Star.php b/packages/dspam/pear/Image/Graph/Marker/Star.php new file mode 100644 index 00000000..67b2b9b3 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Star.php @@ -0,0 +1,88 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a triangle. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Star extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + + $d = $this->_size / 5; + $x = round($x); + $y = round($y); + + $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + round($d), 'y' => $y - round($d))); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y - round($d))); + $this->_canvas->addVertex(array('x' => $x + round(2 * $d), 'y' => $y + round($d))); + $this->_canvas->addVertex(array('x' => $x + round(3 * $d), 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y + round(3 * $d))); + $this->_canvas->addVertex(array('x' => $x - round(3 * $d), 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x - round(2 * $d), 'y' => $y + round($d))); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y - round($d))); + $this->_canvas->addVertex(array('x' => $x - round($d), 'y' => $y - round($d))); + $this->_canvas->polygon(array('connect' => true)); + + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Triangle.php b/packages/dspam/pear/Image/Graph/Marker/Triangle.php new file mode 100644 index 00000000..626f2589 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Triangle.php @@ -0,0 +1,75 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a triangle. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Triangle extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y + $this->_size)); + $this->_canvas->polygon(array('connect' => true)); + parent::_drawMarker($x, $y, $values); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Marker/Value.php b/packages/dspam/pear/Image/Graph/Marker/Value.php new file mode 100644 index 00000000..24f142f3 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Marker/Value.php @@ -0,0 +1,214 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * A marker showing the data value. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @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/package/Image_Graph + */ +class Image_Graph_Marker_Value extends Image_Graph_Marker +{ + + /** + * Datapreproccesor to format the value + * @var DataPreprocessor + * @access private + */ + var $_dataPreprocessor = null; + + /** + * Which value to use from the data set, ie the X or Y value + * @var int + * @access private + */ + var $_useValue; + + /** + * Create a value marker, ie a box containing the value of the 'pointing + * data' + * + * @param int $useValue Defines which value to use from the dataset, i.e. the + * X or Y value + */ + function Image_Graph_Marker_Value($useValue = IMAGE_GRAPH_VALUE_X) + { + parent::Image_Graph_Marker(); + $this->_padding = array('left' => 2, 'top' => 2, 'right' => 2, 'bottom' => 2); + $this->_useValue = $useValue; + $this->_fillStyle = 'white'; + $this->_borderStyle = 'black'; + } + + /** + * Sets the background fill style of the element + * + * @param Image_Graph_Fill $background The background + * @see Image_Graph_Fill + */ + function setBackground(& $background) + { + $this->setFillStyle($background); + } + + /** + * Sets the background color of the element + * + * @param mixed $color The color + */ + function setBackgroundColor($color) + { + $this->setFillColor($color); + } + + /** + * Sets a data preprocessor for formatting the values + * + * @param DataPreprocessor $dataPreprocessor The data preprocessor + * @return Image_Graph_DataPreprocessor The data preprocessor + */ + function &setDataPreprocessor(& $dataPreprocessor) + { + $this->_dataPreprocessor =& $dataPreprocessor; + return $dataPreprocessor; + } + + /** + * Get the value to display + * + * @param array $values The values representing the data the marker 'points' + * to + * @return string The display value, this is the pre-preprocessor value, to + * support for customized with multiple values. i.e show 'x = y' or '(x, y)' + * @access private + */ + function _getDisplayValue($values) + { + switch ($this->_useValue) { + case IMAGE_GRAPH_VALUE_X: + $value = $values['X']; + break; + + case IMAGE_GRAPH_PCT_X_MIN: + $value = $values['PCT_MIN_X']; + break; + + case IMAGE_GRAPH_PCT_X_MAX: + $value = $values['PCT_MAX_X']; + break; + + case IMAGE_GRAPH_PCT_Y_MIN: + $value = $values['PCT_MIN_Y']; + break; + + case IMAGE_GRAPH_PCT_Y_MAX: + $value = $values['PCT_MAX_Y']; + break; + + case IMAGE_GRAPH_PCT_Y_TOTAL: + if (isset($values['SUM_Y'])) { + $value = 100 * $values['Y'] / $values['SUM_Y']; + } + else { + $value = 0; + } + break; + + case IMAGE_GRAPH_POINT_ID: + $value = $values['ID']; + break; + + default: + $value = $values['Y']; + break; + } + return $value; + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + parent::_drawMarker($x, $y, $values); + + $value = $this->_getDisplayValue($values); + + if ($this->_dataPreprocessor) { + $value = $this->_dataPreprocessor->_process($value); + } + + if ($this->_defaultFontOptions !== false) { + $this->_canvas->setFont($this->_defaultFontOptions); + } else { + $this->_canvas->setFont($this->_getFont()); + } + + $width = $this->_canvas->textWidth($value); + $height = $this->_canvas->textHeight($value); + $offsetX = $width/2 + $this->_padding['left']; + $offsetY = $height/2 + $this->_padding['top']; + + $this->_getFillStyle(); + $this->_getBorderStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $x - $offsetX, + 'y0' => $y - $offsetY, + 'x1' => $x + $offsetX, + 'y1' => $y + $offsetY + ) + ); + + $this->write($x, $y, $value, IMAGE_GRAPH_ALIGN_CENTER); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot.php b/packages/dspam/pear/Image/Graph/Plot.php new file mode 100644 index 00000000..4a6c16d3 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot.php @@ -0,0 +1,824 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea/Element.php + */ +require_once 'Image/Graph/Plotarea/Element.php'; + +/** + * Framework for a chart + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + * @abstract + */ +class Image_Graph_Plot extends Image_Graph_Plotarea_Element +{ + + /** + * The dataset to plot + * @var Dataset + * @access private + */ + var $_dataset; + + /** + * The marker to plot the data set as + * @var Marker + * @access private + */ + var $_marker = null; + + /** + * The dataselector to use for data marking + * @var DataSelector + * @access private + */ + var $_dataSelector = null; + + /** + * The Y axis to associate the plot with + * @var int + * @access private + */ + var $_axisY = IMAGE_GRAPH_AXIS_Y; + + /** + * The type of the plot if multiple datasets are used + * @var string + * @access private + */ + var $_multiType = 'normal'; + + /** + * The title of the plot, used for legending in case of simple plots + * @var string + * @access private + */ + var $_title = 'plot'; + + /** + * PlotType [Constructor] + * + * Valid values for multiType are: + * + * 'normal' Plot is normal, multiple datasets are displayes next to one + * another + * + * 'stacked' Datasets are stacked on top of each other + * + * 'stacked100pct' Datasets are stacked and displayed as percentages of the + * total sum + * + * I no title is specified a default is used, which is basically the plot + * type (fx. for a 'Image_Graph_Plot_Smoothed_Area' default title is + * 'Smoothed Area') + * + * @param Image_Graph_Dataset $dataset The data set (value containter) to + * plot or an array of datasets + * @param string $multiType The type of the plot + * @param string $title The title of the plot (used for legends, + * {@link Image_Graph_Legend}) + */ + function Image_Graph_Plot(& $dataset, $multiType = 'normal', $title = '') + { + if (!is_a($dataset, 'Image_Graph_Dataset')) { + if (is_array($dataset)) { + $keys = array_keys($dataset); + foreach ($keys as $key) { + if (!is_a($dataset[$key], 'Image_Graph_Dataset')) { + $this->_error('Invalid dataset passed to ' . get_class($this)); + } + } + unset($keys); + } else { + $this->_error('Invalid dataset passed to ' . get_class($this)); + } + } + + parent::Image_Graph_Common(); + if ($dataset) { + if (is_array($dataset)) { + $this->_dataset =& $dataset; + } else { + $this->_dataset = array(&$dataset); + } + } + if ($title) { + $this->_title = $title; + } else { + $this->_title = str_replace('_', ' ', substr(get_class($this), 17)); + } + + $multiType = strtolower($multiType); + if (($multiType == 'normal') || + ($multiType == 'stacked') || + ($multiType == 'stacked100pct')) + { + $this->_multiType = $multiType; + } else { + $this->_error( + 'Invalid multitype: ' . $multiType . + ' expected (normal|stacked|stacked100pct)' + ); + $this->_multiType = 'normal'; + } + } + + /** + * Sets the title of the plot, used for legend + * + * @param string $title The title of the plot + */ + function setTitle($title) + { + $this->_title = $title; + } + + /** + * Parses the URL mapping data in the point and adds it to the parameter array used by + * Image_Canvas + * + * @param array $point The data point (from the dataset) + * @param array $canvasData The The for the canvas method + * @return array The union of the canvas data points and the appropriate points for the dataset + * @access private + */ + function _mergeData($point, $canvasData) + { + if (isset($point['data'])) { + if (isset($point['data']['url'])) { + $canvasData['url'] = $point['data']['url']; + } + if (isset($point['data']['target'])) { + $canvasData['target'] = $point['data']['target']; + } + if (isset($point['data']['alt'])) { + $canvasData['alt'] = $point['data']['alt']; + } + if (isset($point['data']['htmltags'])) { + $canvasData['htmltags'] = $point['data']['htmltags']; + } + } + + return $canvasData; + } + + /** + * Sets the Y axis to plot the data + * + * @param int $axisY The Y axis (either IMAGE_GRAPH_AXIS_Y / 'y' or + * IMAGE_GRAPH_AXIS_Y_SECONDARY / 'ysec' (defaults to IMAGE_GRAPH_AXIS_Y)) + * @access private + */ + function _setAxisY($axisY) + { + if ($axisY == 'y') { + $this->_axisY = IMAGE_GRAPH_AXIS_Y; + } elseif ($axisY == 'ysec') { + $this->_axisY = IMAGE_GRAPH_AXIS_Y_SECONDARY; + } else { + $this->_axisY = $axisY; + } + } + + /** + * Sets the marker to 'display' data points on the graph + * + * @param Marker $marker The marker + */ + function &setMarker(& $marker) + { + $this->add($marker); + $this->_marker =& $marker; + return $marker; + } + + /** + * Sets the dataselector to specify which data should be displayed on the + * plot as markers and which are not + * + * @param DataSelector $dataSelector The dataselector + */ + function setDataSelector(& $dataSelector) + { + $this->_dataSelector =& $dataSelector; + } + + /** + * Calculate marker point data + * + * @param array Point The point to calculate data for + * @param array NextPoint The next point + * @param array PrevPoint The previous point + * @param array Totals The pre-calculated totals, if needed + * @return array An array containing marker point data + * @access private + */ + function _getMarkerData($point, $nextPoint, $prevPoint, & $totals) + { + if (is_array($this->_dataset)) { + if ($this->_multiType == 'stacked') { + if (!isset($totals['SUM_Y'])) { + $totals['SUM_Y'] = array(); + } + $x = $point['X']; + if (!isset($totals['SUM_Y'][$x])) { + $totals['SUM_Y'][$x] = 0; + } + } elseif ($this->_multiType == 'stacked100pct') { + $x = $point['X']; + if ($totals['TOTAL_Y'][$x] != 0) { + if (!isset($totals['SUM_Y'])) { + $totals['SUM_Y'] = array(); + } + if (!isset($totals['SUM_Y'][$x])) { + $totals['SUM_Y'][$x] = 0; + } + } + } + + if (isset($totals['ALL_SUM_Y'])) { + $point['SUM_Y'] = $totals['ALL_SUM_Y']; + } + + if (!$prevPoint) { + $point['AX'] = -5; + $point['AY'] = 5; + $point['PPX'] = 0; + $point['PPY'] = 0; + $point['NPX'] = $nextPoint['X']; + $point['NPY'] = $nextPoint['Y']; + } elseif (!$nextPoint) { + $point['AX'] = 5; + $point['AY'] = 5; + $point['PPX'] = $prevPoint['X']; + $point['PPY'] = $prevPoint['Y']; + $point['NPX'] = 0; + $point['NPY'] = 0; + } else { + $point['AX'] = $this->_pointY($prevPoint) - $this->_pointY($nextPoint); + $point['AY'] = $this->_pointX($nextPoint) - $this->_pointX($prevPoint); + $point['PPX'] = $prevPoint['X']; + $point['PPY'] = $prevPoint['Y']; + $point['NPX'] = $nextPoint['X']; + $point['NPY'] = $nextPoint['Y']; + } + + $point['APX'] = $point['X']; + $point['APY'] = $point['Y']; + + if ((isset($totals['MINIMUM_X'])) && ($totals['MINIMUM_X'] != 0)) { + $point['PCT_MIN_X'] = 100 * $point['X'] / $totals['MINIMUM_X']; + } + if ((isset($totals['MAXIMUM_X'])) && ($totals['MAXIMUM_X'] != 0)) { + $point['PCT_MAX_X'] = 100 * $point['X'] / $totals['MAXIMUM_X']; + } + + if ((isset($totals['MINIMUM_Y'])) && ($totals['MINIMUM_Y'] != 0)) { + $point['PCT_MIN_Y'] = 100 * $point['Y'] / $totals['MINIMUM_Y']; + } + if ((isset($totals['MAXIMUM_Y'])) && ($totals['MAXIMUM_Y'] != 0)) { + $point['PCT_MAX_Y'] = 100 * $point['Y'] / $totals['MAXIMUM_Y']; + } + + $point['LENGTH'] = sqrt($point['AX'] * $point['AX'] + + $point['AY'] * $point['AY']); + + if ((isset($point['LENGTH'])) && ($point['LENGTH'] != 0)) { + $point['ANGLE'] = asin($point['AY'] / $point['LENGTH']); + } + + if ((isset($point['AX'])) && ($point['AX'] > 0)) { + $point['ANGLE'] = pi() - $point['ANGLE']; + } + + if ($this->_parent->_horizontal) { + $point['MARKER_Y1'] = $this->_pointY($point) - + (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); + + $point['MARKER_Y2'] = $this->_pointY($point) + + (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); + + $point['COLUMN_WIDTH'] = abs($point['MARKER_Y2'] - + $point['MARKER_Y1']) / count($this->_dataset); + + $point['MARKER_Y'] = $point['MARKER_Y1'] + + ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) * + $point['COLUMN_WIDTH']; + + $point['MARKER_X'] = $this->_pointX($point); + + if ($this->_multiType == 'stacked') { + $point['MARKER_Y'] = + ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2; + + $P1 = array('Y' => $totals['SUM_Y'][$x]); + $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']); + + $point['MARKER_X'] = + ($this->_pointX($P1) + $this->_pointX($P2)) / 2; + } elseif ($this->_multiType == 'stacked100pct') { + $x = $point['X']; + if ($totals['TOTAL_Y'][$x] != 0) { + $point['MARKER_Y'] = + ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2; + + $P1 = array( + 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x] + ); + + $P2 = array( + 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x] + ); + + $point['MARKER_X'] = + ($this->_pointX($P1) + $this->_pointX($P2)) / 2; + } else { + $point = false; + } + } + } + else { + $point['MARKER_X1'] = $this->_pointX($point) - + (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); + + $point['MARKER_X2'] = $this->_pointX($point) + + (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); + + $point['COLUMN_WIDTH'] = abs($point['MARKER_X2'] - + $point['MARKER_X1']) / count($this->_dataset); + + $point['MARKER_X'] = $point['MARKER_X1'] + + ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) * + $point['COLUMN_WIDTH']; + + $point['MARKER_Y'] = $this->_pointY($point); + + if ($this->_multiType == 'stacked') { + $point['MARKER_X'] = + ($point['MARKER_X1'] + $point['MARKER_X2']) / 2; + + $P1 = array('Y' => $totals['SUM_Y'][$x]); + $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']); + + $point['MARKER_Y'] = + ($this->_pointY($P1) + $this->_pointY($P2)) / 2; + } elseif ($this->_multiType == 'stacked100pct') { + $x = $point['X']; + if ($totals['TOTAL_Y'][$x] != 0) { + $point['MARKER_X'] = + ($point['MARKER_X1'] + $point['MARKER_X2']) / 2; + + $P1 = array( + 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x] + ); + + $P2 = array( + 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x] + ); + + $point['MARKER_Y'] = + ($this->_pointY($P1) + $this->_pointY($P2)) / 2; + } else { + $point = false; + } + } + } + return $point; + } + } + + /** + * Draws markers on the canvas + * + * @access private + */ + function _drawMarker() + { + if (($this->_marker) && (is_array($this->_dataset))) { + $this->_canvas->startGroup(get_class($this) . '_marker'); + + $totals = $this->_getTotals(); + $totals['WIDTH'] = $this->width() / ($this->_maximumX() + 2) / 2; + + $number = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $totals['MINIMUM_X'] = $dataset->minimumX(); + $totals['MAXIMUM_X'] = $dataset->maximumX(); + $totals['MINIMUM_Y'] = $dataset->minimumY(); + $totals['MAXIMUM_Y'] = $dataset->maximumY(); + $totals['NUMBER'] = $number ++; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $prevPoint = $dataset->_nearby(-2); + $nextPoint = $dataset->_nearby(); + + $x = $point['X']; + $y = $point['Y']; + if (((!is_object($this->_dataSelector)) || + ($this->_dataSelector->_select($point))) && ($point['Y'] !== null)) + { + + $point = $this->_getMarkerData( + $point, + $nextPoint, + $prevPoint, + $totals + ); + + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + if (!isset($totals['SUM_Y'])) { + $totals['SUM_Y'] = array(); + } + if (isset($totals['SUM_Y'][$x])) { + $totals['SUM_Y'][$x] += $y; + } else { + $totals['SUM_Y'][$x] = $y; + } + } + } + unset($keys); + $this->_canvas->endGroup(); + } + } + + /** + * Get the minimum X value from the dataset + * + * @return double The minimum X value + * @access private + */ + function _minimumX() + { + if (!is_array($this->_dataset)) { + return 0; + } + + $min = false; + if (is_array($this->_dataset)) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + if ($min === false) { + $min = $this->_dataset[$key]->minimumX(); + } else { + $min = min($min, $this->_dataset[$key]->minimumX()); + } + } + unset($keys); + } + return $min; + } + + /** + * Get the maximum X value from the dataset + * + * @return double The maximum X value + * @access private + */ + function _maximumX() + { + if (!is_array($this->_dataset)) { + return 0; + } + + $max = 0; + if (is_array($this->_dataset)) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $max = max($max, $this->_dataset[$key]->maximumX()); + } + unset($keys); + } + return $max; + } + + /** + * Get the minimum Y value from the dataset + * + * @return double The minimum Y value + * @access private + */ + function _minimumY() + { + if (!is_array($this->_dataset)) { + return 0; + } + + $min = false; + if (is_array($this->_dataset)) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + if ($this->_multiType == 'normal') { + if ($min === false) { + $min = $this->_dataset[$key]->minimumY(); + } else { + $min = min($min, $this->_dataset[$key]->minimumY()); + } + } else { + if ($min === false) { + $min = 0; + } + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($point = $dataset->_next()) { + if ($point['Y'] < 0) { + $x = $point['X']; + if ((!isset($total)) || (!isset($total[$x]))) { + $total[$x] = $point['Y']; + } else { + $total[$x] += $point['Y']; + } + if (isset($min)) { + $min = min($min, $total[$x]); + } else { + $min = $total[$x]; + } + } + } + } + } + unset($keys); + } + return $min; + } + + /** + * Get the maximum Y value from the dataset + * + * @return double The maximum Y value + * @access private + */ + function _maximumY() + { + if ($this->_multiType == 'stacked100pct') { + return 100; + } + + $maxY = 0; + if (is_array($this->_dataset)) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + if ($this->_multiType == 'normal') { + if (isset($maxY)) { + $maxY = max($maxY, $dataset->maximumY()); + } else { + $maxY = $dataset->maximumY(); + } + } else { + $dataset->_reset(); + while ($point = $dataset->_next()) { + if ($point['Y'] > 0) { + $x = $point['X']; + if ((!isset($total)) || (!isset($total[$x]))) { + $total[$x] = $point['Y']; + } else { + $total[$x] += $point['Y']; + } + if (isset($maxY)) { + $maxY = max($maxY, $total[$x]); + } else { + $maxY = $total[$x]; + } + } + } + } + } + unset($keys); + } + return $maxY; + } + + /** + * Get the X pixel position represented by a value + * + * @param double $point The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($point) + { + $point['AXIS_Y'] = $this->_axisY; + return parent::_pointX($point); + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($point) + { + $point['AXIS_Y'] = $this->_axisY; + return parent::_pointY($point); + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + $this->_setCoords($this->_parent->_plotLeft, $this->_parent->_plotTop, $this->_parent->_plotRight, $this->_parent->_plotBottom); + parent::_updateCoords(); + } + + /** + * Get the dataset + * + * @return Image_Graph_Dataset The dataset(s) + */ + function &dataset() + { + return $this->_dataset; + } + + /** + * Calulate totals + * + * @return array An associated array with the totals + * @access private + */ + function _getTotals() + { + $total = array( + 'MINIMUM_X' => $this->_minimumX(), + 'MAXIMUM_X' => $this->_maximumX(), + 'MINIMUM_Y' => $this->_minimumY(), + 'MAXIMUM_Y' => $this->_maximumY() + ); + $total['ALL_SUM_Y'] = 0; + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + $dataset->_reset(); + while ($point = $dataset->_next()) { + $x = $point['X']; + + if (is_numeric($point['Y'])) { + $total['ALL_SUM_Y'] += $point['Y']; + if (isset($total['TOTAL_Y'][$x])) { + $total['TOTAL_Y'][$x] += $point['Y']; + } else { + $total['TOTAL_Y'][$x] = $point['Y']; + } + } + + if (is_numeric($point['X'])) { + if (isset($total['TOTAL_X'][$x])) { + $total['TOTAL_X'][$x] += $point['X']; + } else { + $total['TOTAL_X'][$x] = $point['X']; + } + } + } + } + unset($keys); + return $total; + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1)); + } + + /** + * Draw a sample for use with legend + * + * @param array $param The parameters for the legend + * @access private + */ + function _legendSample(&$param) + { + if (!is_array($this->_dataset)) { + return false; + } + + if (is_a($this->_fillStyle, 'Image_Graph_Fill')) { + $this->_fillStyle->_reset(); + } + + $count = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $count++; + + $caption = ($dataset->_name ? $dataset->_name : $this->_title); + + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height'] + 5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y']; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height']; + + if (!isset($param['simulate'])) { + $this->_getFillStyle($key); + $this->_getLineStyle(); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + if (($this->_marker) && ($dataset) && ($param['show_marker'])) { + $dataset->_reset(); + $point = $dataset->_next(); + $prevPoint = $dataset->_nearby(-2); + $nextPoint = $dataset->_nearby(); + + $tmp = array(); + $point = $this->_getMarkerData($point, $nextPoint, $prevPoint, $tmp); + if (is_array($point)) { + $point['MARKER_X'] = $x+$param['width']/2; + $point['MARKER_Y'] = $y; + unset ($point['AVERAGE_Y']); + $this->_marker->_drawMarker($point['MARKER_X'], $point['MARKER_Y'], $point); + } + } + $this->write($x + $param['width'] + 10, $y + $param['height'] / 2, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + unset($keys); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Area.php b/packages/dspam/pear/Image/Graph/Plot/Area.php new file mode 100644 index 00000000..a5288e1a --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Area.php @@ -0,0 +1,194 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Area Chart plot. + * + * An area chart plots all data points similar to a {@link + * Image_Graph_Plot_Line}, but the area beneath the line is filled and the whole + * area 'the-line', 'the right edge', 'the x-axis' and 'the left edge' is + * bounded. Smoothed charts are only supported with non-stacked types + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Area extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $dx = abs($x1 - $x0) / 3; + $dy = abs($y1 - $y0) / 3; + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1)); + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y0 + $dy)); + $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0)); + $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0 + 2*$dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y0 + $dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1)); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + $base = array(); + if ($this->_multiType == 'stacked') { + reset($this->_dataset); + $key = key($this->_dataset); + $dataset =& $this->_dataset[$key]; + + $first = $dataset->first(); + $point = array ('X' => $first['X'], 'Y' => '#min_pos#'); + $base[] = array(); + $base[] = $this->_pointY($point); + $first = $this->_pointX($point); + $base[] = $first; + + $last = $dataset->last(); + $point = array ('X' => $last['X'], 'Y' => '#min_pos#'); + $base[] = array(); + $base[] = $this->_pointY($point); + $base[] = $this->_pointX($point); + + $current = array(); + } + + $minYaxis = $this->_parent->_getMinimum($this->_axisY); + $maxYaxis = $this->_parent->_getMaximum($this->_axisY); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + if ($this->_multiType == 'stacked') { + $plotarea = array_reverse($base); + $base = array(); + while ($point = $dataset->_next()) { + $x = $point['X']; + $p = $point; + if (isset($current[$x])) { + $p['Y'] += $current[$x]; + } else { + $current[$x] = 0; + } + $x1 = $this->_pointX($p); + $y1 = $this->_pointY($p); + $plotarea[] = $x1; + $plotarea[] = $y1; + $plotarea[] = $point; + $base[] = array(); + $base[] = $y1; + $base[] = $x1; + $current[$x] += $point['Y']; + } + } else { + $first = true; + $plotarea = array(); + while ($point = $dataset->_next()) { + if ($first) { + $firstPoint = array ('X' => $point['X'], 'Y' => '#min_pos#'); + $plotarea[] = $this->_pointX($firstPoint); + $plotarea[] = $this->_pointY($firstPoint); + $plotarea[] = array(); + } + $plotarea[] = $this->_pointX($point); + $plotarea[] = $this->_pointY($point); + $plotarea[] = $point; + $lastPoint = $point; + $first = false; + } + $endPoint['X'] = $lastPoint['X']; + $endPoint['Y'] = '#min_pos#'; + $plotarea[] = $this->_pointX($endPoint); + $plotarea[] = $this->_pointY($endPoint); + $plotarea[] = array(); + } + + reset($plotarea); + while (list(, $x) = each($plotarea)) { + list(, $y) = each($plotarea); + list(, $data) = each($plotarea); + $this->_canvas->addVertex( + $this->_mergeData( + $data, + array('x' => $x, 'y' => $y) + ) + ); + } + + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true, 'map_vertices' => true)); + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + + $this->_canvas->endGroup(); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Band.php b/packages/dspam/pear/Image/Graph/Plot/Band.php new file mode 100644 index 00000000..3d5b629a --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Band.php @@ -0,0 +1,205 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * "Band" (area chart with min AND max) chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Plot_Band extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $h = abs($y1 - $y0) / 6; + $w = round(abs($x1 - $x0) / 5); + $y = ($y0 + $y1) / 2; + + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y - $h * 3)); + $this->_canvas->addVertex(array('x' => $x0 + $w, 'y' => $y - 4 * $h)); + $this->_canvas->addVertex(array('x' => $x0 + 2 * $w, 'y' => $y - $h * 2)); + $this->_canvas->addVertex(array('x' => $x0 + 3 * $w, 'y' => $y - $h * 4)); + $this->_canvas->addVertex(array('x' => $x0 + 4 * $w, 'y' => $y - $h * 3)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $h * 2)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y + $h * 3)); + $this->_canvas->addVertex(array('x' => $x0 + 4 * $w, 'y' => $y + $h)); + $this->_canvas->addVertex(array('x' => $x0 + 3 * $w, 'y' => $y + 2 * $h)); + $this->_canvas->addVertex(array('x' => $x0 + 2 * $w, 'y' => $y + 1 * $h)); + $this->_canvas->addVertex(array('x' => $x0 + 1 * $w, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y + $h)); + + $this->_getLineStyle(); + $this->_getFillStyle(); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $current = array(); + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $upperBand = array(); + $lowerBand = array(); + while ($data = $dataset->_next()) { + if ($this->_parent->_horizontal) { + $point['X'] = $data['X']; + + $point['Y'] = $data['Y']['high']; + $y = $this->_pointY($point); + $x_high = $this->_pointX($point); + + $point['Y'] = $data['Y']['low']; + $x_low = $this->_pointX($point); + + $data = array('X' => $x_high, 'Y' => $y); + if (isset($point['data'])) { + $data['data'] = $point['data']; + } else { + $data['data'] = array(); + } + $upperBand[] = $data; + + $data = array('X' => $x_low, 'Y' => $y); + if (isset($point['data'])) { + $data['data'] = $point['data']; + } else { + $data['data'] = array(); + } + $lowerBand[] = $data; + } + else { + $point['X'] = $data['X']; + $y = $data['Y']; + + $point['Y'] = $data['Y']['high']; + $x = $this->_pointX($point); + $y_high = $this->_pointY($point); + + $point['Y'] = $data['Y']['low']; + $y_low = $this->_pointY($point); + + $data = array('X' => $x, 'Y' => $y_high); + if (isset($point['data'])) { + $data['data'] = $point['data']; + } else { + $data['data'] = array(); + } + $upperBand[] = $data; + + $data = array('X' => $x, 'Y' => $y_low); + if (isset($point['data'])) { + $data['data'] = $point['data']; + } else { + $data['data'] = array(); + } + $lowerBand[] = $data; + } + } + $lowerBand = array_reverse($lowerBand); + foreach ($lowerBand as $point) { + $this->_canvas->addVertex( + $this->_mergeData( + $point['data'], + array('x' => $point['X'], 'y' => $point['Y']) + ) + ); + } + foreach ($upperBand as $point) { + $this->_canvas->addVertex( + $this->_mergeData( + $point['data'], + array('x' => $point['X'], 'y' => $point['Y']) + ) + ); + } + unset($upperBand); + unset($lowerBand); + + $this->_getLineStyle($key); + $this->_getFillStyle($key); + $this->_canvas->polygon(array('connect' => true, 'map_vertices' => true)); + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + + $this->_canvas->endGroup(); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Bar.php b/packages/dspam/pear/Image/Graph/Plot/Bar.php new file mode 100644 index 00000000..3e35f92c --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Bar.php @@ -0,0 +1,307 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * A bar chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Bar extends Image_Graph_Plot +{ + + /** + * The space between 2 bars (should be a multipla of 2) + * @var int + * @access private + */ + var $_space = 4; + + /** + * The width of the bars + * @var array + * @access private + */ + var $_width = 'auto'; + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $dx = abs($x1 - $x0) / 7; + $this->_canvas->rectangle(array('x0' => $x0 + $dx, 'y0' => $y0, 'x1' => $x1 - $dx, 'y1' => $y1)); + } + + /** + * Set the spacing between 2 neighbouring bars + * + * @param int $space The number of pixels between 2 bars, should be a + * multipla of 2 (ie an even number) + */ + function setSpacing($space) + { + $this->_space = (int) ($space / 2); + } + + /** + * Set the width of a bars. + * + * Specify 'auto' to auto calculate the width based on the positions on the + * x-axis. + * + * Supported units are: + * + * '%' The width is specified in percentage of the total plot width + * + * 'px' The width specified in pixels + * + * @param string $width The width of any bar + * @param string $unit The unit of the width + */ + function setBarWidth($width, $unit = false) + { + if ($width == 'auto') { + $this->_width = $width; + } else { + $this->_width = array( + 'width' => $width, + 'unit' => $unit + ); + } + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + if ($this->_width == 'auto') { + $width = $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2; + } elseif ($this->_width['unit'] == '%') { + $width = $this->_width['width'] * $this->width() / 200; + } elseif ($this->_width['unit'] == 'px') { + $width = $this->_width['width'] / 2; + } + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + + $minYaxis = $this->_parent->_getMinimum($this->_axisY); + $maxYaxis = $this->_parent->_getMaximum($this->_axisY); + + $number = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($point = $dataset->_next()) { + + if ($this->_parent->_horizontal) { + $y1 = $this->_pointY($point) - $width; + $y2 = $this->_pointY($point) + $width; + + if ($y2 - $this->_space > $y1 + $this->_space) { + /* + * Take bar spacing into account _only_ if the space doesn't + * turn the bar "inside-out", i.e. if the actual bar width + * is smaller than the space between the bars + */ + $y2 -= $this->_space; + $y1 += $this->_space; + } + } + else { + $x1 = $this->_pointX($point) - $width; + $x2 = $this->_pointX($point) + $width; + + if ($x2 - $this->_space > $x1 + $this->_space) { + /* + * Take bar spacing into account _only_ if the space doesn't + * turn the bar "inside-out", i.e. if the actual bar width + * is smaller than the space between the bars + */ + $x2 -= $this->_space; + $x1 += $this->_space; + } + } + + + if (($this->_multiType == 'stacked') || + ($this->_multiType == 'stacked100pct')) + { + $x = $point['X']; + + if ($point['Y'] >= 0) { + if (!isset($current[$x])) { + $current[$x] = 0; + } + + if ($this->_multiType == 'stacked') { + $p0 = array( + 'X' => $point['X'], + 'Y' => $current[$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => $current[$x] + $point['Y'] + ); + } else { + $p0 = array( + 'X' => $point['X'], + 'Y' => 100 * $current[$x] / $total['TOTAL_Y'][$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x] + ); + } + $current[$x] += $point['Y']; + } else { + if (!isset($currentNegative[$x])) { + $currentNegative[$x] = 0; + } + + $p0 = array( + 'X' => $point['X'], + 'Y' => $currentNegative[$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => $currentNegative[$x] + $point['Y'] + ); + $currentNegative[$x] += $point['Y']; + } + } else { + if (count($this->_dataset) > 1) { + $w = 2 * ($width - $this->_space) / count($this->_dataset); + if ($this->_parent->_horizontal) { + $y2 = ($y1 = ($y1 + $y2) / 2 - ($width - $this->_space) + $number * $w) + $w; + } + else { + $x2 = ($x1 = ($x1 + $x2) / 2 - ($width - $this->_space) + $number * $w) + $w; + } + } + $p0 = array('X' => $point['X'], 'Y' => 0); + $p1 = $point; + } + + if ((($minY = min($p0['Y'], $p1['Y'])) < $maxYaxis) && + (($maxY = max($p0['Y'], $p1['Y'])) > $minYaxis) + ) { + $p0['Y'] = $minY; + $p1['Y'] = $maxY; + + if ($p0['Y'] < $minYaxis) { + $p0['Y'] = '#min_pos#'; + } + if ($p1['Y'] > $maxYaxis) { + $p1['Y'] = '#max_neg#'; + } + + if ($this->_parent->_horizontal) { + $x1 = $this->_pointX($p0); + $x2 = $this->_pointX($p1); + } + else { + $y1 = $this->_pointY($p0); + $y2 = $this->_pointY($p1); + } + + $ID = $point['ID']; + if (($ID === false) && (count($this->_dataset) > 1)) { + $ID = $key; + } + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + + if (($y1 != $y2) && ($x1 != $x2)) { + $this->_canvas->rectangle( + $this->_mergeData( + $point, + array( + 'x0' => min($x1, $x2), + 'y0' => min($y1, $y2), + 'x1' => max($x1, $x2), + 'y1' => max($y1, $y2) + ) + ) + ); + } + } + } + $number ++; + } + unset($keys); + + $this->_drawMarker(); + + $this->_clip(false); + + $this->_canvas->endGroup(); + + return true; + } +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/BoxWhisker.php b/packages/dspam/pear/Image/Graph/Plot/BoxWhisker.php new file mode 100644 index 00000000..59c1ee44 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/BoxWhisker.php @@ -0,0 +1,298 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Box & Whisker chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Plot_BoxWhisker extends Image_Graph_Plot +{ + /** + * Whisker circle size + * @var int + * @access private + */ + var $_whiskerSize = false; + + /** + * Draws a box & whisker + * + * @param int $x The x position + * @param int $w The width of the box + * @param int $r The radius of the circle markers + * @param int $y_min The Y position of the minimum value + * @param int $y_q1 The Y position of the median of the first quartile + * @param int $y_med The Y position of the median + * @param int $y_q3 The Y position of the median of the third quartile + * @param int $y_max The Y position of the maximum value + * @param int $key The ID tag + * @access private + */ + function _drawBoxWhiskerV($x, $w, $r, $y_min, $y_q1, $y_med, $y_q3, $y_max, $key = false) + { + // draw circles + $this->_getLineStyle(); + $this->_getFillStyle('min'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_min, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('quartile1'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_q1, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('median'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_med, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('quartile3'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_q3, $r, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('max'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_max, $r, 'rx' => $r, 'ry' => $r)); + + // draw box and lines + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y_min, 'x1' => $x, 'y1' => $y_q1)); + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y_q3, 'x1' => $x, 'y1' => $y_max)); + + $this->_getLineStyle(); + $this->_getFillStyle('box'); + $this->_canvas->rectangle(array('x0' => $x - $w, 'y0' => $y_q1, 'x1' => $x + $w, 'y1' => $y_q3)); + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x - $w, 'y0' => $y_med, 'x1' => $x + $w, 'y1' => $y_med)); + } + + /** + * Draws a box & whisker + * + * @param int $y The x position + * @param int $h The width of the box + * @param int $r The radius of the circle markers + * @param int $x_min The Y position of the minimum value + * @param int $x_q1 The Y position of the median of the first quartile + * @param int $x_med The Y position of the median + * @param int $x_q3 The Y position of the median of the third quartile + * @param int $x_max The Y position of the maximum value + * @param int $key The ID tag + * @access private + */ + function _drawBoxWhiskerH($y, $h, $r, $x_min, $x_q1, $x_med, $x_q3, $x_max, $key = false) + { + // draw circles + $this->_getLineStyle(); + $this->_getFillStyle('min'); + $this->_canvas->ellipse(array('x' => $x_min, 'y' => $y, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('quartile1'); + $this->_canvas->ellipse(array('x' => $x_q1, 'y' => $y, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('median'); + $this->_canvas->ellipse(array('x' => $x_med, 'y' => $y, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('quartile3'); + $this->_canvas->ellipse(array('x' => $x_q3, 'y' => $y, $r, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('max'); + $this->_canvas->ellipse(array('x' => $x_max, 'y' => $y, $r, 'rx' => $r, 'ry' => $r)); + + // draw box and lines + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x_min, 'y0' => $y, 'x1' => $x_q1, 'y1' => $y)); + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x_q3, 'y0' => $y, 'x1' => $x_max, 'y1' => $y)); + + $this->_getLineStyle(); + $this->_getFillStyle('box'); + $this->_canvas->rectangle(array('x0' => $x_q1, 'y0' => $y - $h, 'x1' => $x_q3, 'y1' => $y + $h)); + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x_med, 'y0' => $y - $h, 'x1' => $x_med, 'y1' => $y + $h)); + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $x = round(($x0 + $x1) / 2); + $h = abs($y1 - $y0) / 9; + $w = round(abs($x1 - $x0) / 5); + $r = 2;//round(abs($x1 - $x0) / 13); + $this->_drawBoxWhiskerV($x, $w, $r, $y1, $y1 - 2 * $h, $y1 - 4 * $h, $y0 + 3 * $h, $y0); + } + + /** + * Sets the whisker circle size + * + * @param int $size Size (radius) of the whisker circle/dot + */ + function setWhiskerSize($size = false) + { + $this->_whiskerSize = $size; + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + $current = array(); + $number = 0; + $width = floor(0.5 * $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2); + + if ($this->_whiskerSize !== false) { + $r = $this->_whiskerSize; + } else { + $r = min(5, $width / 10); + } + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($data = $dataset->_next()) { + if ($this->_parent->_horizontal) { + $point['X'] = $data['X']; + $y = $data['Y']; + + $min = min($y); + $max = max($y); + $q1 = $dataset->_median($y, 'first'); + $med = $dataset->_median($y, 'second'); + $q3 = $dataset->_median($y, 'third'); + + $point['Y'] = $min; + $y = $this->_pointY($point); + $x_min = $this->_pointX($point); + + $point['Y'] = $max; + $x_max = $this->_pointX($point); + + $point['Y'] = $q1; + $x_q1 = $this->_pointX($point); + + $point['Y'] = $med; + $x_med = $this->_pointX($point); + + $point['Y'] = $q3; + $x_q3 = $this->_pointX($point); + + $this->_drawBoxWhiskerH($y, $width, $r, $x_min, $x_q1, $x_med, $x_q3, $x_max, $key); + } + else { + $point['X'] = $data['X']; + $y = $data['Y']; + + $min = min($y); + $max = max($y); + $q1 = $dataset->_median($y, 'first'); + $med = $dataset->_median($y, 'second'); + $q3 = $dataset->_median($y, 'third'); + + $point['Y'] = $min; + $x = $this->_pointX($point); + $y_min = $this->_pointY($point); + + $point['Y'] = $max; + $y_max = $this->_pointY($point); + + $point['Y'] = $q1; + $y_q1 = $this->_pointY($point); + + $point['Y'] = $med; + $y_med = $this->_pointY($point); + + $point['Y'] = $q3; + $y_q3 = $this->_pointY($point); + + $this->_drawBoxWhiskerV($x, $width, $r, $y_min, $y_q1, $y_med, $y_q3, $y_max, $key); + } + } + } + unset($keys); + $this->_drawMarker(); + + $this->_clip(false); + + $this->_canvas->endGroup(); + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/CandleStick.php b/packages/dspam/pear/Image/Graph/Plot/CandleStick.php new file mode 100644 index 00000000..b050aea1 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/CandleStick.php @@ -0,0 +1,251 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Candlestick chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Plot_CandleStick extends Image_Graph_Plot +{ + + /** + * (Add basic description here) + * + * @access private + */ + function _drawCandleStickH($y, $h, $x_min, $x_open, $x_close, $x_max, $ID) + { + $this->_getLineStyle($ID); + $this->_canvas->line( + array( + 'x0' => min($x_open, $x_close), + 'y0' => $y, + 'x1' => $x_min, + 'y1' => $y + ) + ); + $this->_getLineStyle($ID); + $this->_canvas->line( + array( + 'x0' => max($x_open, $x_close), + 'y0' => $y, + 'x1' => $x_max, + 'y1' => $y + ) + ); + + $this->_getLineStyle($ID); + $this->_getFillStyle($ID); + $this->_canvas->rectangle( + array( + 'x0' => min($x_open, $x_close), + 'y0' => $y - $h, + 'x1' => max($x_open, $x_close), + 'y1' => $y + $h + ) + ); + } + + /** + * (Add basic description here) + * + * @access private + */ + function _drawCandleStickV($x, $w, $y_min, $y_open, $y_close, $y_max, $ID) + { + $this->_getLineStyle($ID); + $this->_canvas->line( + array( + 'x0' => $x, + 'y0' => min($y_open, $y_close), + 'x1' => $x, + 'y1' => $y_max + ) + ); + $this->_getLineStyle($ID); + $this->_canvas->line( + array( + 'x0' => $x, + 'y0' => max($y_open, $y_close), + 'x1' => $x, + 'y1' => $y_min + ) + ); + + $this->_getLineStyle($ID); + $this->_getFillStyle($ID); + $this->_canvas->rectangle( + array( + 'x0' => $x - $w, + 'y0' => min($y_open, $y_close), + 'x1' => $x + $w, + 'y1' => max($y_open, $y_close) + ) + ); + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $x = round(($x0 + $x1) / 2); + $h = abs($y1 - $y0) / 4; + $w = round(abs($x1 - $x0) / 5); + $this->_drawCandleStickV($x, $w, $y1, $y1 - $h, $y0 + $h, $y0, 'green'); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + $current = array(); + $number = 0; + $width = floor(0.8 * $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2); + + $lastClosed = false; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($data = $dataset->_next()) { + if ($this->_parent->_horizontal) { + $point['X'] = $data['X']; + //$y = $data['Y']; + + if (isset($data['Y']['open'])) { + $point['Y'] = $data['Y']['open']; + } else { + $point['Y'] = $lastClosed; + } + $y = $this->_pointY($point); + $x_open = $this->_pointX($point); + + $lastClosed = $point['Y'] = $data['Y']['close']; + $x_close = $this->_pointX($point); + + $point['Y'] = $data['Y']['min']; + $x_min = $this->_pointX($point); + + $point['Y'] = $data['Y']['max']; + $x_max = $this->_pointX($point); + + if ($data['Y']['close'] < $data['Y']['open']) { + $ID = 'red'; + } else { + $ID = 'green'; + } + + $this->_drawCandleStickH($y, $width, $x_min, $x_open, $x_close, $x_max, $ID); + } + else { + $point['X'] = $data['X']; + //$y = $data['Y']; + + if (isset($data['Y']['open'])) { + $point['Y'] = $data['Y']['open']; + } else { + $point['Y'] = $lastClosed; + } + $x = $this->_pointX($point); + $y_open = $this->_pointY($point); + + $lastClosed = $point['Y'] = $data['Y']['close']; + $y_close = $this->_pointY($point); + + $point['Y'] = $data['Y']['min']; + $y_min = $this->_pointY($point); + + $point['Y'] = $data['Y']['max']; + $y_max = $this->_pointY($point); + + if ($data['Y']['close'] < $data['Y']['open']) { + $ID = 'red'; + } else { + $ID = 'green'; + } + + $this->_drawCandleStickV($x, $width, $y_min, $y_open, $y_close, $y_max, $ID); + } + } + } + unset($keys); + $this->_drawMarker(); + + $this->_clip(false); + + $this->_canvas->endGroup($this->_title); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Dot.php b/packages/dspam/pear/Image/Graph/Plot/Dot.php new file mode 100644 index 00000000..19352567 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Dot.php @@ -0,0 +1,99 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Dot / scatter chart (only marker). + * + * This plot type only displays a {@link Image_Graph_Marker} for the datapoints. + * The marker must explicitly be defined using {@link Image_Graph_Plot:: + * setMarker()}. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Dot extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + if (isset($this->_marker)) { + $key = key($this->_dataset); + $samplePoint = $this->_dataset[$key]->_nearby(); + $this->_marker->_drawMarker(($x0 + $x1) / 2, ($y0 + $y1) / 2, $samplePoint); + } + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (Image_Graph_Plot::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + $this->_drawMarker(); + + $this->_clip(false); + + $this->_canvas->endGroup(); + + return true; + } +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Fit/Line.php b/packages/dspam/pear/Image/Graph/Plot/Fit/Line.php new file mode 100644 index 00000000..07f3b9cc --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Fit/Line.php @@ -0,0 +1,118 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Include file Image/Graph/Tool.php + */ +require_once 'Image/Graph/Tool.php'; + +/** + * Fit the graph (to a line using linear regression). + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Fit_Line extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $y = ($y0 + $y1) / 2; + $dy = abs($y1 - $y0) / 6; + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y + $dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $dy)); + $this->_canvas->polygon(array('connect' => false)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (Image_Graph_Plot::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $data = array(); + while ($point = $dataset->_next()) { + $data[] = array( + 'X' => $this->_pointX($point), + 'Y' => $this->_pointY($point) + ); + } + + $regression = Image_Graph_Tool::calculateLinearRegression($data); + $this->_getLineStyle($key); + $this->_canvas->line( + array( + 'x0' => $this->_left, + 'y0' => $this->_left * $regression['slope'] + $regression['intersection'], + 'x1' => $this->_right, + 'y1' => $this->_right * $regression['slope'] + $regression['intersection'] + ) + ); + } + $this->_clip(false); + $this->_canvas->endGroup(); + + return true; + } +} + +?> diff --git a/packages/dspam/pear/Image/Graph/Plot/Impulse.php b/packages/dspam/pear/Image/Graph/Plot/Impulse.php new file mode 100644 index 00000000..91372cd1 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Impulse.php @@ -0,0 +1,204 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Impulse chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Impulse extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $x = ($x0 + $x1) / 2; + $this->_canvas->line(array('x0' => $x, 'y0' => $y0, 'x1' => $x, 'y1' => $y1)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + $current = array(); + $number = 0; + + $minYaxis = $this->_parent->_getMinimum($this->_axisY); + $maxYaxis = $this->_parent->_getMaximum($this->_axisY); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $x0 = $this->_pointX($point); + if (($this->_multiType == 'stacked') || + ($this->_multiType == 'stacked100pct')) + { + $x = $point['X']; + + if ($point['Y'] >= 0) { + if (!isset($current[$x])) { + $current[$x] = 0; + } + + if ($this->_multiType == 'stacked') { + $p0 = array( + 'X' => $point['X'], + 'Y' => $current[$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => $current[$x] + $point['Y'] + ); + } else { + $p0 = array( + 'X' => $point['X'], + 'Y' => 100 * $current[$x] / $total['TOTAL_Y'][$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x] + ); + } + $current[$x] += $point['Y']; + } else { + if (!isset($currentNegative[$x])) { + $currentNegative[$x] = 0; + } + + $p0 = array( + 'X' => $point['X'], + 'Y' => $currentNegative[$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => $currentNegative[$x] + $point['Y'] + ); + $currentNegative[$x] += $point['Y']; + } + } else { + $p0 = array('X' => $point['X'], 'Y' => 0); + $p1 = $point; + } + + if ((($minY = min($p0['Y'], $p1['Y'])) < $maxYaxis) && + (($maxY = max($p0['Y'], $p1['Y'])) > $minYaxis) + ) { + $p0['Y'] = $minY; + $p1['Y'] = $maxY; + + if ($p0['Y'] < $minYaxis) { + $p0['Y'] = '#min_pos#'; + } + if ($p1['Y'] > $maxYaxis) { + $p1['Y'] = '#max_neg#'; + } + + $x1 = $this->_pointX($p0); + $y1 = $this->_pointY($p0); + + $x2 = $this->_pointX($p1); + $y2 = $this->_pointY($p1); + + if ($this->_multiType == 'normal') { + $offset = 5*$number; + $x1 += $offset; + $x2 += $offset; + } + + $ID = $point['ID']; + if (($ID === false) && (count($this->_dataset) > 1)) { + $ID = $key; + } + $this->_getLineStyle($key); + $this->_canvas->line( + $this->_mergeData( + $point, + array( + 'x0' => $x1, + 'y0' => $y1, + 'x1' => $x2, + 'y1' => $y2 + ) + ) + ); + } + } + $number++; + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Line.php b/packages/dspam/pear/Image/Graph/Plot/Line.php new file mode 100644 index 00000000..009b4e1f --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Line.php @@ -0,0 +1,171 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Linechart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Line extends Image_Graph_Plot +{ + + /** + * Gets the fill style of the element + * + * @return int A GD filestyle representing the fill style + * @see Image_Graph_Fill + * @access private + */ + function _getFillStyle($ID = false) + { + return IMG_COLOR_TRANSPARENT; + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $y = ($y0 + $y1) / 2; + $dx = abs($x1 - $x0) / 3; + $dy = abs($y1 - $y0) / 5; + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y - $dy * 2)); + $this->_canvas->addVertex(array('x' => $x1 - $dx, 'y' => $y + $dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $dy)); + $this->_canvas->polygon(array('connect' => false)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + reset($this->_dataset); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + + $p1 = false; + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $numPoints = 0; + while ($point = $dataset->_next()) { + if (($this->_multiType == 'stacked') || + ($this->_multiType == 'stacked100pct')) + { + $x = $point['X']; + if (!isset($current[$x])) { + $current[$x] = 0; + } + if ($this->_multiType == 'stacked') { + $py = $current[$x] + $point['Y']; + } else { + $py = 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x]; + } + $current[$x] += $point['Y']; + $point['Y'] = $py; + } + + if ($point['Y'] === null) { + if ($numPoints > 1) { + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); + } + else { + $this->_canvas->reset(); + } + $numPoints = 0; + } else { + $p2['X'] = $this->_pointX($point); + $p2['Y'] = $this->_pointY($point); + + $this->_canvas->addVertex( + $this->_mergeData( + $point, + array('x' => $p2['X'], 'y' => $p2['Y']) + ) + ); + $numPoints++; + } + } + if ($numPoints > 1) { + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); + } + else { + $this->_canvas->reset(); + } + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Odo.php b/packages/dspam/pear/Image/Graph/Plot/Odo.php new file mode 100644 index 00000000..d6bf7969 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Odo.php @@ -0,0 +1,719 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Include file Image/Graph/Tool.php + */ +require_once 'Image/Graph/Tool.php'; + +/** + * 2D Odochart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Maxime Delorme + * @copyright Copyright (C) 2005 Maxime Delorme + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Odo extends Image_Graph_Plot +{ + /** + * the percent of the radius of the chart that will be use as the width of the range + * @access private + * @var int + */ + var $_radiusPercent = 50; + + /** + * the minimun value of the chart or the start value + * @access private + * @var int + */ + var $_value_min = 0; + + /** + * the maximum value of the chart or the end value + * @access private + * @var int + */ + var $_value_max = 100; + + /** + * the start angle + * @access private + * @var int + */ + var $_deg_offset = 135; + + /** + * the angle of the chart , the length of the chart + * 180 min a half circle + * @access private + * @var int + */ + var $_deg_width = 270; + + /** + * the length of the big ticks + * the small ones will be half ot it, the values 160% of it + * 180 min a half circle + * @access private + * @var int + */ + var $_tickLength = 14; + + /** + * how many small ticks a big tick appears + * the small ticks appear every 6° + * so with the default value of 5, every 30° there is a value and a big tick + * 180 min a half circle + * @access private + * @var int + */ + var $_axisTicks = 5; + + /** + * Arrow marker + * @access private + * @var Image_Graph_Marker + */ + var $_arrowMarker; + + /** + * Range marker fill style + * @access private + * @var Image_Graph_Fill + */ + var $_rangeFillStyle = null; + + /** + * The width of the arrow + * @access private + * @var int + */ + var $_arrowWidth = 5; + + /** + * The length of the arrow + * @access private + * @var int + */ + var $_arrowLength = 80; + + /** + * The radius of the plot + * @access private + * @var int + */ + var $_radius = false; + + /** + * The total Y + * @access private + * @var int + */ + var $_totalY = false; + + /** + * Center X of odometer "circle" + * @access private + * @var int + */ + var $_centerX = false; + + /** + * Center y of odometer "circle" + * @access private + * @var int + */ + var $_centerY = false; + + /** + * Plot_Odo [Constructor] + * + * dataset with one data per arrow + * @param Image_Graph_Dataset $dataset The data set (value containter) to + * plot or an array of datasets + * {@link Image_Graph_Legend} + */ + function Image_Graph_Plot_Odo(&$dataset) + { + parent::Image_Graph_Plot($dataset); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + if (isset($min)) { + $min = min($dataset->minimumY(), $min); + } + else { + $min = $dataset->minimumY(); + } + if (isset($max)) { + $max = max($dataset->maximumY(), $max); + } + else { + $max = $dataset->maximumY(); + } + } + $this->_value_min = $min; + $this->_value_max = $max; + } + + /** + * Set the center of the odometer + * + * @param int $centerX The center x point + * @param int $centerY The center y point + */ + function setCenter($centerX, $centerY) + { + $this->_centerX = $centerX; + $this->_centerY = $centerY; + } + + /** + * Convert a value to the angle position onto the odometer + * + * @access private + * @param int $value the value to convert + * @return int the angle'position onto the odometer + */ + function _value2angle($value) + { + return $this->_deg_width * (($value - $this->_value_min) / $this->_totalY) + $this->_deg_offset; + } + + /** + * set some internal var + * + * @access private + */ + function _initialize() + { + $v1 = $this->_deg_offset; + $v2 = $this->_deg_offset + $this->_deg_width; + + $dimensions = Image_Graph_Tool::calculateArcDimensionAndCenter($v1, $v2); + + $radiusX = ($this->width() / 2) / $dimensions['rx']; + $radiusY = ($this->height() / 2) / $dimensions['ry']; + + $this->_radius = min($radiusX, $radiusY); + + if ($this->_marker) { + $this->_radius = $this->_radius * 0.85; + } + + //the center of the plot + if ($this->_centerX === false) { + $this->_centerX = (int) (($this->_left + $this->_right) / 2) + + $this->_radius * ($dimensions['cx'] - 0.5); + } + + if ($this->_centerY === false) { + $this->_centerY = (int) (($this->_top + $this->_bottom) / 2) + + $this->_radius * ($dimensions['cy'] - 0.5); + } + + //the max range + $this->_totalY = abs($this->_value_max - $this->_value_min); + } + + /** + * set min and max value of the range + * + * @access public + * @param integer $value_min the minimun value of the chart or the start value + * @param integer $value_max the maximum value of the chart or the end value + */ + function setRange($value_min, $value_max) + { + $this->_value_min = $value_min; + $this->_value_max = $value_max; + } + + /** + * Set start's angle and amplitude of the chart + * + * @access public + * @param integer $deg_offset the start angle + * @param integer $deg_width the angle of the chart (the length) + */ + function setAngles($deg_offset, $deg_width) + { + $this->_deg_offset = min(360, abs($deg_offset)); + $this->_deg_width = min(360, abs($deg_width)); + } + + /** + * set the width of the chart + * + * @access public + * @param string $radius_percent a value between 0 and 100 + */ + function setRadiusWidth($radius_percent) + { + $this->_radiusPercent = $radius_percent; + } + + /** + * set the width and length of the arrow (in percent of the total plot "radius") + * + * @param int length The length in percent + * @param int width The width in percent + */ + function setArrowSize($length, $width) + { + $this->_arrowWidth = max(0, min(100, $width)); + $this->_arrowLength = max(0, min(100, $length)); + } + + /** + * Set the arrow marker + * @param Image_Graph_Marker $marker The marker to set for arrow marker + */ + function setArrowMarker(&$marker) + { + $this->_arrowMarker =& $marker; + } + + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + $this->_initialize(); + $this->_drawRange(); + $this->_drawAxis(); + $this->_drawArrow(); + $this->_drawMarker(); + return true; + } + + /** + * set the length of the ticks + * + * @access public + * @param string $radius_percent a value between 0 and 100 + */ + function setTickLength($radius) + { + $this->_tickLength = $radius; + } + + /** + * set the length of the ticks + * + * @access public + * @param string $radius_percent a value between 0 and 100 + */ + function setAxisTicks($int) + { + $this->_axisTicks = $int; + } + + /** + * Draw the outline and the axis + * + * @access private + */ + function _drawAxis() + { + //draw outline + $this->_getLineStyle(); + $this->_canvas->pieslice( + array( + 'x' => $this->_centerX, + 'y' => $this->_centerY, + 'rx' => $this->_radius, + 'ry' => $this->_radius, + 'v1' => $this->_deg_offset, + 'v2' => $this->_deg_offset+$this->_deg_width, + 'srx' => $this->_radius * (1 - $this->_radiusPercent / 100), + 'sry' => $this->_radius * (1 - $this->_radiusPercent / 100) + ) + ); + + //step for every 6° + $step = (int) ($this->_totalY / $this->_deg_width * 6); + $value = $this->_value_min; + $i = 0; + while ($value <= $this->_value_max) { + $angle = $this->_value2angle($value); + + $cos = cos(deg2rad($angle)); + $sin = sin(deg2rad($angle)); + $point = array('Y' => $value); + $point['AX'] = $cos; + $point['AY'] = $sin; + $point['LENGTH'] = 1; + $x = $this->_centerX + $this->_radius * $cos; + $y = $this->_centerY + $this->_radius * $sin; + $deltaX = - $cos * $this->_tickLength ; + $deltaY = - $sin * $this->_tickLength ; + $this->_getLineStyle(); + if(($i % $this->_axisTicks) == 0){ + $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $deltaX, 'y1' => $y + $deltaY)); + if ($this->_arrowMarker) { + $this->_arrowMarker->_drawMarker($x + $deltaX * 1.6, $y + $deltaY *1.6, $point); + } + } else { + $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $deltaX * 0.5, 'y1' => $y + $deltaY * 0.5)); + } + $i++; + $value += $step; + } + + } + + /** + * Set the line style of the arrows + * + * @param Image_Graph_Line $lineStyle The line style of the Arrow + * @see Image_Graph_Line + * @access public + */ + function setArrowLineStyle($lineStyle) + { + $this->_arrowLineStyle = &$lineStyle; + } + + /** + * Set the fillstyle of the arrows + * + * @param Image_Graph_Fill $fillStyle The fill style of the arrows + * @see Image_Graph_Fill + * @access public + */ + function setArrowFillStyle($fillStyle) + { + $this->_arrowFillStyle = &$fillStyle; + } + + /** + * Draw the arrows + * + * @access private + */ + function _drawArrow() + { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $this->setLineStyle($this->_arrowLineStyle); + $this->setFillStyle($this->_arrowFillStyle); + while ($point = $dataset->_next()) { + $ID = $point['ID']; + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + $deg = $this->_value2angle($point['Y']); + list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX + $this->_arrowLength * $this->_radius / 100, $this->_centerY, $this->_centerX, $this->_centerY, $deg); + $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); + list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX, $this->_centerY - $this->_arrowWidth * $this->_radius/100, $this->_centerX, $this->_centerY, $deg); + $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); + list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX - $this->_arrowWidth * $this->_radius / 100, $this->_centerY, $this->_centerX, $this->_centerY, $deg); + $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); + list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX,$this->_centerY + $this->_arrowWidth * $this->_radius / 100, $this->_centerX, $this->_centerY, $deg); + $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); + $this->_canvas->polygon(array('connect' => true)); + } + } + } + + /** + * Calculate marker point data + * + * @param array $point The point to calculate data for + * @param array $nextPoint The next point + * @param array $prevPoint The previous point + * @param array $totals The pre-calculated totals, if needed + * @return array An array containing marker point data + * @access private + */ + function _getMarkerData($point, $nextPoint, $prevPoint, &$totals) + { + $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals); + + $point['ANGLE'] = $this->_value2angle($point['Y']); + + $point['ANG_X'] = cos(deg2rad($point['ANGLE'])); + $point['ANG_Y'] = sin(deg2rad($point['ANGLE'])); + + $point['AX'] = -$point['ANG_X']; + $point['AY'] = -$point['ANG_Y']; + + $point['LENGTH'] = 2.5; //$radius; + + $point['MARKER_X'] = $totals['CENTER_X'] + + $totals['ODO_RADIUS'] * $point['ANG_X']; + $point['MARKER_Y'] = $totals['CENTER_Y'] + + $totals['ODO_RADIUS'] * $point['ANG_Y']; + + return $point; + } + + /** + * Draws markers of the arrows on the canvas + * + * @access private + */ + function _drawMarker() + { + + if ($this->_marker) { + $this->_marker->_radius += $this->_radius / 2; + $totals = $this->_getTotals(); + + $totals['CENTER_X'] = $this->_centerX; + $totals['CENTER_Y'] = $this->_centerY; + + + /* $keys = array_keys($this->_dataset); + foreach ($keys as $key) { */ + $dataset =& $this->_dataset[0]; + + $totals['RADIUS0'] = false; + $totals['ODO_RADIUS'] = 1.1 * $this->_radius * $this->_arrowLength / 100; + $totals['ALL_SUM_Y'] = $this->_totalY; + + $dataset->_reset(); + while ($point = $dataset->_next()) { + if ((!is_object($this->_dataSelector)) || + ($this->_dataSelector->select($point)) + ) { + $point = $this->_getMarkerData( + $point, + false, + false, + $totals + ); + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + } + /* } + unset($keys); */ + } + } + + /** + * Set range + * + * dataset with two data start and end value of the range + * @param Image_Graph_Dataset $dataset The data set (value containter) to + * plot or an array of datasets + * + */ + function addRangeMarker($min, $max, $id = false) + { + $this->_range[] = + array( + 'min' => max($this->_value_min, min($min, $max)), + 'max' => min($this->_value_max, max($min, $max)), + 'id' => $id + ); + } + + /** + * Set the fillstyle of the ranges + * + * @param Image_Graph_Fill $fillStyle The fill style of the range + * @see Image_Graph_Fill + * @access public + */ + function &setRangeMarkerFillStyle(&$rangeMarkerFillStyle) + { + $this->_rangeFillStyle = $rangeMarkerFillStyle; + } + + /** + * Draw the ranges + * + * @access private + */ + function _drawRange() + { + if($this->_range){ + $radius0 = $this->_radius * (1 - $this->_radiusPercent/100); + foreach ($this->_range as $range) { + $angle1 = $this->_value2angle($range['min']); + $angle2 = $this->_value2angle($range['max']); + + if (is_object($this->_rangeFillStyle)) { + $this->_canvas->setFill($this->_rangeFillStyle->_getFillStyle($range['id'])); + } elseif ($this->_rangeFillStyle != null) { + $this->_canvas->setFill($this->_rangeFillStyle); + } + $this->_getLineStyle(); + $this->_canvas->Pieslice( + array( + 'x' => $this->_centerX, + 'y' => $this->_centerY, + 'rx' => $this->_radius, + 'ry' => $this->_radius, + 'v1' => $angle1, + 'v2' => $angle2, + 'srx' => $radius0, + 'sry' => $radius0 + ) + ); + } + } + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $dx = abs($x1 - $x0) / 4; + $this->_canvas->addVertex(array('x' => $x0 + $dx , 'y' => $y1)); + $this->_canvas->addVertex(array('x' => ($x0 + $x1) / 2, 'y' => $y0 )); + $this->_canvas->addVertex(array('x' => $x1 - $dx , 'y' => $y1)); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Draw a sample for use with legend + * + * @param array $param The parameters for the legend + * @access private + */ + function _legendSample(&$param) + { + if (is_array($this->_dataset)) { + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + $totals = $this->_getTotals(); + $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); + $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); + $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5; + $totals['CURRENT_Y'] = 0; + + if (is_a($this->_fillStyle, "Image_Graph_Fill")) { + $this->_fillStyle->_reset(); + } + + $count = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $count++; + + $dataset->_reset(); + while ($point = $dataset->_next()) { + $caption = $point['X']; + + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height'] + 5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y'] - $param['height'] / 2; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height'] / 2; + + if (!isset($param['simulate'])) { + $this->_getFillStyle($point['ID']); + $this->_getLineStyle($point['ID']); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + if (($this->_marker) && ($dataset) && ($param['show_marker'])) { + $prevPoint = $dataset->_nearby(-2); + $nextPoint = $dataset->_nearby(); + + $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals); + if (is_array($point)) { + $p['MARKER_X'] = $x+$param['width'] / 2; + $p['MARKER_Y'] = $y; + unset ($p['AVERAGE_Y']); + $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p); + } + } + $this->write($x + $param['width'] + 10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + } + unset($keys); + $this->_clip(false); + $this->_canvas->endGroup(); + } + } +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Pie.php b/packages/dspam/pear/Image/Graph/Plot/Pie.php new file mode 100644 index 00000000..f0e872c3 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Pie.php @@ -0,0 +1,623 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * 2D Piechart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Pie extends Image_Graph_Plot +{ + + /** + * The radius of the 'pie' spacing + * @access private + * @var int + */ + var $_radius = 3; + + /** + * Explode pie slices. + * @access private + * @var mixed + */ + var $_explode = false; + + /** + * The starting angle of the plot + * @access private + * @var int + */ + var $_startingAngle = 0; + + /** + * The angle direction (1 = CCW, -1 = CW) + * @access private + * @var int + */ + var $_angleDirection = 1; + + /** + * The diameter of the pie plot + * @access private + * @var int + */ + var $_diameter = false; + + /** + * Group items below this limit together as "the rest" + * @access private + * @var double + */ + var $_restGroupLimit = false; + + /** + * Rest group title + * @access private + * @var string + */ + var $_restGroupTitle = 'The rest'; + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $y = ($y0 + $y1) / 2; + $this->_canvas->pieslice( + array( + 'x' => $x1, + 'y' => $y, + 'rx' => abs($x1 - $x0) / 2, + 'ry' => abs($y1 - $y0) / 2, + 'v1' => 45, + 'v2' => 315 + ) + ); + } + + /** + * Calculate marker point data + * + * @param array $point The point to calculate data for + * @param array $nextPoint The next point + * @param array $prevPoint The previous point + * @param array $totals The pre-calculated totals, if needed + * @return array An array containing marker point data + * @access private + */ + function _getMarkerData($point, $nextPoint, $prevPoint, &$totals) + { + $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals); + + $y = $totals['CURRENT_Y']; + + if ($this->_angleDirection < 0) { + $y = $totals['ALL_SUM_Y'] - $y; + } + + $point['ANGLE'] = 360 * (($y + ($point['Y'] / 2)) / $totals['ALL_SUM_Y']) + $this->_startingAngle; + $totals['CURRENT_Y'] += $point['Y']; + + $point['ANG_X'] = cos(deg2rad($point['ANGLE'])); + $point['ANG_Y'] = sin(deg2rad($point['ANGLE'])); + + $point['AX'] = -10 * $point['ANG_X']; + $point['AY'] = -10 * $point['ANG_Y']; + + if ((isset($totals['ALL_SUM_Y'])) && ($totals['ALL_SUM_Y'] != 0)) { + $point['PCT_MIN_Y'] = $point['PCT_MAX_Y'] = (100 * $point['Y'] / $totals['ALL_SUM_Y']); + } + + $point['LENGTH'] = 10; //$radius; + + $x = $point['X']; + $explodeRadius = 0; + if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { + $explodeRadius = $this->_explode[$x]; + } elseif (is_numeric($this->_explode)) { + $explodeRadius = $this->_explode; + } + + $point['MARKER_X'] = $totals['CENTER_X'] + + ($totals['RADIUS'] + $explodeRadius) * $point['ANG_X']; + $point['MARKER_Y'] = $totals['CENTER_Y'] + + ($totals['RADIUS'] + $explodeRadius) * $point['ANG_Y']; + + return $point; + } + + /** + * Draws markers on the canvas + * + * @access private + */ + function _drawMarker() + { + + if ($this->_marker) { + $totals = $this->_getTotals(); + + $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); + $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); + + $totals['CURRENT_Y'] = 0; + $number = 0; + + $diameter = $this->_getDiameter(); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + if (count($this->_dataset) == 1) { + $totals['RADIUS0'] = false; + $totals['RADIUS'] = $diameter / 2; + } else { + $dr = $diameter / (2 * count($this->_dataset)); + + $totals['RADIUS0'] = $number * $dr + ($number > 0 ? $this->_radius : 0); + $totals['RADIUS'] = ($number + 1) * $dr; + } + + $totals['ALL_SUM_Y'] = 0; + $totals['CURRENT_Y'] = 0; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $totals['ALL_SUM_Y'] += $point['Y']; + } + + $dataset->_reset(); + $currentY = 0; + $the_rest = 0; + while ($point = $dataset->_next()) { + if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) { + $the_rest += $point['Y']; + } + else { + if ((!is_object($this->_dataSelector)) || + ($this->_dataSelector->select($point)) + ) { + $point = $this->_getMarkerData( + $point, + false, + false, + $totals + ); + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + } + } + if ($the_rest > 0) { + $point = array('X' => $this->_restGroupTitle, 'Y' => $the_rest); + $point = $this->_getMarkerData( + $point, + false, + false, + $totals + ); + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + $number++; + } + unset($keys); + } + } + + /** + * Explodes a piece of this pie chart + * + * @param int $explode Radius to explode with (or an array) + * @param string $x The 'x' value to explode or omitted + */ + function explode($explode, $x = false) + { + if ($x === false) { + $this->_explode = $explode; + } else { + $this->_explode[$x] = $explode; + } + } + + /** + * Set the starting angle of the plot + * + * East is 0 degrees + * South is 90 degrees + * West is 180 degrees + * North is 270 degrees + * + * It is also possible to specify the direction of the plot angles (i.e. clockwise 'cw' or + * counterclockwise 'ccw') + */ + function setStartingAngle($angle = 0, $direction = 'ccw') + { + $this->_startingAngle = ($angle % 360); + $this->_angleDirection = ($direction == 'ccw' ? 1 : -1); + } + + /** + * Set the diameter of the pie plot (i.e. the number of pixels the + * pie plot should be across) + * + * Use 'max' for the maximum possible diameter + * + * Use negative values for the maximum possible - minus this value (fx -2 + * to leave 1 pixel at each side) + * + * @param mixed @diameter The number of pixels + */ + function setDiameter($diameter) + { + $this->_diameter = $diameter; + } + + /** + * Set the limit for the y-value, where values below are grouped together + * as "the rest" + * + * @param double $limit The limit + * @param string $title The title to display in the legends (default 'The + * rest') + */ + function setRestGroup($limit, $title = 'The rest') + { + $this->_restGroupLimit = $limit; + $this->_restGroupTitle = $title; + } + + /** + * Get the diameter of the plot + * @return int The number of pixels the diameter is + * @access private + */ + function _getDiameter() + { + $diameter = 0; + if ($this->_diameter === false) { + $diameter = min($this->height(), $this->width()) * 0.75; + } + else { + if ($this->_diameter === 'max') { + $diameter = min($this->height(), $this->width()); + } + elseif ($this->_diameter < 0) { + $diameter = min($this->height(), $this->width()) + $this->_diameter; + } else { + $diameter = $this->_diameter; + } + } + return $diameter; + } + + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $number = 0; + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + $totalY = 0; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $totalY += $point['Y']; + } + + $centerX = (int) (($this->_left + $this->_right) / 2); + $centerY = (int) (($this->_top + $this->_bottom) / 2); + $diameter = $this->_getDiameter(); + if ($this->_angleDirection < 0) { + $currentY = $totalY; + } else { + $currentY = 0; //rand(0, 100)*$totalY/100; + } + $dataset->_reset(); + + if (count($this->_dataset) == 1) { + $radius0 = false; + $radius1 = $diameter / 2; + } else { + $dr = $diameter / (2 * count($this->_dataset)); + + $radius0 = $number * $dr + ($number > 0 ? $this->_radius : 0); + $radius1 = ($number + 1) * $dr; + } + + $the_rest = 0; + while ($point = $dataset->_next()) { + if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) { + $the_rest += $point['Y']; + } + else { + $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle; + $currentY += $this->_angleDirection * $point['Y']; + $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle; + + $x = $point['X']; + $id = $point['ID']; + + $dX = 0; + $dY = 0; + $explodeRadius = 0; + if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { + $explodeRadius = $this->_explode[$x]; + } elseif (is_numeric($this->_explode)) { + $explodeRadius = $this->_explode; + } + + if ($explodeRadius > 0) { + $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2)); + $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2)); + } + + $ID = $point['ID']; + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + $this->_canvas->pieslice( + $this->_mergeData( + $point, + array( + 'x' => $centerX + $dX, + 'y' => $centerY + $dY, + 'rx' => $radius1, + 'ry' => $radius1, + 'v1' => $angle1, + 'v2' => $angle2, + 'srx' => $radius0, + 'sry' => $radius0 + ) + ) + ); + } + } + + if ($the_rest > 0) { + $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle; + $currentY += $this->_angleDirection * $the_rest; + $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle; + + $x = 'rest'; + $id = 'rest'; + + $dX = 0; + $dY = 0; + $explodeRadius = 0; + if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { + $explodeRadius = $this->_explode[$x]; + } elseif (is_numeric($this->_explode)) { + $explodeRadius = $this->_explode; + } + + if ($explodeRadius > 0) { + $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2)); + $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2)); + } + + $ID = $id; + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + $this->_canvas->pieslice( + $this->_mergeData( + $point, + array( + 'x' => $centerX + $dX, + 'y' => $centerY + $dY, + 'rx' => $radius1, + 'ry' => $radius1, + 'v1' => $angle1, + 'v2' => $angle2, + 'srx' => $radius0, + 'sry' => $radius0 + ) + ) + ); + } + $number++; + } + unset($keys); + $this->_drawMarker(); + return true; + } + + /** + * Draw a sample for use with legend + * + * @param array $param The parameters for the legend + * @access private + */ + function _legendSample(&$param) + { + if (is_array($this->_dataset)) { + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + $totals = $this->_getTotals(); + $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); + $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); + $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5; + $totals['CURRENT_Y'] = 0; + + if (is_a($this->_fillStyle, "Image_Graph_Fill")) { + $this->_fillStyle->_reset(); + } + + $count = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $count++; + + $dataset->_reset(); + $the_rest = 0; + while ($point = $dataset->_next()) { + $caption = $point['X']; + if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) { + $the_rest += $point['Y']; + } + else { + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height']+5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y'] - $param['height']/2; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height']/2; + + if (!isset($param['simulate'])) { + $this->_getFillStyle($point['ID']); + $this->_getLineStyle($point['ID']); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + if (($this->_marker) && ($dataset) && ($param['show_marker'])) { + $prevPoint = $dataset->_nearby(-2); + $nextPoint = $dataset->_nearby(); + + $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals); + if (is_array($point)) { + $p['MARKER_X'] = $x+$param['width']/2; + $p['MARKER_Y'] = $y; + unset ($p['AVERAGE_Y']); + $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p); + } + } + $this->write($x + $param['width'] +10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + } + if ($the_rest > 0) { + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height']+5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y'] - $param['height']/2; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height']/2; + + if (!isset($param['simulate'])) { + $this->_getFillStyle('rest'); + $this->_getLineStyle('rest'); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + $this->write($x + $param['width'] + 10, $y, $this->_restGroupTitle, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + } + unset($keys); + $this->_clip(false); + $this->_canvas->endGroup(); + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Radar.php b/packages/dspam/pear/Image/Graph/Plot/Radar.php new file mode 100644 index 00000000..1bfd9da7 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Radar.php @@ -0,0 +1,118 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Radar chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Radar extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $p = 10; + $rx = abs($x1 - $x0) / 2; + $ry = abs($x1 - $x0) / 2; + $r = min($rx, $ry); + $cx = ($x0 + $x1) / 2; + $cy = ($y0 + $y1) / 2; + $max = 5; + for ($i = 0; $i < $p; $i++) { + $v = 2 * pi() * $i / $p; + $t = $r * rand(3, $max) / $max; + $x = $cx + $t * cos($v); + $y = $cy + $t * sin($v); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + if (is_a($this->_parent, 'Image_Graph_Plotarea_Radar')) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $maxY = $dataset->maximumY(); + $count = $dataset->count(); + + $dataset->_reset(); + while ($point = $dataset->_next()) { + $this->_canvas->addVertex(array('x' => + $this->_pointX($point), 'y' => + $this->_pointY($point) + )); + } + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true)); + } + unset($keys); + } + $this->_drawMarker(); + + $this->_clip(false); + $this->_canvas->endGroup(); + return parent::_done(); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Smoothed/Area.php b/packages/dspam/pear/Image/Graph/Plot/Smoothed/Area.php new file mode 100644 index 00000000..8ea469dd --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Smoothed/Area.php @@ -0,0 +1,145 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot/Smoothed/Bezier.php + */ +require_once 'Image/Graph/Plot/Smoothed/Bezier.php'; + +/** + * Bezier smoothed area chart + * + * Similar to an {@link Image_Graph_Plot_Area}, but the interconnecting lines + * between two datapoints are smoothed using a Bezier curve, which enables the + * chart to appear as a nice curved plot instead of the sharp edges of a + * conventional {@link Image_Graph_Plot_Area}. Smoothed charts are only supported + * with non-stacked types + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Smoothed_Area extends Image_Graph_Plot_Smoothed_Bezier +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1)); + $this->_addSamplePoints($x0, $y0, $x1, $y1); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1)); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Output the Bezier smoothed plot as an Area Chart + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $first = true; + while ($p1 = $dataset->_next()) { + $p0 = $dataset->_nearby(-2); + $p2 = $dataset->_nearby(0); + $p3 = $dataset->_nearby(1); + if ($first) { + $p = $p1; + $p['Y'] = '#min_pos#'; + $x = $this->_pointX($p); + $y = $this->_pointY($p); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + + if ($p2) { + $cp = $this->_getControlPoints($p1, $p0, $p2, $p3); + $this->_canvas->addSpline( + array( + 'x' => $cp['X'], + 'y' => $cp['Y'], + 'p1x' => $cp['P1X'], + 'p1y' => $cp['P1Y'], + 'p2x' => $cp['P2X'], + 'p2y' => $cp['P2Y'] + ) + ); + } else { + $x = $this->_pointX($p1); + $y = $this->_pointY($p1); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + $lastPoint = $p1; + $first = false; + } + $lastPoint['Y'] = '#min_pos#'; + $x = $this->_pointX($lastPoint); + $y = $this->_pointY($lastPoint); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true)); + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Smoothed/Bezier.php b/packages/dspam/pear/Image/Graph/Plot/Smoothed/Bezier.php new file mode 100644 index 00000000..bc21b4c8 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Smoothed/Bezier.php @@ -0,0 +1,173 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Include file Image/Graph/Tool.php + */ +require_once 'Image/Graph/Tool.php'; + +/** + * Bezier smoothed plottype. + * + * The framework for calculating the Bezier smoothed curve from the dataset. + * Used in {@link Image_Graph_Plot_Smoothed_Line} and {@link + * Image_Graph_Plot_Smoothed_Area}. Smoothed charts are only supported with non- + * stacked types + * @link http://homepages.borland.com/efg2lab/Graphics/Jean- + * YvesQueinecBezierCurves.htm efg computer lab - description of bezier curves + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + * @abstract + */ +class Image_Graph_Plot_Smoothed_Bezier extends Image_Graph_Plot +{ + + /** + * Image_Graph_Plot_Smoothed_Bezier [Constructor] + * + * Only 'normal' multitype supported + * + * @param Dataset $dataset The data set (value containter) to plot + * @param string $title The title of the plot (used for legends, {@link + * Image_Graph_Legend}) + */ + function Image_Graph_Plot_Smoothed_Bezier(& $dataset, $title = '') + { + parent::Image_Graph_Plot($dataset, 'normal', $title); + } + + /** + * Return the minimum Y point + * + * @return double The minumum Y point + * @access private + */ + function _minimumY() + { + return 1.05 * parent::_minimumY(); + } + + /** + * Return the maximum Y point + * + * @return double The maximum Y point + * @access private + */ + function _maximumY() + { + return 1.05 * parent::_maximumY(); + } + + /** + * Calculates all Bezier points, for the curve + * + * @param array $p1 The actual point to calculate control points for + * @param array $p0 The point "just before" $p1 + * @param array $p2 The point "just after" $p1 + * @param array $p3 The point "just after" $p2 + * @return array Array of Bezier points + * @access private + */ + function _getControlPoints($p1, $p0, $p2, $p3) + { + $p1 = $this->_pointXY($p1); + if ($p2) { + $p2 = $this->_pointXY($p2); + } + if (!$p0) { + $p0['X'] = $p1['X'] - abs($p2['X'] - $p1['X']); + $p0['Y'] = $p1['Y']; //-($p2['Y']-$p1['Y']); + } else { + $p0 = $this->_pointXY($p0); + } + if (!$p3) { + $p3['X'] = $p1['X'] + 2*abs($p1['X'] - $p0['X']); + $p3['Y'] = $p1['Y']; + } else { + $p3 = $this->_pointXY($p3); + } + + if (!$p2) { + $p2['X'] = $p1['X'] + abs($p1['X'] - $p0['X']); + $p2['Y'] = $p1['Y']; + } + + $pC1['X'] = Image_Graph_Tool::controlPoint($p0['X'], $p1['X'], $p2['X']); + $pC1['Y'] = Image_Graph_Tool::controlPoint($p0['Y'], $p1['Y'], $p2['Y']); + $pC2['X'] = Image_Graph_Tool::controlPoint($p3['X'], $p2['X'], $p1['X']); + $pC2['Y'] = Image_Graph_Tool::controlPoint($p3['Y'], $p2['Y'], $p1['Y']); + + return array( + 'X' => $p1['X'], + 'Y' => $p1['Y'], + 'P1X' => $pC1['X'], + 'P1Y' => $pC1['Y'], + 'P2X' => $pC2['X'], + 'P2Y' => $pC2['Y'] + ); + } + + /** + * Create legend sample data for the canvas. + * + * Common for all smoothed plots + * + * @access private + */ + function _addSamplePoints($x0, $y0, $x1, $y1) + { + $p = abs($x1 - $x0); + $cy = ($y0 + $y1) / 2; + $h = abs($y1 - $y0); + $dy = $h / 4; + $dw = abs($x1 - $x0) / $p; + for ($i = 0; $i < $p; $i++) { + $v = 2 * pi() * $i / $p; + $x = $x0 + $i * $dw; + $y = $cy + 2 * $v * sin($v); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Smoothed/Line.php b/packages/dspam/pear/Image/Graph/Plot/Smoothed/Line.php new file mode 100644 index 00000000..00692839 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Smoothed/Line.php @@ -0,0 +1,172 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot/Smoothed/Bezier.php + */ +require_once 'Image/Graph/Plot/Smoothed/Bezier.php'; + +/** + * Bezier smoothed line chart. + * + * Similar to a {@link Image_Graph_Plot_Line}, but the interconnecting lines + * between two datapoints are smoothed using a Bezier curve, which enables the + * chart to appear as a nice curved plot instead of the sharp edges of a + * conventional {@link Image_Graph_Plot_Line}. Smoothed charts are only supported + * with non-stacked types + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Smoothed_Line extends Image_Graph_Plot_Smoothed_Bezier +{ + + /** + * Gets the fill style of the element + * + * @return int A GD filestyle representing the fill style + * @see Image_Graph_Fill + * @access private + */ + function _getFillStyle($ID = false) + { + return IMG_COLOR_TRANSPARENT; + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $this->_addSamplePoints($x0, $y0, $x1, $y1); + $this->_canvas->polygon(array('connect' => false)); + } + + /** + * Output the Bezier smoothed plot as an Line Chart + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $numPoints = 0; + while ($p1 = $dataset->_next()) { + if ($p1['Y'] === null) { + if ($numPoints > 1) { + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); + } + else { + $this->_canvas->reset(); + } + $numPoints = 0; + } else { + $p0 = $dataset->_nearby(-2); + $p2 = $dataset->_nearby(0); + $p3 = $dataset->_nearby(1); + + if (($p0) && ($p0['Y'] === null)) { + $p0 = false; + } + if (($p2) && ($p2['Y'] === null)) { + $p2 = false; + } + if (($p3) && ($p3['Y'] === null)) { + $p3 = false; + } + + if ($p2) { + $cp = $this->_getControlPoints($p1, $p0, $p2, $p3); + $this->_canvas->addSpline( + $this->_mergeData( + $p1, + array( + 'x' => $cp['X'], + 'y' => $cp['Y'], + 'p1x' => $cp['P1X'], + 'p1y' => $cp['P1Y'], + 'p2x' => $cp['P2X'], + 'p2y' => $cp['P2Y'] + ) + ) + ); + } else { + $x = $this->_pointX($p1); + $y = $this->_pointY($p1); + $this->_canvas->addVertex( + $this->_mergeData( + $p1, + array('x' => $x, 'y' => $y) + ) + ); + } + $numPoints++; + } + } + if ($numPoints > 1) { + $this->_getLineStyle(); + $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); + } + else { + $this->_canvas->reset(); + } + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } + +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Smoothed/Radar.php b/packages/dspam/pear/Image/Graph/Plot/Smoothed/Radar.php new file mode 100644 index 00000000..d505a11f --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Smoothed/Radar.php @@ -0,0 +1,142 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Plot/Smoothed/Bezier.php + */ +require_once 'Image/Graph/Plot/Smoothed/Bezier.php'; + +/** + * Smoothed radar chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Plot_Smoothed_Radar extends Image_Graph_Plot_Smoothed_Bezier +{ + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + if (is_a($this->_parent, 'Image_Graph_Plotarea_Radar')) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + if ($dataset->count() >= 3) { + $dataset->_reset(); + $p1_ = $dataset->_next(); + $p2_ = $dataset->_next(); + $p3_ = $dataset->_next(); + $plast_ = false; + if ($p3_) { + while ($p = $dataset->_next()) { + $plast_ = $p; + } + } + + if ($plast_ === false) { + $plast_ = $p3_; + } + $dataset->_reset(); + while ($p1 = $dataset->_next()) { + $p0 = $dataset->_nearby(-2); + $p2 = $dataset->_nearby(0); + $p3 = $dataset->_nearby(1); + + if ($p0 === false) { + $p0 = $plast_; + } + + if ($p2 === false) { + $p2 = $p1_; + $p3 = $p2_; + } elseif ($p3 === false) { + $p3 = $p1_; + } + + + $cp = $this->_getControlPoints($p1, $p0, $p2, $p3); + $this->_canvas->addSpline( + array( + 'x' => $cp['X'], + 'y' => $cp['Y'], + 'p1x' => $cp['P1X'], + 'p1y' => $cp['P1Y'], + 'p2x' => $cp['P2X'], + 'p2y' => $cp['P2Y'] + ) + ); + + $next2last = $p0; + $last = $p1; + } + + $cp = $this->_getControlPoints($p1_, $plast_, $p2_, $p3_); + $this->_canvas->addSpline( + array( + 'x' => $cp['X'], + 'y' => $cp['Y'], + 'p1x' => $cp['P1X'], + 'p1y' => $cp['P1Y'], + 'p2x' => $cp['P2X'], + 'p2y' => $cp['P2Y'] + ) + ); + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true)); + } + } + unset($keys); + } + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup($this->_title); + return parent::_done(); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plot/Step.php b/packages/dspam/pear/Image/Graph/Plot/Step.php new file mode 100644 index 00000000..bc9267fe --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plot/Step.php @@ -0,0 +1,200 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot/Bar.php + */ +require_once 'Image/Graph/Plot/Bar.php'; + +/** + * Step chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @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/package/Image_Graph + */ +class Image_Graph_Plot_Step extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $dx = abs($x1 - $x0) / 3; + $dy = abs($y1 - $y0) / 3; + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1)); + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y0 + $dy)); + + $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0 + $dy)); + $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0)); + + $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0)); + $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0 + 2*$dy)); + + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y0 + 2*$dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1)); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * PlotType [Constructor] + * + * A 'normal' step chart is 'stacked' + * + * @param Dataset $dataset The data set (value containter) to plot + * @param string $multiType The type of the plot + * @param string $title The title of the plot (used for legends, + * {@link Image_Graph_Legend}) + */ + function Image_Graph_Plot_Step(& $dataset, $multiType = 'stacked', $title = '') + { + $multiType = strtolower($multiType); + if (($multiType != 'stacked') && ($multiType != 'stacked100pct')) { + $multiType = 'stacked'; + } + parent::Image_Graph_Plot($dataset, $multiType, $title); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (Image_Graph_Plot::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + + if ($this->_parent->_horizontal) { + $width = $this->height() / ($this->_maximumX() + 2) / 2; + } + else { + $width = $this->width() / ($this->_maximumX() + 2) / 2; + } + + reset($this->_dataset); + $key = key($this->_dataset); + $dataset =& $this->_dataset[$key]; + + $first = $dataset->first(); + $last = $dataset->last(); + + $point = array ('X' => $first['X'], 'Y' => '#min_pos#'); + $firstY = $this->_pointY($point) + ($this->_parent->_horizontal ? $width : 0); + $base[] = $firstY; + $firstX = $this->_pointX($point) - ($this->_parent->_horizontal ? 0 : $width); + $base[] = $firstX; + + $point = array ('X' => $last['X'], 'Y' => '#min_pos#'); + $base[] = $this->_pointY($point) - ($this->_parent->_horizontal ? $width : 0); + $base[] = $this->_pointX($point) + ($this->_parent->_horizontal ? 0 : $width); + + $first = ($this->_parent->_horizontal ? $firstY : $firstX); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $polygon = array_reverse($base); + unset ($base); + $last = $first; + while ($point = $dataset->_next()) { + $x = $point['X']; + $p = $point; + + if (!isset($current[$x])) { + $current[$x] = 0; + } + + if ($this->_multiType == 'stacked100pct') { + $p['Y'] = 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x]; + } else { + $p['Y'] += $current[$x]; + } + $current[$x] += $point['Y']; + $point = $p; + + if ($this->_parent->_horizontal) { + $x0 = $this->_pointX($point); + $y0 = $last; + $x1 = $this->_pointX($point); + $last = $y1 = $this->_pointY($point) - $width; + } + else { + $x0 = $last; + $y0 = $this->_pointY($point); + $last = $x1 = $this->_pointX($point) + $width; + $y1 = $this->_pointY($point); + } + $polygon[] = $x0; $base[] = $y0; + $polygon[] = $y0; $base[] = $x0; + $polygon[] = $x1; $base[] = $y1; + $polygon[] = $y1; $base[] = $x1; + } + + while (list(, $x) = each($polygon)) { + list(, $y) = each($polygon); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true)); + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plotarea.php b/packages/dspam/pear/Image/Graph/Plotarea.php new file mode 100644 index 00000000..42aeb26a --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plotarea.php @@ -0,0 +1,1145 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Plot area used for drawing plots. + * + * The plotarea consists of an x-axis and an y-axis, the plotarea can plot multiple + * charts within one plotares, by simply adding them (the axis' will scale to the + * plots automatically). A graph can consist of more plotareas + * + * @category Images + * @package Image_Graph + * @subpackage Plotarea + * @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/package/Image_Graph + */ +class Image_Graph_Plotarea extends Image_Graph_Layout +{ + + /** + * The left most pixel of the 'real' plot area on the canvas + * @var int + * @access private + */ + var $_plotLeft = 0; + + /** + * The top most pixel of the 'real' plot area on the canvas + * @var int + * @access private + */ + var $_plotTop = 0; + + /** + * The right most pixel of the 'real' plot area on the canvas + * @var int + * @access private + */ + var $_plotRight = 0; + + /** + * The bottom most pixel of the 'real' plot area on the canvas + * @var int + * @access private + */ + var $_plotBottom = 0; + + /** + * The X axis + * @var Axis + * @access private + */ + var $_axisX = null; + + /** + * The Y axis + * @var Axis + * @access private + */ + var $_axisY = null; + + /** + * The secondary Y axis + * @var Axis + * @access private + */ + var $_axisYSecondary = null; + + /** + * The border style of the 'real' plot area + * @var LineStyle + * @access private + */ + var $_plotBorderStyle = null; + + /** + * Does any plot have any data? + * @var bool + * @access private + */ + var $_hasData = false; + + /** + * Is the plotarea horizontal? + * @var bool + * @access private + */ + var $_horizontal = false; + + /** + * Image_Graph_Plotarea [Constructor] + * + * @param string $axisX The class of the X axis (if omitted a std. axis is created) + * @param string $axisY The class of the Y axis (if omitted a std. axis is created) + * @param string $direction The direction of the plotarea - 'horizontal' or 'vertical' (default) + */ + function Image_Graph_Plotarea($axisX = 'Image_Graph_Axis_Category', $axisY = 'Image_Graph_Axis', $direction = 'vertical') + { + parent::Image_Graph_Layout(); + + $this->_padding = array('left' => 5, 'top' => 5, 'right' => 5, 'bottom' => 5);; + + include_once 'Image/Graph.php'; + + $this->_axisX =& Image_Graph::factory($axisX, IMAGE_GRAPH_AXIS_X); + $this->_axisX->_setParent($this); + + $this->_axisY =& Image_Graph::factory($axisY, IMAGE_GRAPH_AXIS_Y); + $this->_axisY->_setParent($this); + $this->_axisY->_setMinimum(0); + + $this->_fillStyle = false; + + if ($direction == 'horizontal') { + $this->_horizontal = true; + $this->_axisX->_transpose = true; + $this->_axisY->_transpose = true; + } + } + + /** + * Sets the parent. The parent chain should ultimately be a GraPHP object + * + * @see Image_Graph_Common + * @param Image_Graph_Common $parent The parent + * @access private + */ + function _setParent(& $parent) + { + parent::_setParent($parent); + if ($this->_axisX !== null) { + $this->_axisX->_setParent($this); + } + if ($this->_axisY !== null) { + $this->_axisY->_setParent($this); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setParent($this); + } + } + + /** + * Sets the plot border line style of the element. + * + * @param Image_Graph_Line $lineStyle The line style of the border + * @deprecated 0.3.0dev2 - 2004-12-16 + */ + function setPlotBorderStyle(& $plotBorderStyle) + { + } + + /** + * Adds an element to the plotarea + * + * @param Image_Graph_Element $element The element to add + * @param int $axis The axis to associate the element with, either + * IMAGE_GRAPH_AXIS_X, IMAGE_GRAPH_AXIS_Y, IMAGE_GRAPH_AXIS_Y_SECONDARY + * or the shorter string notations 'x', 'y' or 'ysec' (defaults to + * IMAGE_GRAPH_AXIS_Y) + * @return Image_Graph_Element The added element + * @see Image_Graph_Common::add() + */ + function &add(& $element, $axis = IMAGE_GRAPH_AXIS_Y) + { + if ($axis == 'x') { + $axis = IMAGE_GRAPH_AXIS_X; + } + if ($axis == 'y') { + $axis = IMAGE_GRAPH_AXIS_Y; + } + if ($axis == 'ysec') { + $axis = IMAGE_GRAPH_AXIS_Y_SECONDARY; + } + if (($axis == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary == null)) + { + $this->_axisYSecondary =& Image_Graph::factory('axis', IMAGE_GRAPH_AXIS_Y_SECONDARY); + $this->_axisYSecondary->_setMinimum(0); + if ($this->_horizontal) { + $this->_axisYSecondary->_transpose = true; + } + } + + parent::add($element); + + if (is_a($element, 'Image_Graph_Plot')) { + $element->_setAxisY($axis); + // postpone extrema calculation until we calculate coordinates + //$this->_setExtrema($element); + } elseif (is_a($element, 'Image_Graph_Grid')) { + switch ($axis) { + case IMAGE_GRAPH_AXIS_X: + if ($this->_axisX != null) { + $element->_setPrimaryAxis($this->_axisX); + if ($this->_axisY != null) { + $element->_setSecondaryAxis($this->_axisY); + } + } + break; + case IMAGE_GRAPH_AXIS_Y: + if ($this->_axisY != null) { + $element->_setPrimaryAxis($this->_axisY); + if ($this->_axisX != null) { + $element->_setSecondaryAxis($this->_axisX); + } + } + break; + case IMAGE_GRAPH_AXIS_Y_SECONDARY: + if ($this->_axisYSecondary != null) { + $element->_setPrimaryAxis($this->_axisYSecondary); + if ($this->_axisX != null) { + $element->_setSecondaryAxis($this->_axisX); + } + } + break; + } + } elseif (is_a($element, 'Image_Graph_Axis')) { + switch ($element->_type) { + case IMAGE_GRAPH_AXIS_X: + $this->_axisX =& $element; + break; + + case IMAGE_GRAPH_AXIS_Y: + $this->_axisY =& $element; + break; + + case IMAGE_GRAPH_AXIS_Y_SECONDARY: + $this->_axisYSecondary =& $element; + break; + + } + if ($element->_getMinimum() == $element->_getMaximum()) { + $element->_setMinimum(0); + $element->_setMaximum(1); + } + } + return $element; + } + + /** + * Get the width of the 'real' plotarea + * + * @return int The width of the 'real' plotarea, ie not including space occupied by padding and axis + * @access private + */ + function _plotWidth() + { + return abs($this->_plotRight - $this->_plotLeft); + } + + /** + * Get the height of the 'real' plotarea + * + * @return int The height of the 'real' plotarea, ie not including space + * occupied by padding and axis + * @access private + */ + function _plotHeight() + { + return abs($this->_plotBottom - $this->_plotTop); + } + + /** + * Set the extrema of the axis + * + * @param Image_Graph_Plot $plot The plot that 'hold' the values + * @access private + */ + function _setExtrema(& $plot) + { + if (($this->_axisX != null) && ($this->_axisX->_isNumeric())) { + $this->_axisX->_setMinimum($plot->_minimumX()); + $this->_axisX->_setMaximum($plot->_maximumX()); + } + + if (($plot->_axisY == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary !== null) && + ($this->_axisYSecondary->_isNumeric())) + { + $this->_axisYSecondary->_setMinimum($plot->_minimumY()); + $this->_axisYSecondary->_setMaximum($plot->_maximumY()); + } elseif (($this->_axisY != null) && ($this->_axisY->_isNumeric())) { + $this->_axisY->_setMinimum($plot->_minimumY()); + $this->_axisY->_setMaximum($plot->_maximumY()); + } + + $datasets =& $plot->dataset(); + if (!is_array($datasets)) { + $datasets = array($datasets); + } + + $keys = array_keys($datasets); + foreach ($keys as $key) { + $dataset =& $datasets[$key]; + if ($dataset->count() > 0) { + $this->_hasData = true; + } + + if (is_a($dataset, 'Image_Graph_Dataset')) { + if (($this->_axisX != null) && (!$this->_axisX->_isNumeric())) { + $this->_axisX->_applyDataset($dataset); + } + + if (($plot->_axisY == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary !== null) && + (!$this->_axisYSecondary->_isNumeric())) + { + $this->_axisYSecondary->_applyDataset($dataset); + } elseif (($this->_axisY != null) && (!$this->_axisY->_isNumeric())) { + $this->_axisY->_applyDataset($dataset); + } + } + } + unset($keys); + } + + /** + * Left boundary of the background fill area + * + * @return int Leftmost position on the canvas + * @access private + */ + function _fillLeft() + { + return $this->_plotLeft; + } + + /** + * Top boundary of the background fill area + * + * @return int Topmost position on the canvas + * @access private + */ + function _fillTop() + { + return $this->_plotTop; + } + + /** + * Right boundary of the background fill area + * + * @return int Rightmost position on the canvas + * @access private + */ + function _fillRight() + { + return $this->_plotRight; + } + + /** + * Bottom boundary of the background fill area + * + * @return int Bottommost position on the canvas + * @access private + */ + function _fillBottom() + { + return $this->_plotBottom; + } + + /** + * Get the point from the x-axis + * @param array $value The value array + * @param int $min The minimum pixel position possible + * @param int $max The maximum pixel position possible + * @return int The pixel position from the axis + * @access private + */ + function _axisPointX($value, $min, $max) + { + if (($this->_axisX == null) || (!isset($value['X']))) { + return false; + } + + if ($value['X'] === '#min#') { + return $min; + } + if ($value['X'] === '#max#') { + return $max; + } + + return $this->_axisX->_point($value['X']); + } + + /** + * Get the point from the x-axis + * @param array $value The value array + * @param int $min The minimum pixel position possible + * @param int $max The maximum pixel position possible + * @return int The pixel position from the axis + * @access private + */ + function _axisPointY($value, $min, $max) + { + if (!isset($value['Y'])) { + return false; + } + + if (($value['Y'] === '#min_pos#') || ($value['Y'] === '#max_nex#')) { + // return the minimum (bottom) position or if negative then zero + // or the maxmum (top) position or if positive then zero + if ((isset($value['AXIS_Y'])) && + ($value['AXIS_Y'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary !== null) + ) { + $axisY =& $this->_axisYSecondary; + } else { + $axisY =& $this->_axisY; + } + if ($value['Y'] === '#min_pos#') { + return $axisY->_point(max(0, $axisY->_getMinimum())); + } else { + return $axisY->_point(min(0, $axisY->_getMaximum())); + } + } + + if ($value['Y'] === '#min#') { + return $min; + } + if ($value['Y'] === '#max#') { + return $max; + } + + if ((isset($value['AXIS_Y'])) && + ($value['AXIS_Y'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) + ) { + if ($this->_axisYSecondary !== null) { + return $this->_axisYSecondary->_point($value['Y']); + } + } else { + if ($this->_axisY !== null) { + return $this->_axisY->_point($value['Y']); + } + } + return false; + } + + /** + * Get the X pixel position represented by a value + * + * @param double Value the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($value) + { + if ($this->_horizontal) { + return $this->_axisPointY($value, $this->_plotLeft, $this->_plotRight); + } + else { + return $this->_axisPointX($value, $this->_plotLeft, $this->_plotRight); + } + } + + /** + * Get the Y pixel position represented by a value + * + * @param double Value the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($value) + { + if ($this->_horizontal) { + return $this->_axisPointX($value, $this->_plotBottom, $this->_plotTop); + } + else { + return $this->_axisPointY($value, $this->_plotBottom, $this->_plotTop); + } + } + + /** + * Return the minimum value of the specified axis + * + * @param int $axis The axis to return the minimum value of (see {$link + * Image_Graph_Plotarea::getAxis()}) + * @return double The minimum value of the axis + * @access private + */ + function _getMinimum($axis = IMAGE_GRAPH_AXIS_Y) + { + $axis =& $this->getAxis($axis); + if ($axis !== null) { + return $axis->_getMinimum(); + } else { + return 0; + } + } + + /** + * Return the maximum value of the specified axis + * + * @param int $axis The axis to return the maximum value of(see {$link + * Image_Graph_Plotarea::getAxis()}) + * @return double The maximum value of the axis + * @access private + */ + function _getMaximum($axis = IMAGE_GRAPH_AXIS_Y) + { + $axis =& $this->getAxis($axis); + if ($axis !== null) { + return $axis->_getMaximum(); + } else { + return 0; + } + } + + /** + * Return the label distance for the specified axis. + * + * @param int $axis The axis to return the label distance for + * @return int The distance between 2 adjacent labels + * @access private + */ + function _labelDistance($axis) + { + $axis =& $this->getAxis($axis); + if ($axis !== null) { + return $axis->_labelDistance(); + } + + return false; + } + + /** + * Hides the axis + */ + function hideAxis($axis = false) + { + if (((!$axis) || ($axis === $this->_axisX) || ($axis === 'x')) && ($this->_axisX != null)) { + $this->_axisX->hide(); + } + if (((!$axis) || ($axis === $this->_axisY) || ($axis === 'y')) && ($this->_axisY != null)) { + $this->_axisY->hide(); + } + if (((!$axis) || ($axis === $this->_axisYSecondary) || ($axis === 'y_sec')) && ($this->_axisYSecondary != null)) { + $this->_axisYSecondary->hide(); + } + } + + /** + * Clears/removes the axis + */ + function clearAxis() + { + $this->_axisX = $this->_axisY = $this->_axisYSecondary = null; + } + + /** + * Get axis. + * + * Possible values are IMAGE_GRAPH_AXIS_X, IMAGE_GRAPH_AXIS_Y, + * IMAGE_GRAPH_AXIS_Y_SECONDARY or a short hand notation using + * string identifiers: 'x', 'y', 'ysec' + * + * @param int $axis The axis to return + * @return Image_Graph_Axis The axis + */ + function &getAxis($axis = IMAGE_GRAPH_AXIS_X) + { + switch ($axis) { + case IMAGE_GRAPH_AXIS_X: + case 'x': + return $this->_axisX; + + case IMAGE_GRAPH_AXIS_Y: + case 'y': + return $this->_axisY; + + case IMAGE_GRAPH_AXIS_Y_SECONDARY: + case 'ysec': + return $this->_axisYSecondary; + + } + return null; + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + $element =& $this->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + if (((is_a($element, 'Image_Graph_Plot_Bar')) || + (is_a($element, 'Image_Graph_Plot_Step')) || + (is_a($element, 'Image_Graph_Plot_Dot')) || + (is_a($element, 'Image_Graph_Plot_CandleStick')) || + (is_a($element, 'Image_Graph_Plot_BoxWhisker')) || + (is_a($element, 'Image_Graph_Plot_Impulse'))) && + ($this->_axisX != null) && + (strtolower(get_class($this->_axisX)) != 'image_graph_axis') // do not push plot if x-axis is linear + ) + { + $this->_axisX->_pushValues(); + } + $this->_setExtrema($element); + } + } + unset($keys); + } + + $this->_calcEdges(); + + $pctWidth = (int) ($this->width() * 0.05); + $pctHeight = (int) ($this->height() * 0.05); + + $left = $this->_left + $this->_padding['left']; + $top = $this->_top + $this->_padding['top']; + $right = $this->_right - $this->_padding['right']; + $bottom = $this->_bottom - $this->_padding['bottom']; + + // temporary place holder for axis point calculations + $axisPoints['x'] = array($left, $top, $right, $bottom); + $axisPoints['y'] = $axisPoints['x']; + $axisPoints['y2'] = $axisPoints['x']; + + if ($this->_axisX !== null) { + $intersectX = $this->_axisX->_getAxisIntersection(); + $sizeX = $this->_axisX->_size(); + $this->_axisX->_setCoords($left, $top, $right, $bottom); + $this->_axisX->_updateCoords(); + } + + if ($this->_axisY !== null) { + $intersectY = $this->_axisY->_getAxisIntersection(); + $sizeY = $this->_axisY->_size(); + $this->_axisY->_setCoords($left, $top, $right, $bottom); + $this->_axisY->_updateCoords(); + } + + if ($this->_axisYSecondary !== null) { + $intersectYsec = $this->_axisYSecondary->_getAxisIntersection(); + $sizeYsec = $this->_axisYSecondary->_size(); + $this->_axisYSecondary->_setCoords($left, $top, $right, $bottom); + $this->_axisYSecondary->_updateCoords(); + } + + $axisCoordAdd = array('left' => 0, 'right' => 0, 'top' => 0, 'bottom' => 0); + + if ($this->_axisY != null) { + if ($this->_axisX != null) { + $pos = $this->_axisX->_intersectPoint($intersectY['value']); + } else { + $pos = ($this->_horizontal ? $bottom : $left); + } + + if ($this->_horizontal) { + if (($pos + $sizeY) > $bottom) { + $axisCoordAdd['bottom'] = ($pos + $sizeY) - $bottom; + // the y-axis position needs to be recalculated! + } else { + // top & bottom may need to be adjusted when the x-axis has been + // calculated! + $this->_axisY->_setCoords( + $left, + $pos, + $right, + $pos + $sizeY + ); + $this->_axisY->_updateCoords(); + } + } + else { + if (($pos - $sizeY) < $left) { + $axisCoordAdd['left'] = $left - ($pos - $sizeY); + // the y-axis position needs to be recalculated! + } else { + // top & bottom may need to be adjusted when the x-axis has been + // calculated! + $this->_axisY->_setCoords( + $pos - $sizeY, + $top, + $pos, + $bottom + ); + $this->_axisY->_updateCoords(); + } + } + } + + if ($this->_axisYSecondary != null) { + if ($this->_axisX != null) { + $pos = $this->_axisX->_intersectPoint($intersectYsec['value']); + } else { + $pos = ($this->_horizontal ? $top : $right); + } + + if ($this->_horizontal) { + if (($pos - $sizeYsec) < $top) { + $axisCoordAdd['top'] = $top - ($pos - $sizeYsec); + // the secondary y-axis position need to be recalculated + } else { + // top & bottom may need to be adjusted when the x-axis has been + // calculated! + $this->_axisYSecondary->_setCoords( + $left, + $pos - $sizeY, + $right, + $pos + ); + $this->_axisYSecondary->_updateCoords(); + } + } + else { + if (($pos + $sizeYsec) > $right) { + $axisCoordAdd['right'] = ($pos + $sizeYsec) - $right; + // the secondary y-axis position need to be recalculated + } else { + // top & bottom may need to be adjusted when the x-axis has been + // calculated! + $this->_axisYSecondary->_setCoords( + $pos, + $top, + $pos + $sizeY, + $bottom + ); + $this->_axisYSecondary->_updateCoords(); + } + } + } + + if ($this->_axisX != null) { + if (($intersectX['axis'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary !== null) + ) { + $axis =& $this->_axisYSecondary; + } elseif ($this->_axisY !== null) { + $axis =& $this->_axisY; + } else { + $axis = false; + } + + if ($axis !== false) { + $pos = $axis->_intersectPoint($intersectX['value']); + } else { + $pos = ($this->_horizontal ? $left : $bottom); + } + + if ($this->_horizontal) { + if (($pos - $sizeX) < $left) { + $axisCoordAdd['left'] = $left - ($pos - $sizeX); + $pos = $left + $sizeX; + } + + $this->_axisX->_setCoords( + $pos - $sizeX, + $top + $axisCoordAdd['top'], + $pos, + $bottom - $axisCoordAdd['bottom'] + ); + $this->_axisX->_updateCoords(); + } + else { + if (($pos + $sizeX) > $bottom) { + $axisCoordAdd['bottom'] = ($pos + $sizeX) - $bottom; + $pos = $bottom - $sizeX; + } + + $this->_axisX->_setCoords( + $left + $axisCoordAdd['left'], + $pos, + $right - $axisCoordAdd['right'], + $pos + $sizeX + ); + $this->_axisX->_updateCoords(); + } + } + + if ($this->_horizontal) { + if (($this->_axisX !== null) && + (($axisCoordAdd['top'] != 0) || + ($axisCoordAdd['bottom'] != 0)) + ) { + // readjust y-axis for better estimate of position + if ($this->_axisY !== null) { + $pos = $this->_axisX->_intersectPoint($intersectY['value']); + $this->_axisY->_setCoords( + false, + $pos, + false, + $pos + $sizeY + ); + $this->_axisY->_updateCoords(); + } + + if ($this->_axisYSecondary !== null) { + $pos = $this->_axisX->_intersectPoint($intersectYsec['value']); + $this->_axisYSecondary->_setCoords( + false, + $pos - $sizeYsec, + false, + $pos + ); + $this->_axisYSecondary->_updateCoords(); + } + } + + // adjust top and bottom of y-axis + if ($this->_axisY !== null) { + $this->_axisY->_setCoords( + $left + $axisCoordAdd['left'], + false, + $right - $axisCoordAdd['right'], + false + ); + $this->_axisY->_updateCoords(); + } + + // adjust top and bottom of y-axis + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setCoords( + $left + $axisCoordAdd['left'], + false, + $right - $axisCoordAdd['right'], + false + ); + $this->_axisYSecondary->_updateCoords(); + } + + if ($this->_axisX !== null) { + $this->_plotTop = $this->_axisX->_top; + $this->_plotBottom = $this->_axisX->_bottom; + } else { + $this->_plotTop = $top; + $this->_plotBottom = $bottom; + } + + if ($this->_axisY !== null) { + $this->_plotLeft = $this->_axisY->_left; + $this->_plotRight = $this->_axisY->_right; + } elseif ($this->_axisYSecondary !== null) { + $this->_plotLeft = $this->_axisYSecondary->_left; + $this->_plotRight = $this->_axisYSecondary->_right; + } else { + $this->_plotLeft = $this->_left; + $this->_plotRight = $this->_right; + } + } + else { + if (($this->_axisX !== null) && + (($axisCoordAdd['left'] != 0) || + ($axisCoordAdd['right'] != 0)) + ) { + // readjust y-axis for better estimate of position + if ($this->_axisY !== null) { + $pos = $this->_axisX->_intersectPoint($intersectY['value']); + $this->_axisY->_setCoords( + $pos - $sizeY, + false, + $pos, + false + ); + $this->_axisY->_updateCoords(); + } + + if ($this->_axisYSecondary !== null) { + $pos = $this->_axisX->_intersectPoint($intersectYsec['value']); + $this->_axisYSecondary->_setCoords( + $pos, + false, + $pos + $sizeYsec, + false + ); + $this->_axisYSecondary->_updateCoords(); + } + } + + // adjust top and bottom of y-axis + if ($this->_axisY !== null) { + $this->_axisY->_setCoords( + false, + $top + $axisCoordAdd['top'], + false, + $bottom - $axisCoordAdd['bottom'] + ); + $this->_axisY->_updateCoords(); + } + + // adjust top and bottom of y-axis + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setCoords( + false, + $top + $axisCoordAdd['top'], + false, + $bottom - $axisCoordAdd['bottom'] + ); + $this->_axisYSecondary->_updateCoords(); + } + + if ($this->_axisX !== null) { + $this->_plotLeft = $this->_axisX->_left; + $this->_plotRight = $this->_axisX->_right; + } else { + $this->_plotLeft = $left; + $this->_plotRight = $right; + } + + if ($this->_axisY !== null) { + $this->_plotTop = $this->_axisY->_top; + $this->_plotBottom = $this->_axisY->_bottom; + } elseif ($this->_axisYSecondary !== null) { + $this->_plotTop = $this->_axisYSecondary->_top; + $this->_plotBottom = $this->_axisYSecondary->_bottom; + } else { + $this->_plotTop = $this->_top; + $this->_plotBottom = $this->_bottom; + } + } + + Image_Graph_Element::_updateCoords(); +/* + if ($this->_axisX != null) { + $this->_axisX->_updateCoords(); + } + if ($this->_axisY != null) { + $this->_axisY->_updateCoords(); + } + if ($this->_axisYSecondary != null) { + $this->_axisYSecondary->_updateCoords(); + }*/ + } + + /** + * Set the axis padding for a specified position. + * + * The axis padding is padding "inside" the plotarea (i.e. to put some space + * between the axis line and the actual plot). + * + * This can be specified in a number of ways: + * + * 1) Specify an associated array with 'left', 'top', 'right' and 'bottom' + * indices with values for the paddings. Leave out 2nd parameter. + * + * 2) Specify an overall padding as the first parameter + * + * 3) Specify the padding and position with position values as mentioned + * above + * + * Normally you'd only consider applying axis padding to a category x-axis. + * + * @param mixed $value The value/padding + * @param mixed $position The "position" of the padding + */ + function setAxisPadding($value, $position = false) + { + if ($position === false) { + if (is_array($value)) { + if ($this->_horizontal) { + if ((isset($value['top'])) && ($this->_axisX !== null)) { + $this->_axisX->_setAxisPadding('low', $value['top']); + } + if ((isset($value['bottom'])) && ($this->_axisX !== null)) { + $this->_axisX->_setAxisPadding('high', $value['bottom']); + } + if ((isset($value['left'])) && ($this->_axisY !== null)) { + $this->_axisY->_setAxisPadding('low', $value['left']); + } + if ((isset($value['right'])) && ($this->_axisY !== null)) { + $this->_axisY->_setAxisPadding('high', $value['right']); + } + if ((isset($value['left'])) && ($this->_axisYSecondary !== null)) { + $this->_axisYSecondary->_setAxisPadding('low', $value['left']); + } + if ((isset($value['right'])) && ($this->_axisYSecondary !== null)) { + $this->_axisYSecondary->_setAxisPadding('high', $value['right']); + } + } + else { + if ((isset($value['left'])) && ($this->_axisX !== null)) { + $this->_axisX->_setAxisPadding('low', $value['left']); + } + if ((isset($value['right'])) && ($this->_axisX !== null)) { + $this->_axisX->_setAxisPadding('high', $value['right']); + } + if ((isset($value['bottom'])) && ($this->_axisY !== null)) { + $this->_axisY->_setAxisPadding('low', $value['bottom']); + } + if ((isset($value['top'])) && ($this->_axisY !== null)) { + $this->_axisY->_setAxisPadding('high', $value['top']); + } + if ((isset($value['bottom'])) && ($this->_axisYSecondary !== null)) { + $this->_axisYSecondary->_setAxisPadding('low', $value['bottom']); + } + if ((isset($value['top'])) && ($this->_axisYSecondary !== null)) { + $this->_axisYSecondary->_setAxisPadding('high', $value['top']); + } + } + } else { + if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('low', $value); + $this->_axisX->_setAxisPadding('high', $value); + } + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('low', $value); + $this->_axisY->_setAxisPadding('high', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('low', $value); + $this->_axisYSecondary->_setAxisPadding('high', $value); + } + } + } else { + switch ($position) { + case 'left': + if ($this->_horizontal) { + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('low', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('low', $value); + } + } + else if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('low', $value); + } + break; + + case 'right': + if ($this->_horizontal) { + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('high', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('high', $value); + } + } + else if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('high', $value); + } + break; + + case 'top': + if (!$this->_horizontal) { + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('high', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('high', $value); + } + } + else if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('high', $value); + } + break; + + case 'bottom': + if (!$this->_horizontal) { + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('low', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('low', $value); + } + } + else if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('low', $value); + } + break; + } + } + } + + /** + * Output the plotarea to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if ($this->_hasData) { + $this->_canvas->startGroup(get_class($this)); + + if ($this->_axisX != null) { + $this->add($this->_axisX); + } + if ($this->_axisY != null) { + $this->add($this->_axisY); + } + if ($this->_axisYSecondary != null) { + $this->add($this->_axisYSecondary); + } + + $this->_getFillStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $this->_plotLeft, + 'y0' => $this->_plotTop, + 'x1' => $this->_plotRight, + 'y1' => $this->_plotBottom + ) + ); + $result = parent::_done(); + $this->_canvas->endGroup(); + return $result; + } else { + // no data -> do nothing at all! + return true; + } + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plotarea/Element.php b/packages/dspam/pear/Image/Graph/Plotarea/Element.php new file mode 100644 index 00000000..a7d1b8d2 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plotarea/Element.php @@ -0,0 +1,87 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Representation of a element on a plotarea. + * + * @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: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Plotarea_Element extends Image_Graph_Element +{ + + /** + * Get the X pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($point) + { + return $this->_parent->_pointX($point); + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($point) + { + return $this->_parent->_pointY($point); + } + + /** + * Get the X and Y pixel position represented by a value + * + * @param array $point the values to get the pixel-point for + * @return array The (x, y) pixel position along the axis + * @access private + */ + function _pointXY($point) + { + return array ('X' => $this->_pointX($point), 'Y' => $this->_pointY($point)); + } + +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plotarea/Map.php b/packages/dspam/pear/Image/Graph/Plotarea/Map.php new file mode 100644 index 00000000..888d3384 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plotarea/Map.php @@ -0,0 +1,304 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea.php + */ +require_once 'Image/Graph/Plotarea.php'; + +/** + * Plot area used for map plots. + * + * A map plot is a chart that displays a map (fx. a world map) in the form of . + * png file. The maps must be located in the /Images/Maps folder and a + * corresponding .txt files mush also exist in this location where named + * locations are mapped to an (x, y) coordinate of the map picture (this text + * file is tab separated with 'Name' 'X' 'Y' values, fx 'Denmark 378 223'). The + * x-values in the dataset are then the named locations (fx 'Denmark') and the + * y-values are then the data to plot. Currently the best (if not only) use is + * to combine a map plot area with a {@link Image_Graph_Plot_Dot} using {@link + * Image_Graph_Marker_PercentageCircle} as marker. + * + * @category Images + * @package Image_Graph + * @subpackage Plotarea + * @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/package/Image_Graph + */ +class Image_Graph_Plotarea_Map extends Image_Graph_Plotarea +{ + + /** + * The GD image for the map + * @var string + * @access private + */ + var $_imageMap; + + /** + * The value for scaling the width and height to fit into the layout boundaries + * @var int + * @access private + */ + var $_scale; + + /** + * The (x,y)-points for the named point + * @var array + * @access private + */ + var $_mapPoints; + + /** + * The original size of the image map + * @var array + * @access private + */ + var $_mapSize; + + /** + * PlotareaMap [Constructor] + * + * @param string $map The name of the map, i.e. the [name].png and [name]. + * txt files located in the Images/maps folder + */ + function Image_Graph_Plotarea_Map($map) + { + parent::Image_Graph_Plotarea(); + + $this->_imageMap = dirname(__FILE__)."/../Images/Maps/$map.png"; + $points = file(dirname(__FILE__)."/../Images/Maps/$map.txt"); + list($width, $height) = getimagesize($this->_imageMap); + $this->_mapSize['X'] = $width; + $this->_mapSize['Y'] = $height; + + if (is_array($points)) { + unset($this->_mapPoints); + foreach ($points as $line) { + list($country, $x, $y) = explode("\t", $line); + $this->_mapPoints[$country] = array('X' => $x, 'Y' => $y); + } + } + } + + /** + * Left boundary of the background fill area + * + * @return int Leftmost position on the canvas + * @access private + */ + function _fillLeft() + { + return $this->_left + $this->_padding['left']; + } + + /** + * Top boundary of the background fill area + * + * @return int Topmost position on the canvas + * @access private + */ + function _fillTop() + { + return $this->_top + $this->_padding['top']; + } + + /** + * Right boundary of the background fill area + * + * @return int Rightmost position on the canvas + * @access private + */ + function _fillRight() + { + return $this->_right - $this->_padding['right']; + } + + /** + * Bottom boundary of the background fill area + * + * @return int Bottommost position on the canvas + * @access private + */ + function _fillBottom() + { + return $this->_bottom - $this->_padding['bottom']; + } + + /** + * Set the extrema of the axis + * + * @param Image_Graph_Plot $plot The plot that 'hold' the values + * @access private + */ + function _setExtrema(& $plot) + { + } + + /** + * Get the X pixel position represented by a value + * + * @param double $value The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($value) + { + $country = $value['X']; + return $this->_plotLeft+$this->_mapPoints[$country]['X']*$this->_scale; + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $value The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($value) + { + $country = $value['X']; + return $this->_plotTop+$this->_mapPoints[$country]['Y']*$this->_scale; + } + + /** + * Hides the axis + */ + function hideAxis() + { + } + + /** + * Add a point to the maps + * + * @param int $latitude The latitude of the point + * @param int $longiude The longitude of the point + * @param string $name The name of the plot + */ + function addMappoint($latitude, $longitude, $name) + { + $x = (($longitude + 180) * ($this->_mapSize['X'] / 360)); + $y = ((($latitude * -1) + 90) * ($this->_mapSize['Y'] / 180)); + $this->_mapPoints[$name] = array('X' => $x, 'Y' => $y); + } + + /** + * Add a point to the maps + * + * @param int $x The latitude of the point + * @param int $y The longitude of the point + * @param string $name The name of the plot + */ + function addPoint($x, $y, $name) + { + $this->_mapPoints[$name] = array('X' => $x, 'Y' => $y); + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + parent::_updateCoords(); + + $mapAspectRatio = $this->_mapSize['X']/$this->_mapSize['Y']; + $plotAspectRatio = ($width = $this->_fillWidth())/($height = $this->_fillHeight()); + + $scaleFactorX = ($mapAspectRatio > $plotAspectRatio); + + if ((($this->_mapSize['X'] <= $width) && ($this->_mapSize['Y'] <= $height)) || + (($this->_mapSize['X'] >= $width) && ($this->_mapSize['Y'] >= $height))) + { + if ($scaleFactorX) { + $this->_scale = $width / $this->_mapSize['X']; + } else { + $this->_scale = $height / $this->_mapSize['Y']; + } + } elseif ($this->_mapSize['X'] < $width) { + $this->_scale = $height / $this->_mapSize['Y']; + } elseif ($this->_mapSize['Y'] < $height) { + $this->_scale = $width / $this->_mapSize['X']; + } + + $this->_plotLeft = ($this->_fillLeft() + $this->_fillRight() - + $this->_mapSize['X']*$this->_scale)/2; + + $this->_plotTop = ($this->_fillTop() + $this->_fillBottom() - + $this->_mapSize['Y']*$this->_scale)/2; + + $this->_plotRight = ($this->_fillLeft() + $this->_fillRight() + + $this->_mapSize['X']*$this->_scale)/2; + + $this->_plotBottom = ($this->_fillTop() + $this->_fillBottom() + + $this->_mapSize['Y']*$this->_scale)/2; + } + + /** + * Output the plotarea to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $this->_getFillStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $this->_fillLeft(), + 'y0' => $this->_fillTop(), + 'x1' => $this->_fillRight(), + 'y1' => $this->_fillBottom() + ) + ); + + $scaledWidth = $this->_mapSize['X']*$this->_scale; + $scaledHeight = $this->_mapSize['Y']*$this->_scale; + + $this->_canvas->image( + array( + 'x' => $this->_plotLeft, + 'y' => $this->_plotTop, + 'filename' => $this->_imageMap, + 'width' => $scaledWidth, + 'height' => $scaledHeight + ) + ); + + return Image_Graph_Layout::_done(); + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Plotarea/Radar.php b/packages/dspam/pear/Image/Graph/Plotarea/Radar.php new file mode 100644 index 00000000..cfb200ea --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Plotarea/Radar.php @@ -0,0 +1,243 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea.php + */ +require_once 'Image/Graph/Plotarea.php'; + +/** + * Plot area used for radar plots. + * + * @category Images + * @package Image_Graph + * @subpackage Plotarea + * @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/package/Image_Graph + */ +class Image_Graph_Plotarea_Radar extends Image_Graph_Plotarea +{ + + /** + * Create the plotarea, implicitely creates 2 normal axis + */ + function Image_Graph_Plotarea_Radar() + { + parent::Image_Graph_Element(); + $this->_padding = array('left' => 10, 'top' => 10, 'right' => 10, 'bottom' => 10); + $this->_axisX =& Image_Graph::factory('Image_Graph_Axis_Radar'); + $this->_axisX->_setParent($this); + $this->_axisY =& Image_Graph::factory('Image_Graph_Axis', IMAGE_GRAPH_AXIS_Y); + $this->_axisY->_setParent($this); + $this->_axisY->_setMinimum(0); + } + + /** + * Get the width of the 'real' plotarea + * + * @return int The width of the 'real' plotarea, ie not including space occupied by padding and axis + * @access private + */ + function _plotWidth() + { + return (min($this->height(), $this->width())) * 0.80; + } + + /** + * Get the height of the 'real' plotarea + * + * @return int The height of the 'real' plotarea, ie not including space occupied by padding and axis + * @access private + */ + function _plotHeight() + { + return (min($this->height(), $this->width())) * 0.80; + } + + /** + * Left boundary of the background fill area + * + * @return int Leftmost position on the canvas + * @access private + */ + function _fillLeft() + { + return (int) (($this->_left + $this->_right - $this->_plotWidth()) / 2); + } + + /** + * Top boundary of the background fill area + * + * @return int Topmost position on the canvas + * @access private + */ + function _fillTop() + { + return (int) (($this->_top + $this->_bottom - $this->_plotHeight()) / 2); + } + + /** + * Right boundary of the background fill area + * + * @return int Rightmost position on the canvas + * @access private + */ + function _fillRight() + { + return (int) (($this->_left + $this->_right + $this->_plotWidth()) / 2); + } + + /** + * Bottom boundary of the background fill area + * + * @return int Bottommost position on the canvas + * @access private + */ + function _fillBottom() + { + return (int) (($this->_top + $this->_bottom + $this->_plotHeight()) / 2); + } + + /** + * Get the X pixel position represented by a value + * + * @param double $value The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($value) + { + if (is_array($value)) { + if ($value['Y'] == '#min#') { + $radius = 0; + } elseif (($value['Y'] == '#max#') || ($value['Y'] === false)) { + $radius = 1; + } else { + $radius = ($value['Y'] - $this->_axisY->_getMinimum()) / + ($this->_axisY->_getMaximum() - $this->_axisY->_getMinimum()); + } + $x = ($this->_left + $this->_right) / 2 - + $radius * ($this->_plotWidth() / 2) * + cos(deg2rad($this->_axisX->_point($value['X']))); + } + return max($this->_plotLeft, min($this->_plotRight, $x)); + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $value The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($value) + { + if (is_array($value)) { + if ($value['Y'] == '#min#') { + $radius = 0; + } elseif (($value['Y'] == '#max#') || ($value['Y'] === false)) { + $radius = 1; + } else { + $radius = ($value['Y'] - $this->_axisY->_getMinimum()) / + ($this->_axisY->_getMaximum() - $this->_axisY->_getMinimum()); + } + + $y = ($this->_top + $this->_bottom) / 2 - + $radius * ($this->_plotHeight() / 2) * + sin(deg2rad($this->_axisX->_point($value['X']))); + } + return max($this->_plotTop, min($this->_plotBottom, $y)); + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + $element =& $this->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $this->_setExtrema($element); + } + } + unset($keys); + } + + $this->_calcEdges(); + + $centerX = (int) (($this->_left + $this->_right) / 2); + $centerY = (int) (($this->_top + $this->_bottom) / 2); + $radius = min($this->_plotHeight(), $this->_plotWidth()) / 2; + + if (is_object($this->_axisX)) { + $this->_axisX->_setCoords( + $centerX - $radius, + $centerY - $radius, + $centerX + $radius, + $centerY + $radius + ); + } + + if (is_object($this->_axisY)) { + $this->_axisY->_setCoords( + $centerX, + $centerY, + $centerX - $radius, + $centerY - $radius + ); + } + + $this->_plotLeft = $this->_fillLeft(); + $this->_plotTop = $this->_fillTop(); + $this->_plotRight = $this->_fillRight(); + $this->_plotBottom = $this->_fillBottom(); + + Image_Graph_Element::_updateCoords(); + + if (is_object($this->_axisX)) { + $this->_axisX->_updateCoords(); + } + + if (is_object($this->_axisY)) { + $this->_axisY->_updateCoords(); + } + + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Simple.php b/packages/dspam/pear/Image/Graph/Simple.php new file mode 100644 index 00000000..9d14c4da --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Simple.php @@ -0,0 +1,121 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph.php + */ +require_once 'Image/Graph.php'; + +/** + * Class for simple creation of graphs + * + * @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: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Simple extends Image_Graph +{ + + /** + * Image_Graph_Simple [Constructor] + * + * @param int $width The width of the graph in pixels + * @param int $height The height of the graph in pixels + */ + function Image_Graph_Simple($width, $height, $plotType, $data, $title, $lineColor = 'black', $fillColor = 'white', $font = false) + { + parent::Image_Graph($width, $height); + + $plotarea =& Image_Graph::factory('plotarea'); + + $dataset =& Image_Graph::factory('dataset', array($data)); + + if ($font === false) { + $font =& Image_Graph::factory('Image_Graph_Font'); + } elseif (is_string($font)) { + $font =& Image_Graph::factory('ttf_font', $font); + $font->setSize(8); + } + + $this->setFont($font); + + $this->add( + Image_Graph::vertical( + Image_Graph::factory('title', + array( + $title, + array('size_rel' => 2) + ) + ), + $plotarea, + 10 + ) + ); + + $plotarea->addNew('line_grid', array(), IMAGE_GRAPH_AXIS_Y); + + $plot =& $plotarea->addNew($plotType, array(&$dataset)); + $plot->setLineColor($lineColor); + $plot->setFillColor($fillColor); + + $axisX =& $plotarea->getAxis(IMAGE_GRAPH_AXIS_X); + $axisX->showLabel( + IMAGE_GRAPH_LABEL_MINIMUM + + IMAGE_GRAPH_LABEL_ZERO + + IMAGE_GRAPH_LABEL_MAXIMUM + ); + + } + + /** + * Factory method to create the Image_Simple_Graph object. + */ + function &factory($width, $height, $plotType, $data, $title, $lineColor = 'black', $fillColor = 'white', $font = false) + { + $obj =& Image_Graph::factory('Image_Graph_Simple', + array( + $width, + $height, + $plotType, + $data, + $title, + $lineColor, + $fillColor, + $font + ) + ); + return $obj; + } + +} +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Title.php b/packages/dspam/pear/Image/Graph/Title.php new file mode 100644 index 00000000..2cffe5f3 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Title.php @@ -0,0 +1,194 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Title + * + * @category Images + * @package Image_Graph + * @subpackage Text + * @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/package/Image_Graph + */ +class Image_Graph_Title extends Image_Graph_Layout +{ + + /** + * The text to print + * @var string + * @access private + */ + var $_text; + + /** + * The font to use + * @var Font + * @access private + */ + var $_font; + + /** + * The alignment of the title + * @var int + * @access private + */ + var $_alignment = IMAGE_GRAPH_ALIGN_CENTER_X; + + /** + * Create the title. + * + * Pass a Image_Graph_Font object - preferably by-ref (&) as second + * parameter, the font size in pixels or an associated array with some or + * all of the followin keys: + * + * 'size' The size of the title + * + * 'angle' The angle at which to write the title (in degrees or 'vertical') + * + * 'color' The font-face color + * + * @param sting $text The text to represent the title + * @param mixed $fontOptions The font to use in the title + */ + function Image_Graph_Title($text, $fontOptions = false) + { + parent::Image_Graph_Layout(); + if (is_object($fontOptions)) { + $this->_font =& $fontOptions; + } else { + if (is_array($fontOptions)) { + $this->_fontOptions = $fontOptions; + } else { + $this->_fontOptions['size'] = $fontOptions; + } + } + $this->setText($text); + } + + /** + * Set the text + * + * @param string $text The text to display + */ + function setText($text) + { + $this->_text = $text; + } + + /** + * Returns the calculated "auto" size + * + * @return int The calculated auto size + * @access private + */ + function _getAutoSize() + { + if ($this->_defaultFontOptions !== false) { + $this->_canvas->setFont($this->_defaultFontOptions); + } else { + $this->_canvas->setFont($this->_getFont()); + } + + return $this->_canvas->textHeight($this->_text); + } + + /** + * Set the alignment of the legend + * + * @param int $alignment The alignment + */ + function setAlignment($alignment) + { + $this->_alignment = $alignment & 0x7; + } + + /** + * Output the text + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if ($this->_defaultFontOptions !== false) { + $this->_canvas->setFont($this->_defaultFontOptions); + } else { + $this->_canvas->setFont($this->_getFont()); + } + + if (is_a($this->_parent, 'Image_Graph_Plotarea')) { + $this->_setCoords( + $this->_parent->_left, + $this->_parent->_top, + $this->_parent->_right, + $this->_parent->_top + $this->_canvas->textHeight($this->_text) + ); + } elseif (!is_a($this->_parent, 'Image_Graph_Layout')) { + $this->_setCoords( + $this->_parent->_fillLeft(), + $this->_parent->_fillTop(), + $this->_parent->_fillRight(), + $this->_parent->_fillTop() + $this->_canvas->textHeight($this->_text) + ); + } + + if (parent::_done() === false) { + return false; + } + + if ($this->_alignment == IMAGE_GRAPH_ALIGN_CENTER_X) { + $x = ($this->_left + $this->_right) / 2; + } elseif ($this->_alignment == IMAGE_GRAPH_ALIGN_LEFT) { + $x = $this->_left; + } else { + $x = $this->_right; + } + $y = ($this->_top + $this->_bottom) / 2; + + $this->write( + $x, + $y, + $this->_text, + $this->_alignment + IMAGE_GRAPH_ALIGN_CENTER_Y + ); + return true; + } + +} + +?> \ No newline at end of file diff --git a/packages/dspam/pear/Image/Graph/Tool.php b/packages/dspam/pear/Image/Graph/Tool.php new file mode 100644 index 00000000..cf245685 --- /dev/null +++ b/packages/dspam/pear/Image/Graph/Tool.php @@ -0,0 +1,291 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * This class contains a set of tool-functions. + * + * These functions are all to be called statically + * + * @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: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Tool +{ + + /** + * 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_Graph_Tool::mirror($p1, $p2, $smoothFactor); + $sb = Image_Graph_Tool::mid($p2, $sa); + + $m = Image_Graph_Tool::mid($p2, $factor); + + $pC = Image_Graph_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; + } + + /** + * For a given point (x,y) return a point rotated by a given angle aroung the center (xy,yc) + * + * @param int $x x coordinate of the point to rotate + * @param int $y y coordinate of the point to rotate + * @param int $xc x coordinate of the center of the rotation + * @param int $yc y coordinate of the center of the rotation + * @param int $angle angle of the rotation + * @return array the coordinate of the new point + * @static + */ + function rotate($x, $y, $xc, $yc, $angle) + { + $cos = cos(deg2rad($angle)); + $sin = sin(deg2rad($angle)); + $xr= $x - $xc; + $yr= $y - $yc; + $x1= $xc + $cos * $xr - $sin * $yr; + $y1= $yc + $sin * $xr + $cos * $yr; + return array((int) $x1,(int) $y1); + } + + /** + * If a number is close 0 zero (i.e. 0 within $decimal decimals) it is rounded down to zero + * + * @param double $value The value to round + * @param int $decimal The number of decimals + * @return double The value or zero if "close enough" to zero + * @static + */ + function close2zero($value, $decimal) + { + if (abs($value) < pow(10, -$decimal)) { + return 0; + } + else { + return $value; + } + } + + /** + * Calculate the dimensions and center point (of gravity) for an arc + * + * @param int $v1 The angle at which the arc starts + * @param int $v2 The angle at which the arc ends + * @return array An array with the dimensions in a fraction of a circle width radius 1 'rx', 'ry' and the + * center point of gravity ('cx', 'cy') + * @static + */ + function calculateArcDimensionAndCenter($v1, $v2) + { + // $v2 always larger than $v1 + $r1x = Image_Graph_Tool::close2zero(cos(deg2rad($v1)), 3); + $r2x = Image_Graph_Tool::close2zero(cos(deg2rad($v2)), 3); + + $r1y = Image_Graph_Tool::close2zero(sin(deg2rad($v1)), 3); + $r2y = Image_Graph_Tool::close2zero(sin(deg2rad($v2)), 3); + + // $rx = how many percent of the x-diameter of the entire ellipse does the arc x-diameter occupy: 1 entire width, 0 no width + // $cx = at what percentage of the diameter does the center lie + + // if the arc passes through 0/360 degrees the "highest" of r1x and r2x is replaced by 1! + if ((($v1 <= 0) && ($v2 >= 0)) || (($v1 <= 360) && ($v2 >= 360))) { + $r1x = min($r1x, $r2x); + $r2x = 1; + } + + // if the arc passes through 180 degrees the "lowest" of r1x and r2x is replaced by -1! + if ((($v1 <= 180) && ($v2 >= 180)) || (($v1 <= 540) && ($v2 >= 540))) { + $r1x = max($r1x, $r2x); + $r2x = -1; + } + + if ($r1x >= 0) { // start between [270; 360] or [0; 90] + if ($r2x >= 0) { + $rx = max($r1x, $r2x) / 2; + $cx = 0; // center lies 0 percent along this "vector" + } + else { + $rx = abs($r1x - $r2x) / 2; + $cx = abs($r2x / 2) / $rx; + } + } + else { // start between ]90; 270[ + if ($r2x < 0) { + $rx = max(abs($r1x), abs($r2x)) / 2; + $cx = $rx; + } + else { + $rx = abs($r1x - $r2x) / 2; + $cx = abs($r1x / 2) / $rx; + } + } + + // $ry = how many percent of the y-diameter of the entire ellipse does the arc y-diameter occupy: 1 entire, 0 none + // $cy = at what percentage of the y-diameter does the center lie + + // if the arc passes through 90 degrees the "lowest" of r1x and r2x is replaced by -1! + if ((($v1 <= 90) && ($v2 >= 90)) || (($v1 <= 450) && ($v2 >= 450))) { + $r1y = min($r1y, $r2y); + $r2y = 1; + } + + // if the arc passes through 270 degrees the "highest" of r1y and r2y is replaced by -1! + if ((($v1 <= 270) && ($v2 >= 270)) || (($v1 <= 630) && ($v2 >= 630))) { + $r1y = max($r1y, $r2y); + $r2y = -1; + } + + if ($r1y >= 0) { // start between [0; 180] + if ($r2y >= 0) { + $ry = max($r1y, $r2y) / 2; + $cy = 0; // center lies 0 percent along this "vector" + } + else { + $ry = abs($r1y - $r2y) / 2; + $cy = abs($r2y / 2) / $ry; + } + } + else { // start between ]180; 360[ + if ($r2y < 0) { + $ry = max(abs($r1y), abs($r2y)) / 2; + $cy = $ry; + } + else { + $ry = abs($r1y - $r2y) / 2; + $cy = abs($r1y / 2) / $ry; + } + } + + return array( + 'rx' => $rx, + 'cx' => $cx, + 'ry' => $ry, + 'cy' => $cy + ); + } + + /** + * Calculate linear regression on a dataset + * @param array $data The data to calculate regression upon + * @return array The slope and intersection of the "best-fit" line + * @static + */ + function calculateLinearRegression(&$data) + { + $sumX = 0; + $sumY = 0; + foreach ($data as $point) { + $sumX += $point['X']; + $sumY += $point['Y']; + } + $meanX = $sumX / count($data); + $meanY = $sumY / count($data); + + $sumXX = 0; + $sumYY = 0; + $sumXY = 0; + foreach ($data as $point) { + $sumXX += ($point['X'] - $meanX) * ($point['X'] - $meanX); + $sumYY += ($point['Y'] - $meanY) * ($point['Y'] - $meanY); + $sumXY += ($point['X'] - $meanX) * ($point['Y'] - $meanY); + } + + $result = array(); + $result['slope'] = ($sumXY / $sumXX); + $result['intersection'] = $meanY - ($result['slope'] * $meanX); + return $result; + } + +} + +?> \ No newline at end of file -- cgit v1.2.3