aboutsummaryrefslogtreecommitdiffstats
path: root/config/dspam/pear/Image/Canvas
diff options
context:
space:
mode:
Diffstat (limited to 'config/dspam/pear/Image/Canvas')
-rw-r--r--config/dspam/pear/Image/Canvas/Color.php182
-rw-r--r--config/dspam/pear/Image/Canvas/Fonts/README12
-rw-r--r--config/dspam/pear/Image/Canvas/Fonts/fontmap.txt25
-rw-r--r--config/dspam/pear/Image/Canvas/GD.php1693
-rw-r--r--config/dspam/pear/Image/Canvas/GD/JPG.php119
-rw-r--r--config/dspam/pear/Image/Canvas/GD/PNG.php125
-rw-r--r--config/dspam/pear/Image/Canvas/ImageMap.php354
-rw-r--r--config/dspam/pear/Image/Canvas/PDF.php1007
-rw-r--r--config/dspam/pear/Image/Canvas/SVG.php918
-rw-r--r--config/dspam/pear/Image/Canvas/Tool.php217
-rw-r--r--config/dspam/pear/Image/Canvas/WithMap.php278
11 files changed, 4930 insertions, 0 deletions
diff --git a/config/dspam/pear/Image/Canvas/Color.php b/config/dspam/pear/Image/Canvas/Color.php
new file mode 100644
index 00000000..0ac78553
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/Color.php
@@ -0,0 +1,182 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP Version 4 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Author: Stefan Neufeind <pear.neufeind@speedpartner.de> |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+/**
+* Class for color-handling
+*
+* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
+* @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 <pear.neufeind@speedpartner.de>
+* @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/config/dspam/pear/Image/Canvas/Fonts/README b/config/dspam/pear/Image/Canvas/Fonts/README
new file mode 100644
index 00000000..0a836147
--- /dev/null
+++ b/config/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/config/dspam/pear/Image/Canvas/Fonts/fontmap.txt b/config/dspam/pear/Image/Canvas/Fonts/fontmap.txt
new file mode 100644
index 00000000..ccec67dd
--- /dev/null
+++ b/config/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/config/dspam/pear/Image/Canvas/GD.php b/config/dspam/pear/Image/Canvas/GD.php
new file mode 100644
index 00000000..40132899
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/GD.php
@@ -0,0 +1,1693 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Class for handling output in GD compatible format.
+ *
+ * Supported formats are PNG, JPEG, GIF and WBMP.
+ *
+ * Requires PHP extension GD
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @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 <pear.nosey@veggerby.dk>
+ * @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 &amp;)
+ *
+ * '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 '<img src="' . $params['urlpath'] . $params['filename'] . '"' .
+ (isset($params['alt']) ? ' alt="' . $params['alt'] . '"' : '') .
+ (isset($params['cssclass']) ? ' class="' . $params['cssclass'] . '"' : '') .
+ (isset($params['border']) ? ' border="' . $params['border'] . '"' : '') .
+ (isset($this->_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("<td[^>]*>GD Version *<\/td><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/config/dspam/pear/Image/Canvas/GD/JPG.php b/config/dspam/pear/Image/Canvas/GD/JPG.php
new file mode 100644
index 00000000..ef78aeca
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/GD/JPG.php
@@ -0,0 +1,119 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Canvas class to handle JPEG format.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @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 <pear.nosey@veggerby.dk>
+ * @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/config/dspam/pear/Image/Canvas/GD/PNG.php b/config/dspam/pear/Image/Canvas/GD/PNG.php
new file mode 100644
index 00000000..75184d8c
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/GD/PNG.php
@@ -0,0 +1,125 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Canvas class to handle PNG format.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @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 <pear.nosey@veggerby.dk>
+ * @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/config/dspam/pear/Image/Canvas/ImageMap.php b/config/dspam/pear/Image/Canvas/ImageMap.php
new file mode 100644
index 00000000..e69f3de2
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/ImageMap.php
@@ -0,0 +1,354 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Class for handling output as a HTML imagemap
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @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 <pear.nosey@veggerby.dk>
+ * @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[] =
+ '<area shape="' . $shape . '" coords="' . $coords . '" href="' . $url . '"' .
+ ($target ? ' target="' . $target . '"' : '') .
+ ($alt ? ' alt="' . $alt . '"' : '') .
+ (isset($params['id']) ? ' id="' . $params['id'] . '"' : '') .
+ $tags .
+ '>';
+ }
+ }
+
+ /**
+ * 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 '<map name="' . $params['name'] . '">' . "\n\t" . implode($this->_map, "\n\t") . "\n</map>";
+ }
+ return '';
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/PDF.php b/config/dspam/pear/Image/Canvas/PDF.php
new file mode 100644
index 00000000..180263cb
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/PDF.php
@@ -0,0 +1,1007 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class for handling output in PDF format.
+ *
+ * Requires PHP extension PDFlib
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @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 <pear.nosey@veggerby.dk>
+ * @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 '<a href="' . $params['urlpath'] . $params['filename'] . '">' . $params['title'] . '</a>';
+ }
+
+ /**
+ * 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("<td[^>]*>PDFlib GmbH Version *<\/td><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/config/dspam/pear/Image/Canvas/SVG.php b/config/dspam/pear/Image/Canvas/SVG.php
new file mode 100644
index 00000000..3fed62ba
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/SVG.php
@@ -0,0 +1,918 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class for handling output in SVG format.
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @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 <pear.nosey@veggerby.dk>
+ * @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 . '<a xlink:href="' . $url . '"' . ($target ? ' target="' . $target . '"' : '') . '>' . "\n" .
+ ' ' . $elementdata .
+ $this->_indent . '</a>' . "\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(
+ '<radialGradient id="' . $id . '" cx="' .
+ $cx .'" cy="' . $cy .'" r="' . $r .'" fx="' .
+ $fx .'" fy="' . $fy .'">'
+ );
+ $this->_addDefine(
+ ' <stop offset="0%" style="stop-color:' .
+ $startColor. ';' . ($startOpacity ? 'stop-opacity:' .
+ $startOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ ' <stop offset="100%" style="stop-color:' .
+ $endColor. ';' . ($endOpacity ? 'stop-opacity:' .
+ $endOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ '</radialGradient>'
+ );
+ } elseif (($fillStyle['direction'] == 'vertical_mirror') ||
+ ($fillStyle['direction'] == 'horizontal_mirror'))
+ {
+ $this->_addDefine(
+ '<linearGradient id="' . $id . '" x1="' .
+ $x1 .'" y1="' . $y1 .'" x2="' . $x2 .'" y2="' .
+ $y2 .'">'
+ );
+ $this->_addDefine(
+ ' <stop offset="0%" style="stop-color:' .
+ $startColor. ';' . ($startOpacity ? 'stop-opacity:' .
+ $startOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ ' <stop offset="50%" style="stop-color:' .
+ $endColor. ';' . ($endOpacity ? 'stop-opacity:' .
+ $endOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ ' <stop offset="100%" style="stop-color:' .
+ $startColor. ';' . ($startOpacity ? 'stop-opacity:' .
+ $startOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ '</linearGradient>'
+ );
+ } else {
+ $this->_addDefine(
+ '<linearGradient id="' . $id . '" x1="' .
+ $x1 .'" y1="' . $y1 .'" x2="' . $x2 .'" y2="' .
+ $y2 .'">'
+ );
+ $this->_addDefine(
+ ' <stop offset="0%" style="stop-color:' .
+ $startColor. ';' . ($startOpacity ? 'stop-opacity:' .
+ $startOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ ' <stop offset="100%" style="stop-color:' .
+ $endColor. ';' . ($endOpacity ? 'stop-opacity:' .
+ $endOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ '</linearGradient>'
+ );
+ }
+
+ 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<br>
+ * If 'type' = 'ttf' then the following can be specified<br>
+ * 'size' = size in pixels<br>
+ * '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(
+ '<line ' .
+ 'x1="' . round($x0) . '" ' .
+ 'y1="' . round($y0) . '" ' .
+ 'x2="' . round($x1) . '" ' .
+ 'y2="' . round($y1) . '" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $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(
+ '<path ' .
+ 'd="' . $points . '" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $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(
+ '<rect ' .
+ 'x="' . round($x0) . '" ' .
+ 'y="' . round($y0) . '" ' .
+ 'width="' . round(abs($x1 - $x0)) . '" ' .
+ 'height="' . round(abs($y1 - $y0)) . '" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $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(
+ '<ellipse ' .
+ 'cx="' . round($x) . '" ' .
+ 'cy="' . round($y) . '" ' .
+ 'rx="' . round($rx) . '" ' .
+ 'ry="' . round($ry) . '" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $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(
+ '<path d="' .
+ 'M' . round($x) . ',' . round($y) . ' ' .
+ 'L' . round($x1) . ',' . round($y1) . ' ' .
+ 'A' . round($rx) . ',' . round($ry) . ($dv > 180 ? ' 0 1,1 ' : ' 0 0,1 ') .
+ round($x2) . ',' . round($y2) . ' ' .
+ 'Z" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $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(
+ '<g transform="translate(' . round($x) . ', ' . round($y) . ')">' . "\n" .
+ $this->_indent . ' <text ' .
+ 'x="0" ' .
+ 'y="0" ' .
+ (isset($this->_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) .
+ '</text>' . "\n" .
+ $this->_indent . '</g>',
+ $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(
+ '<image xlink:href="' . $data . '" x="' . $x . '" y="' . $y . '"' .
+ ($width ? ' width="' . $width . '"' : '') .
+ ($height ? ' height="' . $height . '"' : '') .
+ ' preserveAspectRatio="none"/>',
+ $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('<g id="' . htmlspecialchars($name) . '">');
+ $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('</g>');
+ }
+
+ /**
+ * Output the result of the canvas
+ *
+ * @param array $param Parameter array
+ */
+ function show($param = false)
+ {
+ parent::show($param);
+ $output = '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n" .
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"' . "\n\t" .
+ ' "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">' . "\n" .
+ '<svg width="' . $this->_width . '" height="' . $this->_height .
+ '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' . "\n" .
+ ($this->_defs ?
+ ' <defs>' . "\n" .
+ $this->_defs .
+ ' </defs>' . "\n" :
+ ''
+ ) .
+ $this->_elements .
+ '</svg>';
+
+ 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 = '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n" .
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"' . "\n\t" .
+ ' "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">' . "\n" .
+ '<svg width="' . $this->_width . '" height="' . $this->_height .
+ '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' . "\n" .
+ ($this->_defs ?
+ ' <defs>' . "\n" .
+ $this->_defs .
+ ' </defs>' . "\n" :
+ ''
+ ) .
+ $this->_elements .
+ '</svg>';
+
+ $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('</g>');
+ }
+ else {
+ $group = "clipping_" . $this->_id;
+ $this->_id++;
+ $this->_addElement('<g clip-path="url(#' . $group . ')">');
+
+ $this->_addDefine('<clipPath id="' . $group . '">');
+ $this->_addDefine(' <path d="' .
+ 'M' . $this->_getX($params['x0']) . ' ' . $this->_getY($params['y0']) .
+ ' H' . $this->_getX($params['x1']) .
+ ' V' . $this->_getY($params['y1']) .
+ ' H' . $this->_getX($params['x0']) .
+ ' Z"/>');
+ $this->_addDefine('</clipPath>');
+ }
+ }
+
+ /**
+ * 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 '<embed src="' . $params['urlpath'] . $params['filename'] . '" width=' . $params['width'] . ' height=' . $params['height'] . ' type="image/svg+xml">';
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/Tool.php b/config/dspam/pear/Image/Canvas/Tool.php
new file mode 100644
index 00000000..3b87122c
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/Tool.php
@@ -0,0 +1,217 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Canvas based creation of images to facilitate different output formats
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @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 <pear.nosey@veggerby.dk>
+ * @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/config/dspam/pear/Image/Canvas/WithMap.php b/config/dspam/pear/Image/Canvas/WithMap.php
new file mode 100644
index 00000000..dc43ec4d
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/WithMap.php
@@ -0,0 +1,278 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Canvas based creation of images to facilitate different output formats
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @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 <pear.nosey@veggerby.dk>
+ * @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