Initial Commit of AgileBill Open Source

This commit is contained in:
unknown
2008-11-26 14:50:40 -08:00
parent ae5a0fc25e
commit 02306ccc47
2954 changed files with 410976 additions and 0 deletions

View File

@@ -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: Color.php,v 1.3 2005/09/14 17:25:46 nosey Exp $
/**
* 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);
}
}
?>

View File

@@ -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/

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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: JPG.php,v 1.2 2005/08/24 20:37:34 nosey Exp $
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
*/
/**
* Include file Image/Canvas/GD.php
*/
require_once 'Image/Canvas/GD.php';
/**
* JPEG Canvas class.
*
* @category Images
* @package Image_Canvas
* @author Jesper Veggerby <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);
}
}
?>

View File

@@ -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: PNG.php,v 1.3 2005/08/24 20:37:34 nosey Exp $
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
*/
/**
* Include file Image/Canvas/GD.php
*/
require_once 'Image/Canvas/GD.php';
/**
* PNG Canvas class.
*
* @category Images
* @package Image_Canvas
* @author Jesper Veggerby <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);
}
}
?>

View File

@@ -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: ImageMap.php,v 1.6 2005/08/17 17:59:11 nosey Exp $
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
*/
/**
* Class for handling output as a HTML imagemap
*
* @category Images
* @package Image_Canvas
* @author Jesper Veggerby <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, '"') >= 0) {
$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 '';
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,885 @@
<?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: SVG.php,v 1.9 2005/11/08 19:00:35 nosey Exp $
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
*/
/**
* Include file Image/Canvas.php
*/
require_once 'Image/Canvas.php';
/**
* Include file Image/Canvas/Color.php
*/
require_once 'Image/Canvas/Color.php';
/**
* SVG Canvas class.
*
* @category Images
* @package Image_Canvas
* @author Jesper Veggerby <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(
'<text ' .
'x="' . round($x) . '" ' .
'y="' . round($y) . '" ' .
/* (isset($this->_font['angle']) && ($this->_font['angle'] > 0) ?
'rotate="' . $this->_font['angle'] . '" ' :
''
) .*/
'style="' .
(isset($this->_font['name']) ?
'font-family:' . $this->_font['name'] . ';' : '') .
'font-size:' . $this->_font['size'] . 'px;fill=' .
$textColor . ($textOpacity ? ';fill-opacity:' .
$textOpacity :
''
) . ';' . $align . '">' .
htmlspecialchars($text) .
'</text>',
$params
);
parent::addText($params);
}
/**
* Overlay image
*
* Parameter array:
* 'x': int X-point of overlayed image
* 'y': int Y-point of overlayed image
* 'filename': string The filename of the image to overlay
* 'width': int [optional] The width of the overlayed image (resizing if possible)
* 'height': int [optional] The height of the overlayed image (resizing if possible)
* 'alignment': array [optional] Alignment
*/
function image($params)
{
$x = $this->_getX($params['x']);
$y = $this->_getY($params['y']);
$filename = $params['filename'];
list($width, $height, $type, $attr) = getimagesize($filename);
$width = (isset($params['width']) ? $params['width'] : $width);
$height = (isset($params['height']) ? $params['height'] : $height);
$alignment = (isset($params['alignment']) ? $params['alignment'] : false);
$file = fopen($filename, 'rb');
$filedata = fread($file, filesize($filename));
fclose($file);
$data = 'data:' . image_type_to_mime_type($type) . ';base64,' . base64_encode($filedata);
$this->_addElement(
'<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);
}
/**
* 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">';
}
}
?>

View File

@@ -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: Tool.php,v 1.3 2005/08/22 20:52:11 nosey Exp $
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
*/
/**
* This class contains a set of tool-functions.
*
* These functions are all to be called statically
*
* @category Images
* @package Image_Canvas
* @author Jesper Veggerby <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;
}
}
?>

View File

@@ -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: WithMap.php,v 1.3 2005/08/24 20:37:35 nosey Exp $
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
*/
/**
* Class for handling different output formats including a HTML image map
*
* @category Images
* @package Image_Canvas
* @author Jesper Veggerby <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;
}
}
?>