This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
khosb/includes/pear/Image/Graph/Element.php
2008-11-26 14:50:40 -08:00

727 lines
20 KiB
PHP

<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Image_Graph - Main class for the graph creation.
*
* 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_Graph
* @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: Element.php,v 1.16 2005/08/03 21:21:52 nosey Exp $
* @link http://pear.php.net/package/Image_Graph
*/
/**
* Include file Common.php
*/
require_once 'Image/Graph/Common.php';
/**
* Representation of a element.
*
* The Image_Graph_Element can be drawn on the canvas, ie it has coordinates,
* {@link Image_Graph_Line}, {@link Image_Graph_Fill}, border and background -
* although not all of these may apply to all children.
*
* @category Images
* @package Image_Graph
* @author Jesper Veggerby <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/package/Image_Graph
* @abstract
*/
class Image_Graph_Element extends Image_Graph_Common
{
/**
* The leftmost pixel of the element on the canvas
* @var int
* @access private
*/
var $_left = 0;
/**
* The topmost pixel of the element on the canvas
* @var int
* @access private
*/
var $_top = 0;
/**
* The rightmost pixel of the element on the canvas
* @var int
* @access private
*/
var $_right = 0;
/**
* The bottommost pixel of the element on the canvas
* @var int
* @access private
*/
var $_bottom = 0;
/**
* Background of the element. Default: None
* @var FillStyle
* @access private
*/
var $_background = null;
/**
* Borderstyle of the element. Default: None
* @var LineStyle
* @access private
*/
var $_borderStyle = null;
/**
* Line style of the element. Default: None
* @var LineStyle
* @access private
*/
var $_lineStyle = 'black';
/**
* Fill style of the element. Default: None
* @var FillStyle
* @access private
*/
var $_fillStyle = 'white';
/**
* Font of the element. Default: Standard font - FONT
* @var Font
* @access private
* @see $IMAGE_GRAPH_FONT
*/
var $_font = null;
/**
* Font options
* @var array
* @access private
*/
var $_fontOptions = array();
/**
* Default font options
*
* This option is included for performance reasons. The value is calculated
* before output and reused in default cases to avoid unnecessary recursive
* calls.
*
* @var array
* @access private
*/
var $_defaultFontOptions = false;
/**
* Shadows options of the element
* @var mixed
* @access private
*/
var $_shadow = false;
/**
* The padding displayed on the element
* @var int
* @access private
*/
var $_padding = 0;
/**
* Sets the background fill style of the element
*
* @param Image_Graph_Fill $background The background
* @see Image_Graph_Fill
*/
function setBackground(& $background)
{
if (!is_a($background, 'Image_Graph_Fill')) {
$this->_error(
'Could not set background for ' . get_class($this) . ': ' .
get_class($background), array('background' => &$background)
);
} else {
$this->_background =& $background;
$this->add($background);
}
}
/**
* Shows shadow on the element
*/
function showShadow($color = 'black@0.2', $size = 5)
{
$this->_shadow = array(
'color' => $color,
'size' => $size
);
}
/**
* Sets the background color of the element.
*
* See colors.txt in the docs/ folder for a list of available named colors.
*
* @param mixed $color The color
*/
function setBackgroundColor($color)
{
$this->_background = $color;
}
/**
* Gets the background fill style of the element
*
* @return int A GD fillstyle representing the background style
* @see Image_Graph_Fill
* @access private
*/
function _getBackground()
{
if (is_object($this->_background)) {
$this->_canvas->setFill($this->_background->_getFillStyle());
} elseif ($this->_background != null) {
$this->_canvas->setFill($this->_background);
} else {
return false;
}
return true;
}
/**
* Sets the border line style of the element
*
* @param Image_Graph_Line $borderStyle The line style of the border
* @see Image_Graph_Line
*/
function setBorderStyle(& $borderStyle)
{
if (!is_a($borderStyle, 'Image_Graph_Line')) {
$this->_error(
'Could not set border style for ' . get_class($this) . ': ' .
get_class($borderStyle), array('borderstyle' => &$borderStyle)
);
} else {
$this->_borderStyle =& $borderStyle;
$this->add($borderStyle);
}
}
/**
* Sets the border color of the element.
*
* See colors.txt in the docs/ folder for a list of available named colors.
* @param mixed $color The color
*/
function setBorderColor($color)
{
$this->_borderStyle = $color;
}
/**
* Gets the border line style of the element
*
* @return int A GD linestyle representing the borders line style
* @see Image_Graph_Line
* @access private
*/
function _getBorderStyle()
{
if (is_object($this->_borderStyle)) {
$result = $this->_borderStyle->_getLineStyle();
$this->_canvas->setLineThickness($result['thickness']);
$this->_canvas->setLineColor($result['color']);
} elseif ($this->_borderStyle != null) {
$this->_canvas->setLineThickness(1);
$this->_canvas->setLineColor($this->_borderStyle);
} else {
return false;
}
return true;
}
/**
* Sets the line style of the element
*
* @param Image_Graph_Line $lineStyle The line style of the element
* @see Image_Graph_Line
*/
function setLineStyle(& $lineStyle)
{
if (!is_object($lineStyle)) {
$this->_error(
'Could not set line style for ' . get_class($this) . ': ' .
get_class($lineStyle), array('linestyle' => &$lineStyle)
);
} else {
$this->_lineStyle =& $lineStyle;
$this->add($lineStyle);
}
}
/**
* Sets the line color of the element.
*
* See colors.txt in the docs/ folder for a list of available named colors.
*
* @param mixed $color The color
*/
function setLineColor($color)
{
$this->_lineStyle = $color;
}
/**
* Gets the line style of the element
*
* @return int A GD linestyle representing the line style
* @see Image_Graph_Line
* @access private
*/
function _getLineStyle($ID = false)
{
if (is_object($this->_lineStyle)) {
$result = $this->_lineStyle->_getLineStyle($ID);
if (is_array($result)) {
$this->_canvas->setLineThickness($result['thickness']);
$this->_canvas->setLineColor($result['color']);
} else {
$this->_canvas->setLineThickness(1);
$this->_canvas->setLineColor($result);
}
} elseif ($this->_lineStyle != null) {
$this->_canvas->setLineThickness(1);
$this->_canvas->setLineColor($this->_lineStyle);
} else {
return false;
}
return true;
}
/**
* Sets the fill style of the element
*
* @param Image_Graph_Fill $fillStyle The fill style of the element
* @see Image_Graph_Fill
*/
function setFillStyle(& $fillStyle)
{
if (!is_a($fillStyle, 'Image_Graph_Fill')) {
$this->_error(
'Could not set fill style for ' . get_class($this) . ': ' .
get_class($fillStyle), array('fillstyle' => &$fillStyle)
);
} else {
$this->_fillStyle =& $fillStyle;
$this->add($fillStyle);
}
}
/**
* Sets the fill color of the element.
*
* See colors.txt in the docs/ folder for a list of available named colors.
*
* @param mixed $color The color
*/
function setFillColor($color)
{
$this->_fillStyle = $color;
}
/**
* Gets the fill style of the element
*
* @return int A GD filestyle representing the fill style
* @see Image_Graph_Fill
* @access private
*/
function _getFillStyle($ID = false)
{
if (is_object($this->_fillStyle)) {
$this->_canvas->setFill($this->_fillStyle->_getFillStyle($ID));
} elseif ($this->_fillStyle != null) {
$this->_canvas->setFill($this->_fillStyle);
} else {
return false;
}
return true;
}
/**
* Gets the font of the element.
*
* If not font has been set, the parent font is propagated through it's
* children.
*
* @return array An associated array used for canvas
* @access private
*/
function _getFont($options = false)
{
if (($options === false) && ($this->_defaultFontOptions !== false)) {
return $this->_defaultFontOptions;
}
if ($options === false) {
$saveDefault = true;
} else {
$saveDefault = false;
}
if ($options === false) {
$options = $this->_fontOptions;
} else {
$options = array_merge($this->_fontOptions, $options);
}
if ($this->_font == null) {
$result = $this->_parent->_getFont($options);
} else {
$result = $this->_font->_getFont($options);
}
if ((isset($result['size'])) && (isset($result['size_rel']))) {
$result['size'] += $result['size_rel'];
unset($result['size_rel']);
}
if ($saveDefault) {
$this->_defaultFontOptions = $result;
}
return $result;
}
/**
* Sets the font of the element
*
* @param Image_Graph_Font $font The font of the element
* @see Image_Graph_Font
*/
function setFont(& $font)
{
if (!is_a($font, 'Image_Graph_Font')) {
$this->_error('Invalid font set on ' . get_class($this));
} else {
$this->_font =& $font;
$this->add($font);
}
}
/**
* Sets the font size
*
* @param int $size The size of the font
*/
function setFontSize($size)
{
$this->_fontOptions['size'] = $size;
}
/**
* Sets the font angle
*
* @param int $angle The angle of the font
*/
function setFontAngle($angle)
{
if ($angle == 'vertical') {
$this->_fontOptions['vertical'] = true;
$this->_fontOptions['angle'] = 90;
} else {
$this->_fontOptions['angle'] = $angle;
}
}
/**
* Sets the font color
*
* @param mixed $color The color of the font
*/
function setFontColor($color)
{
$this->_fontOptions['color'] = $color;
}
/**
* Sets the coordinates of the element
*
* @param int $left The leftmost pixel of the element on the canvas
* @param int $top The topmost pixel of the element on the canvas
* @param int $right The rightmost pixel of the element on the canvas
* @param int $bottom The bottommost pixel of the element on the canvas
* @access private
*/
function _setCoords($left, $top, $right, $bottom)
{
if ($left === false) {
$left = $this->_left;
}
if ($top === false) {
$top = $this->_top;
}
if ($right === false) {
$right = $this->_right;
}
if ($bottom === false) {
$bottom = $this->_bottom;
}
$this->_left = min($left, $right);
$this->_top = min($top, $bottom);
$this->_right = max($left, $right);
$this->_bottom = max($top, $bottom);
}
/**
* Moves the element
*
* @param int $deltaX Number of pixels to move the element to the right
* (negative values move to the left)
* @param int $deltaY Number of pixels to move the element downwards
* (negative values move upwards)
* @access private
*/
function _move($deltaX, $deltaY)
{
$this->_left += $deltaX;
$this->_right += $deltaX;
$this->_top += $deltaY;
$this->_bottom += $deltaY;
}
/**
* Sets the width of the element relative to the left side
*
* @param int $width Number of pixels the element should be in width
* @access private
*/
function _setWidth($width)
{
$this->_right = $this->_left + $width;
}
/**
* Sets the height of the element relative to the top
*
* @param int $width Number of pixels the element should be in height
* @access private
*/
function _setHeight($height)
{
$this->_bottom = $this->_top + $height;
}
/**
* Sets padding of the element
*
* @param int $padding Number of pixels the element should be padded with
*/
function setPadding($padding)
{
$this->_padding = $padding;
}
/**
* The width of the element on the canvas
*
* @return int Number of pixels representing the width of the element
*/
function width()
{
return abs($this->_right - $this->_left) + 1;
}
/**
* The height of the element on the canvas
*
* @return int Number of pixels representing the height of the element
*/
function height()
{
return abs($this->_bottom - $this->_top) + 1;
}
/**
* Left boundary of the background fill area
*
* @return int Leftmost position on the canvas
* @access private
*/
function _fillLeft()
{
return $this->_left + $this->_padding;
}
/**
* Top boundary of the background fill area
*
* @return int Topmost position on the canvas
* @access private
*/
function _fillTop()
{
return $this->_top + $this->_padding;
}
/**
* Right boundary of the background fill area
*
* @return int Rightmost position on the canvas
* @access private
*/
function _fillRight()
{
return $this->_right - $this->_padding;
}
/**
* Bottom boundary of the background fill area
*
* @return int Bottommost position on the canvas
* @access private
*/
function _fillBottom()
{
return $this->_bottom - $this->_padding;
}
/**
* Returns the filling width of the element on the canvas
*
* @return int Filling width
* @access private
*/
function _fillWidth()
{
return $this->_fillRight() - $this->_fillLeft() + 1;
}
/**
* Returns the filling height of the element on the canvas
*
* @return int Filling height
* @access private
*/
function _fillHeight()
{
return $this->_fillBottom() - $this->_fillTop() + 1;
}
/**
* Draws a shadow 'around' the element
*
* Not implemented yet.
*
* @access private
*/
function _displayShadow()
{
if (is_array($this->_shadow)) {
$this->_canvas->startGroup(get_class($this) . '_shadow');
$this->_canvas->setFillColor($this->_shadow['color']);
$this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_top + $this->_shadow['size']));
$this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_top + $this->_shadow['size']));
$this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size']));
$this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size']));
$this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + 1));
$this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_bottom + 1));
$this->_canvas->polygon(array('connect' => true));
$this->_canvas->endGroup();
}
}
/**
* Writes text to the canvas.
*
* @param int $x The x position relative to alignment
* @param int $y The y position relative to alignment
* @param string $text The text
* @param int $alignmen The text alignment (both vertically and horizontally)
*/
function write($x, $y, $text, $alignment = false, $font = false)
{
if (($font === false) && ($this->_defaultFontOptions !== false)) {
$font = $this->_defaultFontOptions;
} else {
$font = $this->_getFont($font);
}
if ($alignment === false) {
$alignment = IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_TOP;
}
$align = array();
if (($alignment & IMAGE_GRAPH_ALIGN_TOP) != 0) {
$align['vertical'] = 'top';
} else if (($alignment & IMAGE_GRAPH_ALIGN_BOTTOM) != 0) {
$align['vertical'] = 'bottom';
} else {
$align['vertical'] = 'center';
}
if (($alignment & IMAGE_GRAPH_ALIGN_LEFT) != 0) {
$align['horizontal'] = 'left';
} else if (($alignment & IMAGE_GRAPH_ALIGN_RIGHT) != 0) {
$align['horizontal'] = 'right';
} else {
$align['horizontal'] = 'center';
}
$this->_canvas->setFont($font);
$this->_canvas->addText(array('x' => $x, 'y' => $y, 'text' => $text, 'alignment' => $align));
}
/**
* Output the element to the canvas
*
* @return bool Was the output 'good' (true) or 'bad' (false).
* @see Image_Graph_Common
* @access private
*/
function _done()
{
$background = $this->_getBackground();
$border = $this->_getBorderStyle();
if (($background) || ($border)) {
$this->_canvas->rectangle(array('x0' => $this->_left, 'y0' => $this->_top, 'x1' => $this->_right, 'y1' => $this->_bottom));
}
$result = parent::_done();
if ($this->_shadow !== false) {
$this->_displayShadow();
}
return $result;
}
}
?>