home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / Image / Graph / Axis.php next >
Encoding:
PHP Script  |  2008-07-02  |  58.7 KB  |  1,690 lines

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  4.  
  5. /**
  6.  * Class for axis handling.
  7.  *
  8.  * PHP versions 4 and 5
  9.  *
  10.  * LICENSE: This library is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU Lesser General Public License as published by
  12.  * the Free Software Foundation; either version 2.1 of the License, or (at your
  13.  * option) any later version. This library is distributed in the hope that it
  14.  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  15.  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
  16.  * General Public License for more details. You should have received a copy of
  17.  * the GNU Lesser General Public License along with this library; if not, write
  18.  * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  19.  * 02111-1307 USA
  20.  *
  21.  * @category   Images
  22.  * @package    Image_Graph
  23.  * @subpackage Axis
  24.  * @author     Jesper Veggerby <pear.nosey@veggerby.dk>
  25.  * @copyright  Copyright (C) 2003, 2004 Jesper Veggerby Hansen
  26.  * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
  27.  * @version    CVS: $Id: Axis.php,v 1.35 2006/02/28 22:48:07 nosey Exp $
  28.  * @link       http://pear.php.net/package/Image_Graph
  29.  */
  30.  
  31. /**
  32.  * Include file Image/Graph/Plotarea/Element.php
  33.  */
  34. require_once 'Image/Graph/Plotarea/Element.php';
  35.  
  36. /**
  37.  * Diplays a normal linear axis (either X- or Y-axis).
  38.  *
  39.  * @category   Images
  40.  * @package    Image_Graph
  41.  * @subpackage Axis
  42.  * @author     Jesper Veggerby <pear.nosey@veggerby.dk>
  43.  * @copyright  Copyright (C) 2003, 2004 Jesper Veggerby Hansen
  44.  * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
  45.  * @version    Release: 0.7.2
  46.  * @link       http://pear.php.net/package/Image_Graph
  47.  */
  48.  class Image_Graph_Axis extends Image_Graph_Plotarea_Element
  49. {
  50.     
  51.     /**
  52.      * The type of the axis, possible values are:
  53.      * <ul>
  54.      * <li>IMAGE_GRAPH_AXIS_X / IMAGE_GRAPH_AXIS_HORIZONTAL
  55.      * <li>IMAGE_GRAPH_AXIS_Y / IMAGE_GRAPH_AXIS_VERTICAL /
  56.      * IMAGE_GRAPH_AXIS_Y_SECONDARY
  57.      * </ul>
  58.      * @var int
  59.      * @access private
  60.      */
  61.     var $_type;
  62.  
  63.     /**
  64.      * The minimum value the axis displays
  65.      * @var int
  66.      * @access private
  67.      */
  68.     var $_minimum = false;
  69.  
  70.     /**
  71.      * The minimum value the axis has been explicitly set by the user
  72.      * @var bool
  73.      * @access private
  74.      */
  75.     var $_minimumSet = false;
  76.  
  77.     /**
  78.      * The maximum value the axis displays
  79.      * @var int
  80.      * @access private
  81.      */
  82.     var $_maximum = false;
  83.  
  84.     /**
  85.      * The maximum value the axis has been explicitly set by the user
  86.      * @var bool
  87.      * @access private
  88.      */
  89.     var $_maximumSet = false;
  90.  
  91.     /**
  92.      * The value span of the axis.
  93.      * This is primarily included for performance reasons
  94.      * @var double
  95.      * @access private
  96.      */
  97.     var $_axisSpan = false;
  98.  
  99.     /**
  100.      * The value span of the axis.
  101.      * This is primarily included for performance reasons
  102.      * @var double
  103.      * @access private
  104.      */
  105.     var $_axisValueSpan = false;
  106.     
  107.     /**
  108.      * The axis padding.
  109.      * The index 'low' specifies the padding for the low axis values (when not
  110.      * inverted), i.e. to the left on an x-axis and on the bottom of an y-axis,
  111.      * vice versa for 'high'.
  112.      * 
  113.      * Axis padding does not make sense on a normal linear y-axis with a 'y-min'
  114.      * of 0 since this corresponds to displaying a small part of the y-axis
  115.      * below 0!
  116.      * 
  117.      * @var array
  118.      * @access private
  119.      */
  120.     var $_axisPadding = array('low' => 0, 'high' => 0);
  121.  
  122.     /**
  123.      * The number of "pixels" representing 1 unit on the axis
  124.      *
  125.      * This is primarily included for performance reasons
  126.      * @var double
  127.      * @access private
  128.      */
  129.     var $_delta = false;
  130.     
  131.     /**
  132.      * Specify if the axis should label the minimum value
  133.      * @var bool
  134.      * @access private
  135.      */
  136.     var $_showLabelMinimum = true;
  137.  
  138.     /**
  139.      * Specify if the axis should label 0 (zero)
  140.      * @var bool
  141.      * @access private
  142.      */
  143.     var $_showLabelZero = false;
  144.  
  145.     /**
  146.      * Specify if the axis should label the maximum value
  147.      * @var bool
  148.      * @access private
  149.      */
  150.     var $_showLabelMaximum = true;
  151.  
  152.     /**
  153.      * Show arrow heads at the 'end' of the axis, default: false
  154.      * @var bool
  155.      * @access private
  156.      */
  157.     var $_showArrow = false;
  158.  
  159.     /**
  160.      * Intersection data of axis
  161.      * @var array
  162.      * @access private
  163.      */
  164.     var $_intersect = array('value' => 'default', 'axis' => 'default');
  165.  
  166.     /**
  167.      * The fixed size of the axis (i.e. width for y-axis, height for x-axis)
  168.      * @var mixed
  169.      * @access private
  170.      */
  171.     var $_fixedSize = false;
  172.  
  173.     /**
  174.      * The label options
  175.      *
  176.      * Should text be shows, preferences for ticks. The indexes start at level
  177.      * 1, which is chosen for readability
  178.      * @var array
  179.      * @access private
  180.      */
  181.     var $_labelOptions = array(
  182.         1 => array(
  183.             'interval' => 1,
  184.             'type' => 'auto',
  185.             'tick' => array(
  186.                 'start' => -2, 
  187.                 'end' => 2, 
  188.                 'color' => false // default color
  189.             ),
  190.             'showtext' => true,
  191.             'showoffset' => false,
  192.             'font' => array(),
  193.             'offset' => 0,
  194.             'position' => 'outside',            
  195.         )
  196.     );
  197.  
  198.     /**
  199.      * The labels that are shown.
  200.      *
  201.      * This is used to make values show only once...
  202.      * @access private
  203.      */
  204.     var $_labelText = array();
  205.  
  206.     /**
  207.      * A data preprocessor for formatting labels, fx showing dates as a standard
  208.      * date instead of Unix time stamp
  209.      * @var Image_Graph_DatePreProcessor
  210.      * @access private
  211.      * @see Image_Graph_DataPreProcessor
  212.      */
  213.     var $_dataPreProcessor = null;
  214.  
  215.     /**
  216.      * Point marked in the axis
  217.      * @var array
  218.      * @access private
  219.      */
  220.     var $_marks = array();
  221.  
  222.     /**
  223.      * Specifies whether the values should be 'pushed' by 0.5
  224.      * @var bool
  225.      * @access private
  226.      */
  227.     var $_pushValues = false;
  228.  
  229.     /**
  230.      * The title of this axis
  231.      * @var string
  232.      * @access private
  233.      */
  234.     var $_title = '';
  235.  
  236.     /**
  237.      * The font used for the title of this axis
  238.      * @var Image_Graph_Font
  239.      * @access private
  240.      */
  241.     var $_titleFont = false;
  242.     
  243.     /**
  244.      * Invert the axis (i.e. if an y-axis normally displays minimum values at
  245.      * the bottom, they are not displayed at the top
  246.      * @var bool
  247.      * @access private
  248.      * @since 0.3.0dev3
  249.      */
  250.     var $_invert = false;
  251.     
  252.     /**
  253.      * Transpose the axis (i.e. is a normal y-axis transposed, so thats it's not show
  254.      * vertically as normally expected, but instead horizontally)
  255.      * @var bool
  256.      * @access private
  257.      */
  258.     var $_transpose = false;
  259.  
  260.     /**
  261.      * Image_Graph_Axis [Constructor].
  262.      * Normally a manual creation should not be necessary, axis are created
  263.      * automatically by the {@link Image_Graph_Plotarea} constructor unless
  264.      * explicitly defined otherwise
  265.      *
  266.      * @param int $type The type (direction) of the Axis, use IMAGE_GRAPH_AXIS_X
  267.      * for an X-axis (default, may be omitted) and IMAGE_GRAPH_AXIS_Y for Y-
  268.      * axis)
  269.      */
  270.     function Image_Graph_Axis($type = IMAGE_GRAPH_AXIS_X)
  271.     {
  272.         parent::Image_Graph_Element();
  273.         $this->_type = $type;
  274.         $this->_fillStyle = 'black';
  275.     }
  276.  
  277.     /**
  278.      * Push the values by 0.5 (for bar and step chart)
  279.      *
  280.      * @access private
  281.      */
  282.     function _pushValues()
  283.     {
  284.         $this->_pushValues = true;
  285.     }
  286.     
  287.     /**
  288.      * Sets the axis padding for a given position ('low' or 'high')
  289.      * @param string $where The position
  290.      * @param int $value The number of pixels to "pad"
  291.      * @access private
  292.      */
  293.     function _setAxisPadding($where, $value)
  294.     {
  295.         $this->_axisPadding[$where] = $value;
  296.     }     
  297.  
  298.     /**
  299.      * Gets the font of the title.
  300.      *
  301.      * If not font has been set, the parent font is propagated through it's
  302.      * children.
  303.      *
  304.      * @return array An associated array used for canvas
  305.      * @access private
  306.      */
  307.     function _getTitleFont()
  308.     {
  309.         if ($this->_titleFont === false) {
  310.             if ($this->_defaultFontOptions !== false) {
  311.                 return $this->_defaultFontOptions;
  312.             } else {
  313.                 return $this->_getFont();
  314.             }
  315.         } else {
  316.             if (is_object($this->_titleFont)) {
  317.                 return $this->_titleFont->_getFont();
  318.             } elseif (is_array($this->_titleFont)) {
  319.                 return $this->_getFont($this->_titleFont);
  320.             } elseif (is_int($this->_titleFont)) {
  321.                 return $this->_getFont(array('size' => $this->_titleFont));
  322.             }
  323.         }
  324.         return array();
  325.     }
  326.  
  327.     /**
  328.      * Shows a label for the the specified values.
  329.      *
  330.      * Allowed values are  combinations of:
  331.      * <ul>
  332.      * <li>IMAGE_GRAPH_LABEL_MINIMUM
  333.      * <li>IMAGE_GRAPH_LABEL_ZERO
  334.      * <li>IMAGE_GRAPH_LABEL_MAXIMUM
  335.      * </ul>
  336.      * By default none of these are shows on the axis
  337.      *
  338.      * @param int $value The values to show labels for
  339.      */
  340.     function showLabel($value)
  341.     {
  342.         $this->_showLabelMinimum = ($value & IMAGE_GRAPH_LABEL_MINIMUM);
  343.         $this->_showLabelZero = ($value & IMAGE_GRAPH_LABEL_ZERO);
  344.         $this->_showLabelMaximum = ($value & IMAGE_GRAPH_LABEL_MAXIMUM);
  345.     }
  346.  
  347.     /**
  348.      * Sets a data preprocessor for formatting the axis labels
  349.      *
  350.      * @param Image_Graph_DataPreprocessor $dataPreProcessor The data preprocessor
  351.      * @see Image_Graph_DataPreprocessor
  352.      */
  353.     function setDataPreProcessor(& $dataPreProcessor)
  354.     {
  355.         $this->_dataPreProcessor =& $dataPreProcessor;
  356.     }
  357.  
  358.     /**
  359.      * Gets the minimum value the axis will show
  360.      *
  361.      * @return double The minumum value
  362.      * @access private
  363.      */
  364.     function _getMinimum()
  365.     {
  366.         return $this->_minimum;
  367.     }
  368.  
  369.     /**
  370.      * Gets the maximum value the axis will show
  371.      *
  372.      * @return double The maximum value
  373.      * @access private
  374.      */
  375.     function _getMaximum()
  376.     {
  377.         return $this->_maximum;
  378.     }
  379.  
  380.     /**
  381.      * Sets the minimum value the axis will show
  382.      *
  383.      * @param double $minimum The minumum value to use on the axis
  384.      * @access private
  385.      */
  386.     function _setMinimum($minimum)
  387.     {
  388.         if ($this->_minimum === false) {
  389.             $this->forceMinimum($minimum, false);
  390.         } else {
  391.             $this->forceMinimum(min($this->_minimum, $minimum), false);
  392.         }
  393.     }
  394.  
  395.     /**
  396.      * Sets the maximum value the axis will show
  397.      *
  398.      * @param double $maximum The maximum value to use on the axis
  399.      * @access private
  400.      */
  401.     function _setMaximum($maximum)
  402.     {
  403.         if ($this->_maximum === false) {
  404.             $this->forceMaximum($maximum, false);
  405.         } else {
  406.             $this->forceMaximum(max($this->_maximum, $maximum), false);
  407.         }
  408.     }
  409.  
  410.     /**
  411.      * Forces the minimum value of the axis
  412.      *
  413.      * @param double $minimum The minumum value to use on the axis
  414.      * @param bool $userEnforce This value should not be set, used internally
  415.      */
  416.     function forceMinimum($minimum, $userEnforce = true)
  417.     {        
  418.         if (($userEnforce) || (!$this->_minimumSet)) {
  419.             $this->_minimum = $minimum;
  420.             $this->_minimumSet = $userEnforce;
  421.         }
  422.         $this->_calcLabelInterval();
  423.     }
  424.  
  425.     /**
  426.      * Forces the maximum value of the axis
  427.      *
  428.      * @param double $maximum The maximum value to use on the axis
  429.      * @param bool $userEnforce This value should not be set, used internally
  430.      */
  431.     function forceMaximum($maximum, $userEnforce = true)
  432.     {
  433.         if (($userEnforce) || (!$this->_maximumSet)) {
  434.             $this->_maximum = $maximum;
  435.             $this->_maximumSet = $userEnforce;
  436.         }
  437.         $this->_calcLabelInterval();
  438.     }
  439.  
  440.     /**
  441.      * Show an arrow head on the 'end' of the axis
  442.      */
  443.     function showArrow()
  444.     {
  445.         $this->_showArrow = true;
  446.     }
  447.  
  448.     /**
  449.      * Do not show an arrow head on the 'end' of the axis (default)
  450.      */
  451.     function hideArrow()
  452.     {
  453.         $this->_showArrow = false;
  454.     }
  455.  
  456.     /**
  457.      * Return the label distance.
  458.      *
  459.      * @param int $level The label level to return the distance of
  460.      * @return int The distance between 2 adjacent labels
  461.      * @access private
  462.      */
  463.     function _labelDistance($level = 1)
  464.     {
  465.         $l1 = $this->_getNextLabel(false, $level);
  466.         $l2 = $this->_getNextLabel($l1, $level);;
  467.         return abs($this->_point($l2) - $this->_point($l1));
  468.     }
  469.  
  470.     /**
  471.      * Sets an interval for when labels are shown on the axis.
  472.      *
  473.      * By default 'auto' is used, forcing the axis to calculate a approximate
  474.      * best label interval to be used. Specify an array to use user-defined
  475.      * values for labels.
  476.      *
  477.      * @param mixed $labelInterval The interval with which labels are shown
  478.      * @param int $level The label level to set the interval on
  479.      */
  480.     function setLabelInterval($labelInterval = 'auto', $level = 1)
  481.     {
  482.         if (!isset($this->_labelOptions[$level])) {
  483.             $this->_labelOptions[$level] = array();
  484.         }
  485.  
  486.         if ($labelInterval === 'auto') {
  487.             $this->_labelOptions[$level]['type'] = 'auto';
  488.             $this->_calcLabelInterval();
  489.         } else {
  490.             $this->_labelOptions[$level]['type'] = 'manual';
  491.             $this->_labelOptions[$level]['interval'] = $labelInterval;
  492.         }
  493.     }
  494.  
  495.     /**
  496.      * Sets options for the label at a specific level.
  497.      *
  498.      * Possible options are:
  499.      * 
  500.      * 'showtext' true or false whether label text should be shown or not
  501.      * 
  502.      * 'showoffset' should the label be shown at an offset, i.e. should the
  503.      * label be shown at a position so that it does not overlap with prior
  504.      * levels. Only applies to multilevel labels with text
  505.      * 
  506.      * 'font' The font options as an associated array
  507.      * 
  508.      * 'position' The position at which the labels are written ('inside' or
  509.      * 'outside' the axis). NB! This relative position only applies to the
  510.      * default location of the axis, i.e. if an x-axis is inverted then
  511.      * 'outside' still refers to the "left" side of a normal y-axis (since this
  512.      * is normally 'outside') but the actual output will be labels on the
  513.      * "inside"!
  514.      *
  515.      * 'format' To format the label text according to a sprintf statement
  516.      *
  517.      * 'dateformat' To format the label as a date, fx. j. M Y = 29. Jun 2005
  518.      *
  519.      * @param string $option The label option name (see detailed description
  520.      * for possible values)
  521.      * @param mixed $value The value for the option
  522.      * @param int $level The label level to set the interval on
  523.      */
  524.     function setLabelOption($option, $value, $level = 1)
  525.     {
  526.         if (!isset($this->_labelOptions[$level])) {
  527.             $this->_labelOptions[$level] = array('type' => 'auto');
  528.         }
  529.  
  530.         $this->_labelOptions[$level][$option] = $value;
  531.     }
  532.  
  533.     /**
  534.      * Sets options for the label at a specific level.
  535.      *
  536.      * The possible options are specified in {@link Image_Graph_Axis::
  537.      * setLabelOption()}.
  538.      *
  539.      * @param array $options An assciated array with label options
  540.      * @param int $level The label level to set the interval on
  541.      */
  542.     function setLabelOptions($options, $level = 1)
  543.     {
  544.         if (is_array($options)) {
  545.             if (isset($this->_labelOptions[$level])) {
  546.                 $this->_labelOptions[$level] = array_merge($this->_labelOptions[$level], $options);
  547.             } else {
  548.                 $this->_labelOptions[$level] = $options;
  549.             }
  550.                 
  551.         }
  552.     }    
  553.     
  554.     /**
  555.      * Sets the title of this axis.
  556.      *
  557.      * This is used as an alternative (maybe better) method, than using layout's
  558.      * for axis-title generation.
  559.      * 
  560.      * To use the current propagated font, but just set it vertically, simply
  561.      * pass 'vertical' as second parameter for vertical alignment down-to-up or
  562.      * 'vertical2' for up-to-down alignment.
  563.      *
  564.      * @param string $title The title of this axis
  565.      * @param Image_Graph_Font $font The font used for the title
  566.      * @since 0.3.0dev2
  567.      */
  568.     function setTitle($title, $font = false)
  569.     {
  570.         $this->_title = $title;
  571.         if ($font === 'vertical') {
  572.             $this->_titleFont = array('vertical' => true, 'angle' => 90);
  573.         } elseif ($font === 'vertical2') {
  574.             $this->_titleFont = array('vertical' => true, 'angle' => 270);
  575.         } else {
  576.             $this->_titleFont =& $font;
  577.         }
  578.     }
  579.  
  580.     /**
  581.      * Sets a fixed "size" for the axis.
  582.      * 
  583.      * If the axis is any type of y-axis the size relates to the width of the
  584.      * axis, if an x-axis is concerned the size is the height.
  585.      *
  586.      * @param int $size The fixed size of the axis
  587.      * @since 0.3.0dev5
  588.      */
  589.     function setFixedSize($size)
  590.     {
  591.         $this->_fixedSize = $size;
  592.     }
  593.  
  594.     /**
  595.      * Preprocessor for values, ie for using logarithmic axis
  596.      *
  597.      * @param double $value The value to preprocess
  598.      * @return double The preprocessed value
  599.      * @access private
  600.      */
  601.     function _value($value)
  602.     {
  603.         return $value - $this->_getMinimum() + ($this->_pushValues ? 0.5 : 0);
  604.     }
  605.  
  606.     /**
  607.      * Apply the dataset to the axis
  608.      *
  609.      * @param Image_Graph_Dataset $dataset The dataset
  610.      * @access private
  611.      */
  612.     function _applyDataset(&$dataset)
  613.     {
  614.         if ($this->_type == IMAGE_GRAPH_AXIS_X) {
  615.             $this->_setMinimum($dataset->minimumX());
  616.             $this->_setMaximum($dataset->maximumX());
  617.         } else {
  618.             $this->_setMinimum($dataset->minimumY());
  619.             $this->_setMaximum($dataset->maximumY());
  620.         }
  621.     }
  622.  
  623.     /**
  624.      * Get the pixel position represented by a value on the canvas
  625.      *
  626.      * @param double $value the value to get the pixel-point for
  627.      * @return double The pixel position along the axis
  628.      * @access private
  629.      */
  630.     function _point($value)    
  631.     {        
  632.         if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) ||
  633.            (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) 
  634.         {
  635.             if ($this->_invert) {                
  636.                 return max($this->_left, $this->_right - $this->_axisPadding['high'] - $this->_delta * $this->_value($value));
  637.             } else {
  638.                 return min($this->_right, $this->_left + $this->_axisPadding['low'] + $this->_delta * $this->_value($value));
  639.             }                
  640.         } else {
  641.             if ($this->_invert) {                
  642.                 return min($this->_bottom, $this->_top + $this->_axisPadding['high'] + $this->_delta * $this->_value($value));
  643.             } else {
  644.                 return max($this->_top, $this->_bottom - $this->_axisPadding['low'] - $this->_delta * $this->_value($value));
  645.             }
  646.         }
  647.     }
  648.  
  649.  
  650.     /**
  651.      * Get the axis intersection pixel position
  652.      *
  653.      * This is only to be called prior to output! I.e. between the user
  654.      * invokation of Image_Graph::done() and any actual output is performed.
  655.      * This is because it can change the axis range.
  656.      *
  657.      * @param double $value the intersection value to get the pixel-point for
  658.      * @return double The pixel position along the axis
  659.      * @access private
  660.      */
  661.     function _intersectPoint($value)
  662.     {
  663.  
  664.         if (($value === 'min') || ($value < $this->_getMinimum())) {
  665.             if ($this->_type == IMAGE_GRAPH_AXIS_X) {
  666.                 if ($this->_invert) {
  667.                     return ($this->_transpose ? $this->_top : $this->_right);
  668.                 } else {
  669.                     return ($this->_transpose ? $this->_bottom : $this->_left);
  670.                 }
  671.             } else {
  672.                 if ($this->_invert) {
  673.                     return ($this->_transpose ? $this->_right : $this->_top);
  674.                 } else {
  675.                     return ($this->_transpose ? $this->_left : $this->_bottom);
  676.                 }
  677.             }
  678.         } elseif (($value === 'max') || ($value > $this->_getMaximum())) {
  679.             if ($this->_type == IMAGE_GRAPH_AXIS_X) {
  680.                 if ($this->_invert) {
  681.                     return ($this->_transpose ? $this->_bottom : $this->_left);
  682.                 } else {
  683.                     return ($this->_transpose ? $this->_top : $this->_right);
  684.                 }
  685.             } else {
  686.                 if ($this->_invert) {
  687.                     return ($this->_transpose ? $this->_left : $this->_bottom);
  688.                 } else {
  689.                     return ($this->_transpose ? $this->_right : $this->_top);
  690.                 }
  691.             }
  692.         } 
  693.         
  694.         return $this->_point($value);
  695.     }
  696.     
  697.     /**
  698.      * Calculate the delta value (the number of pixels representing one unit
  699.      * on the axis)
  700.      *
  701.      * @return double The label interval
  702.      * @access private
  703.      */
  704.     function _calcDelta()
  705.     {
  706.         if ($this->_axisValueSpan == 0) {
  707.             $this->_delta = false;
  708.         } elseif ($this->_type == IMAGE_GRAPH_AXIS_X) {
  709.             $this->_delta = (($this->_transpose ? $this->height() : $this->width()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / ($this->_axisValueSpan + ($this->_pushValues ? 1 : 0));
  710.         } else {
  711.             $this->_delta = (($this->_transpose ? $this->width() : $this->height()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / ($this->_axisValueSpan + ($this->_pushValues ? 1 : 0));
  712.         }
  713.     }        
  714.     
  715.     /**
  716.      * Calculate the label interval
  717.      *
  718.      * If explicitly defined this will be calucated to an approximate best.
  719.      *
  720.      * @return double The label interval
  721.      * @access private
  722.      */
  723.     function _calcLabelInterval()
  724.     {
  725.         $min = $this->_getMinimum();
  726.         $max = $this->_getMaximum();
  727.         
  728.         $this->_axisValueSpan = $this->_axisSpan = abs($max - $min);
  729.         
  730.         if ((!empty($min)) && (!empty($max)) && ($min > $max)) {
  731.             $this->_labelOptions[1]['interval'] = 1;
  732.             return true;
  733.         }
  734.  
  735.         $span = 0;
  736.         foreach($this->_labelOptions as $level => $labelOptions) {
  737.             if ((!isset($labelOptions['type'])) || ($labelOptions['type'] !== 'auto')) {
  738.                 $span = false;
  739.             } elseif ($level == 1) {
  740.                 $span = $this->_axisValueSpan;
  741.             } else {
  742.                 $l1 = $this->_getNextLabel(false, $level - 1);
  743.                 $l2 = $this->_getNextLabel($l1, $level - 1);
  744.                 if ((!is_numeric($l1)) || (!is_numeric($l2))) {
  745.                     $span == false;
  746.                 } else {
  747.                     $span = $l2 - $l1;
  748.                 }
  749.             }
  750.  
  751.             if ($span !== false) {
  752.                 $interval = pow(10, floor(log10($span)));
  753.  
  754.                 if ($interval == 0) {
  755.                     $interval = 1;
  756.                 }
  757.  
  758.                 if ((($span) / $interval) < 3) {
  759.                     $interval = $interval / 4;
  760.                 } elseif ((($span) / $interval) < 5) {
  761.                     $interval = $interval / 2;
  762.                 } elseif ((($span) / $interval) > 10) {
  763.                     $interval = $interval * 2;
  764.                 }
  765.  
  766.                 if (($interval -floor($interval) == 0.5) && ($interval != 0.5)) {
  767.                     $interval = floor($interval);
  768.                 }
  769.  
  770.                 // just to be 100% sure that an interval of 0 is not returned some
  771.                 // additional checks are performed
  772.                 if ($interval == 0) {
  773.                     $interval = ($span) / 5;
  774.                 }
  775.  
  776.                 if ($interval == 0) {
  777.                     $interval = 1;
  778.                 }
  779.  
  780.                 $this->_labelOptions[$level]['interval'] = $interval;
  781.             }
  782.         }
  783.     }
  784.  
  785.     /**
  786.      * Get next label point
  787.      *
  788.      * @param doubt $currentLabel The current label, if omitted or false, the
  789.      *   first is returned
  790.      * @param int $level The label level to get the next label from
  791.      * @return double The next label point
  792.      * @access private
  793.      */
  794.     function _getNextLabel($currentLabel = false, $level = 1)
  795.     {
  796.         if (!isset($this->_labelOptions[$level])) {
  797.             return false;
  798.         }
  799.  
  800.         if (is_array($this->_labelOptions[$level]['interval'])) {
  801.             if ($currentLabel === false) {
  802.                 reset($this->_labelOptions[$level]['interval']);
  803.             }
  804.  
  805.             if (list(, $label) = each($this->_labelOptions[$level]['interval'])) {
  806.                 return $label;
  807.             } else {
  808.                 return false;
  809.             }
  810.         } else {
  811.             $li = $this->_labelInterval($level);
  812.             if (($this->_axisSpan == 0) || ($this->_axisValueSpan == 0) ||
  813.                 ($li == 0)
  814.             ) {
  815.                 return false;
  816.             }
  817.  
  818.             $labelInterval = $this->_axisSpan / ($this->_axisValueSpan / $li);
  819.  
  820.             if ($labelInterval == 0) {
  821.                 return false;
  822.             }
  823.  
  824.             if ($currentLabel === false) {
  825.                 $label = ((int) ($this->_getMinimum() / $labelInterval)) *
  826.                     $labelInterval - $labelInterval;
  827.                 while ($label < $this->_getMinimum()) {
  828.                     $label += $labelInterval;
  829.                 }
  830.                 return $label;
  831.             } else {
  832.                 if ($currentLabel + $labelInterval > $this->_getMaximum()) {
  833.                     return false;
  834.                 } else {
  835.                     return $currentLabel + $labelInterval;
  836.                 }
  837.             }
  838.         }
  839.     }
  840.  
  841.     /**
  842.      * Get the interval with which labels are shown on the axis.
  843.      *
  844.      * If explicitly defined this will be calucated to an approximate best.
  845.      *
  846.      * @param int $level The label level to get the label interval for
  847.      * @return double The label interval
  848.      * @access private
  849.      */
  850.     function _labelInterval($level = 1)
  851.     {
  852.         if ((!isset($this->_labelOptions[$level])) ||
  853.             (!isset($this->_labelOptions[$level]['interval']))
  854.         ) {
  855.             return 1;
  856.         }
  857.  
  858.         return (is_array($this->_labelOptions[$level]['interval'])
  859.             ? 1
  860.             : $this->_labelOptions[$level]['interval']
  861.         );
  862.     }
  863.  
  864.     /**
  865.      * Get the size in pixels of the axis.
  866.      *
  867.      * For an x-axis this is the width of the axis including labels, and for an
  868.      * y-axis it is the corrresponding height
  869.      *
  870.      * @return int The size of the axis
  871.      * @access private
  872.      */
  873.     function _size()
  874.     {
  875.         if (!$this->_visible) {
  876.             return 0;
  877.         }
  878.         
  879.         if ($this->_fixedSize !== false) {
  880.             return $this->_fixedSize;
  881.         }
  882.          
  883.         krsort($this->_labelOptions);
  884.  
  885.         $totalMaxSize = 0;
  886.  
  887.         foreach ($this->_labelOptions as $level => $labelOptions) {
  888.             if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) {
  889.                 $this->_labelOptions[$level]['offset'] += $totalMaxSize;
  890.             } elseif (!isset($this->_labelOptions[$level]['offset'])) {
  891.                 $this->_labelOptions[$level]['offset'] = 0;
  892.             }
  893.             if (
  894.                 (isset($labelOptions['showtext'])) &&                
  895.                 ($labelOptions['showtext'] === true) &&
  896.                 (
  897.                     (!isset($labelOptions['position'])) ||
  898.                     ($labelOptions['position'] == 'outside')
  899.                 )               
  900.             ) {
  901.                 if (isset($labelOptions['font'])) {
  902.                     $font = $this->_getFont($labelOptions['font']);
  903.                 } else {
  904.                     if ($this->_defaultFontOptions !== false) {
  905.                         $font = $this->_defaultFontOptions;
  906.                     } else {
  907.                         $font = $this->_getFont();
  908.                     }
  909.                 }
  910.                 $this->_canvas->setFont($font);
  911.  
  912.                 $value = false;
  913.                 $maxSize = 0;
  914.                 while (($value = $this->_getNextLabel($value, $level)) !== false) {
  915.                     if ((abs($value) > 0.0001) && ($value > $this->_getMinimum()) &&
  916.                         ($value < $this->_getMaximum()))
  917.                     {
  918.                         if (is_object($this->_dataPreProcessor)) {
  919.                             $labelText = $this->_dataPreProcessor->_process($value);
  920.                         } elseif (isset($labelOptions['format'])) {
  921.                             $labelText = sprintf($labelOptions['format'], $value);
  922.                         } elseif (isset($labelOptions['dateformat'])) {
  923.                             $labelText = date($labelOptions['dateformat'], $value);
  924.                         } else {
  925.                             $labelText = $value;
  926.                         }
  927.  
  928.                         if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) ||
  929.                            (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose)))
  930.                         {
  931.                             $maxSize = max($maxSize, $this->_canvas->textHeight($labelText));
  932.                         } else {
  933.                             $maxSize = max($maxSize, $this->_canvas->textWidth($labelText));
  934.                         }
  935.                     }
  936.                 }
  937.                 if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) {
  938.                     $totalMaxSize += $maxSize;
  939.                 } else {
  940.                     $totalMaxSize = max($totalMaxSize, $maxSize);
  941.                 }
  942.             }
  943.         }
  944.  
  945.         if ($this->_title) {
  946.             $this->_canvas->setFont($this->_getTitleFont());
  947.  
  948.             if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) ||
  949.                (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose)))
  950.             {
  951.                 $totalMaxSize += $this->_canvas->textHeight($this->_title);
  952.             } else {
  953.                 $totalMaxSize += $this->_canvas->textWidth($this->_title);
  954.             }
  955.             $totalMaxSize += 10;
  956.         }
  957.  
  958.         return $totalMaxSize + 3;
  959.     }
  960.  
  961.     /**
  962.      * Adds a mark to the axis at the specified value
  963.      *
  964.      * @param double $value The value
  965.      * @param double $value2 The second value (for a ranged mark)
  966.      */
  967.     function addMark($value, $value2 = false, $text = false)
  968.     {
  969.         if ($value2 === false) {
  970.             $this->_marks[] = $value;
  971.         } else {
  972.             $this->_marks[] = array($value, $value2);
  973.         }
  974.     }
  975.  
  976.     /**
  977.      * Is the axis numeric or not?
  978.      *
  979.      * @return bool True if numeric, false if not
  980.      * @access private
  981.      */
  982.     function _isNumeric()
  983.     {
  984.         return true;
  985.     }
  986.  
  987.     /**
  988.      * Set the major tick appearance.
  989.      *
  990.      * The positions are specified in pixels relative to the axis, meaning that
  991.      * a value of -1 for start will draw the major tick 'line' starting at 1
  992.      * pixel outside (negative) value the axis (i.e. below an x-axis and to the
  993.      * left of a normal y-axis).
  994.      *
  995.      * @param int $start The start position relative to the axis
  996.      * @param int $end The end position relative to the axis
  997.      * @param int $level The label level to set the tick options for
  998.      * @since 0.3.0dev2
  999.      */
  1000.     function setTickOptions($start, $end, $level = 1)
  1001.     {
  1002.         if (!isset($this->_labelOptions[$level])) {
  1003.             $this->_labelOptions[$level] = array();
  1004.         }
  1005.  
  1006.         $this->_labelOptions[$level]['tick'] = array(
  1007.             'start' => $start,
  1008.             'end' => $end
  1009.         );
  1010.     }
  1011.     
  1012.     /**
  1013.      * Invert the axis direction
  1014.      * 
  1015.      * If the minimum values are normally displayed fx. at the bottom setting
  1016.      * axis inversion to true, will cause the minimum values to be displayed at
  1017.      * the top and maximum at the bottom.
  1018.      *
  1019.      * @param bool $invert True if the axis is to be inverted, false if not
  1020.      * @since 0.3.0dev3
  1021.      */
  1022.     function setInverted($invert)
  1023.     {
  1024.         $this->_invert = $invert;
  1025.     }
  1026.  
  1027.     /**
  1028.      * Set axis intersection.
  1029.      *
  1030.      * Sets the value at which the axis intersects other axis, fx. at which Y-
  1031.      * value the x-axis intersects the y-axis (normally at 0).
  1032.      * 
  1033.      * Possible values are 'default', 'min', 'max' or a number between axis min
  1034.      * and max (the value will automatically be limited to this range).
  1035.      * 
  1036.      * For a coordinate system with 2 y-axis, the x-axis can either intersect
  1037.      * the primary or the secondary y-axis. To make the x-axis intersect the
  1038.      * secondary y-axis at a given value pass IMAGE_GRAPH_AXIS_Y_SECONDARY as
  1039.      * second parameter.
  1040.      *
  1041.      * @param mixed $intersection The value at which the axis intersect the
  1042.      * 'other' axis
  1043.      * @param mixed $axis The axis to intersect. Only applies to x-axis with
  1044.      * both a primary and secondary y-axis available.
  1045.      * @since 0.3.0dev2
  1046.      */
  1047.     function setAxisIntersection($intersection, $axis = 'default')
  1048.     {
  1049.         if ($axis == 'x') {
  1050.             $axis = IMAGE_GRAPH_AXIS_X;
  1051.         } elseif ($axis == 'y') {
  1052.             $axis = IMAGE_GRAPH_AXIS_Y;
  1053.         } elseif ($axis == 'ysec') {
  1054.             $axis = IMAGE_GRAPH_AXIS_Y_SECONDARY;
  1055.         }
  1056.         $this->_intersect = array(
  1057.             'value' => $intersection,
  1058.             'axis' => $axis
  1059.         );
  1060.     }
  1061.  
  1062.     /**
  1063.      * Get axis intersection data.
  1064.      * 
  1065.      * @return array An array with the axis intersection data.
  1066.      * @since 0.3.0dev2
  1067.      * @access private
  1068.      */
  1069.     function _getAxisIntersection()
  1070.     {
  1071.         $value = $this->_intersect['value'];
  1072.         $axis = $this->_intersect['axis'];
  1073.         if (($this->_type == IMAGE_GRAPH_AXIS_Y) 
  1074.             || ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY)
  1075.         ) {
  1076.             $axis = IMAGE_GRAPH_AXIS_X;
  1077.         } elseif ($axis == 'default') {
  1078.             $axis = IMAGE_GRAPH_AXIS_Y;
  1079.         }
  1080.         
  1081.         if ($value === 'default') {
  1082.             switch ($this->_type) {
  1083.             case IMAGE_GRAPH_AXIS_Y:
  1084.                 $value = 'min';
  1085.                 break;
  1086.             case IMAGE_GRAPH_AXIS_Y_SECONDARY:
  1087.                 $value = 'max';
  1088.                 break;
  1089.             case IMAGE_GRAPH_AXIS_X:
  1090.                 $value = 0;
  1091.                 break;
  1092.             }
  1093.         }
  1094.         
  1095.         return array('value' => $value, 'axis' => $axis);
  1096.     }
  1097.     
  1098.     /**
  1099.      * Resets the elements
  1100.      *
  1101.      * @access private
  1102.      */
  1103.     function _reset()
  1104.     {
  1105.         parent::_reset();
  1106.         $this->_labelText = array();
  1107.     }
  1108.     
  1109.     /**
  1110.      * Output an axis tick mark.
  1111.      *
  1112.      * @param int $value The value to output
  1113.      * @param int $level The label level to draw the tick for
  1114.      * @access private
  1115.      */
  1116.     function _drawTick($value, $level = 1)
  1117.     {
  1118.         if (isset($this->_labelOptions[$level])) {
  1119.             $labelOptions = $this->_labelOptions[$level];
  1120.             $labelPosition = $this->_point($value);
  1121.  
  1122.             if (isset($labelOptions['offset'])) {
  1123.                 $offset = $labelOptions['offset'];
  1124.             } else {
  1125.                 $offset = 0;
  1126.             }
  1127.  
  1128.             if ((isset($labelOptions['showtext'])) && ($labelOptions['showtext'] === true)) {
  1129.                 if (is_object($this->_dataPreProcessor)) {
  1130.                     $labelText = $this->_dataPreProcessor->_process($value);
  1131.                 } elseif (isset($labelOptions['format'])) {
  1132.                     $labelText = sprintf($labelOptions['format'], $value);
  1133.                 } elseif (isset($labelOptions['dateformat'])) {
  1134.                     $labelText = date($labelOptions['dateformat'], $value);
  1135.                 } else {
  1136.                     $labelText = $value;
  1137.                 }
  1138.  
  1139.                 if (!in_array($labelText, $this->_labelText)) {
  1140.                     $this->_labelText[] = $labelText;
  1141.  
  1142.                     if (isset($labelOptions['font'])) {
  1143.                         $font = $this->_getFont($labelOptions['font']);
  1144.                     } else {
  1145.                         if ($this->_defaultFontOptions !== false) {
  1146.                             $font = $this->_defaultFontOptions;
  1147.                         } else {
  1148.                             $font = $this->_getFont();
  1149.                         }
  1150.                     }
  1151.                     $this->_canvas->setFont($font);
  1152.                     
  1153.                     if (
  1154.                         (isset($labelOptions['position'])) && 
  1155.                         ($labelOptions['position'] == 'inside')
  1156.                     ) {
  1157.                         $labelInside = true;
  1158.                     } else {
  1159.                         $labelInside = false;
  1160.                     }
  1161.                                         
  1162.                     if ($this->_type == IMAGE_GRAPH_AXIS_Y) {
  1163.                         if ($this->_transpose) {
  1164.                             if ($labelInside) {
  1165.                                 $this->write(
  1166.                                     $labelPosition,
  1167.                                     $this->_top - 3 - $offset,
  1168.                                     $labelText,
  1169.                                     IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X,
  1170.                                     $font
  1171.                                 );
  1172.                             } else {
  1173.                                 $this->write(
  1174.                                     $labelPosition,
  1175.                                     $this->_top + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1),                                                                   
  1176.                                     $labelText,
  1177.                                     IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X,
  1178.                                     $font
  1179.                                 );
  1180.                             }
  1181.                         }
  1182.                         else {                        
  1183.                             if ($labelInside) {
  1184.                                 $this->write(
  1185.                                     $this->_right + 3 + $offset,
  1186.                                     $labelPosition,
  1187.                                     $labelText,
  1188.                                     IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT,
  1189.                                     $font
  1190.                                 );
  1191.                             } else {
  1192.                                 $this->write(
  1193.                                     $this->_right - 3 - $offset,
  1194.                                     $labelPosition,
  1195.                                     $labelText,
  1196.                                     IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT,
  1197.                                     $font
  1198.                                 );
  1199.                             }
  1200.                         }
  1201.                     } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
  1202.                         if ($this->_transpose) {
  1203.                             if ($labelInside) {
  1204.                                 $this->write(
  1205.                                     $labelPosition,
  1206.                                     $this->_bottom + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1),
  1207.                                     $labelText,
  1208.                                     IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X,
  1209.                                     $font
  1210.                                 );
  1211.                             } else {
  1212.                                 $this->write(
  1213.                                     $labelPosition,
  1214.                                     $this->_bottom - 3 - $offset,                                                                   
  1215.                                     $labelText,
  1216.                                     IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X,
  1217.                                     $font
  1218.                                 );
  1219.                             }
  1220.                         }
  1221.                         else {
  1222.                             if ($labelInside) {
  1223.                                 $this->write(
  1224.                                     $this->_left - 3 - $offset,
  1225.                                     $labelPosition,
  1226.                                     $labelText,
  1227.                                     IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT,
  1228.                                     $font
  1229.                                 );
  1230.                             } else {
  1231.                                 $this->write(
  1232.                                     $this->_left + 3 + $offset,
  1233.                                     $labelPosition,
  1234.                                     $labelText,
  1235.                                     IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT,
  1236.                                     $font
  1237.                                 );
  1238.                             }
  1239.                         }
  1240.                     } else {
  1241.                         if ($this->_transpose) {
  1242.                             if ($labelInside) {
  1243.                                 $this->write(
  1244.                                     $this->_right + 3 + $offset,
  1245.                                     $labelPosition,
  1246.                                     $labelText,
  1247.                                     IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT,
  1248.                                     $font
  1249.                                 );
  1250.                             } else {
  1251.                                 $this->write(
  1252.                                     $this->_right - 3 - $offset,                                                                   
  1253.                                     $labelPosition,
  1254.                                     $labelText,
  1255.                                     IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT,
  1256.                                     $font
  1257.                                 );
  1258.                             }
  1259.                         }
  1260.                         else {
  1261.                             if ($labelInside === true) {
  1262.                                 $this->write(
  1263.                                     $labelPosition,
  1264.                                     $this->_top - 3 - $offset,
  1265.                                     $labelText,
  1266.                                     IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_BOTTOM,
  1267.                                     $font
  1268.                                 );
  1269.                             } else {                                
  1270.                                 $this->write(
  1271.                                     $labelPosition,
  1272.                                     $this->_top + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1),
  1273.                                     $labelText,
  1274.                                     IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_BOTTOM,
  1275.                                     $font
  1276.                                 );
  1277.                             }
  1278.                         }
  1279.                     }
  1280.                 }
  1281.             }
  1282.  
  1283.             $tickColor = false;
  1284.             if (isset($this->_labelOptions[$level]['tick'])) {
  1285.                 if (isset($this->_labelOptions[$level]['tick']['start'])) {                
  1286.                     $tickStart = $this->_labelOptions[$level]['tick']['start'];
  1287.                 } else {
  1288.                     $tickStart = false;
  1289.                 }
  1290.  
  1291.                 if (isset($this->_labelOptions[$level]['tick']['end'])) {                
  1292.                     $tickEnd = $this->_labelOptions[$level]['tick']['end'];
  1293.                 } else {
  1294.                     $tickEnd = false;
  1295.                 }
  1296.                                     
  1297.                 if ((isset($this->_labelOptions[$level]['tick']['color'])) && ($this->_labelOptions[$level]['tick']['color'] !== false)) {
  1298.                     $tickColor = $this->_labelOptions[$level]['tick']['color'];
  1299.                 }
  1300.             }
  1301.             
  1302.             if ($tickStart === false) {
  1303.                 $tickStart = -2;
  1304.             }
  1305.             
  1306.             if ($tickEnd === false) {
  1307.                 $tickEnd = 2;
  1308.             }
  1309.  
  1310.             if ($tickColor !== false) {
  1311.                 $this->_canvas->setLineColor($tickColor);
  1312.             }
  1313.             else {
  1314.                 $this->_getLineStyle();
  1315.             }
  1316.             
  1317.             if ($this->_type == IMAGE_GRAPH_AXIS_Y) {
  1318.                 if ($tickStart === 'auto') {
  1319.                     $tickStart = -$offset;
  1320.                 }
  1321.                 if ($this->_transpose) {
  1322.                     $this->_canvas->line(
  1323.                         array(
  1324.                             'x0' => $labelPosition,
  1325.                             'y0' => $this->_top + $tickStart,
  1326.                             'x1' => $labelPosition,
  1327.                             'y1' => $this->_top + $tickEnd
  1328.                         )
  1329.                     );
  1330.                 }
  1331.                 else {
  1332.                     $this->_canvas->line(
  1333.                         array(
  1334.                             'x0' => $this->_right + $tickStart,
  1335.                             'y0' => $labelPosition,
  1336.                             'x1' => $this->_right + $tickEnd,
  1337.                             'y1' => $labelPosition
  1338.                         )
  1339.                     );
  1340.                 }
  1341.             } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
  1342.                 if ($tickStart === 'auto') {
  1343.                     $tickStart = $offset;
  1344.                 }
  1345.                 if ($this->_transpose) {
  1346.                     $this->_canvas->line(
  1347.                         array(
  1348.                             'x0' => $labelPosition,
  1349.                             'y0' => $this->_bottom - $tickStart,
  1350.                             'x1' => $labelPosition,
  1351.                             'y1' => $this->_bottom - $tickEnd
  1352.                         )
  1353.                     );
  1354.                 }
  1355.                 else {
  1356.                     $this->_canvas->line(
  1357.                         array(
  1358.                             'x0' => $this->_left - $tickStart,
  1359.                             'y0' => $labelPosition,
  1360.                             'x1' => $this->_left - $tickEnd,
  1361.                             'y1' => $labelPosition
  1362.                         )
  1363.                     );
  1364.                 }
  1365.             } else {
  1366.                 if ($tickStart === 'auto') {
  1367.                     $tickStart = $offset;
  1368.                 }
  1369.                 if ($this->_transpose) {
  1370.                     $this->_canvas->line(
  1371.                         array(
  1372.                             'x0' => $this->_right + $tickStart,
  1373.                             'y0' => $labelPosition,
  1374.                             'x1' => $this->_right + $tickEnd,
  1375.                             'y1' => $labelPosition
  1376.                         )
  1377.                     );
  1378.                 }
  1379.                 else {
  1380.                     $this->_canvas->line(
  1381.                         array(
  1382.                             'x0' => $labelPosition,
  1383.                             'y0' => $this->_top - $tickStart,
  1384.                             'x1' => $labelPosition,
  1385.                             'y1' => $this->_top - $tickEnd
  1386.                         )
  1387.                     );
  1388.                 }
  1389.             }
  1390.         }
  1391.     }
  1392.  
  1393.     /**
  1394.      * Draws axis lines.
  1395.      *
  1396.      * @access private
  1397.      */
  1398.     function _drawAxisLines()
  1399.     {
  1400.         if ($this->_type == IMAGE_GRAPH_AXIS_X) {
  1401.             $this->_getLineStyle(); 
  1402.             $this->_getFillStyle(); 
  1403.             
  1404.             if ($this->_transpose) {
  1405.                 $data = array(
  1406.                         'x0' => $this->_right,
  1407.                         'y0' => $this->_top,
  1408.                         'x1' => $this->_right,
  1409.                         'y1' => $this->_bottom
  1410.                     );
  1411.             } else {
  1412.                 $data = array(
  1413.                         'x0' => $this->_left,
  1414.                         'y0' => $this->_top,
  1415.                         'x1' => $this->_right,
  1416.                         'y1' => $this->_top
  1417.                     );
  1418.             }
  1419.                 
  1420.             if ($this->_showArrow) {
  1421.                 if ($this->_getMaximum() <= 0) {
  1422.                     $data['end0'] = 'arrow2';
  1423.                     $data['size0'] = 7;
  1424.                 }
  1425.                 else {
  1426.                     $data['end1'] = 'arrow2';
  1427.                     $data['size1'] = 7;
  1428.                 }
  1429.             } 
  1430.             
  1431.             $this->_canvas->line($data);
  1432.  
  1433.             if ($this->_title) {
  1434.                 if (!$this->_transpose) {
  1435.                     $y = $this->_bottom;
  1436.                     $x = $this->_left + $this->width() / 2;
  1437.                     $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont());
  1438.                 }
  1439.                 else {
  1440.                     $y = $this->_top + $this->height() / 2;
  1441.                     $x = $this->_left;
  1442.                     $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont());
  1443.                 }
  1444.             }
  1445.         } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
  1446.             $this->_getLineStyle();
  1447.             $this->_getFillStyle(); 
  1448.             
  1449.             if ($this->_transpose) {
  1450.                 $data = array(
  1451.                         'x0' => $this->_left,
  1452.                         'y0' => $this->_bottom,
  1453.                         'x1' => $this->_right,
  1454.                         'y1' => $this->_bottom
  1455.                     );
  1456.             } else {
  1457.                 $data = array(
  1458.                         'x0' => $this->_left,
  1459.                         'y0' => $this->_bottom,
  1460.                         'x1' => $this->_left,
  1461.                         'y1' => $this->_top
  1462.                     );
  1463.             }
  1464.             if ($this->_showArrow) {
  1465.                 if ($this->_getMaximum() <= 0) {
  1466.                     $data['end0'] = 'arrow2';
  1467.                     $data['size0'] = 7;
  1468.                 }
  1469.                 else {
  1470.                     $data['end1'] = 'arrow2';
  1471.                     $data['size1'] = 7;
  1472.                 }
  1473.             } 
  1474.             $this->_canvas->line($data);
  1475.  
  1476.             if ($this->_title) {
  1477.                 if ($this->_transpose) {
  1478.                     $y = $this->_top;
  1479.                     $x = $this->_left + $this->width() / 2;
  1480.                     $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_TOP, $this->_getTitleFont());
  1481.                 }
  1482.                 else {
  1483.                     $y = $this->_top + $this->height() / 2;
  1484.                     $x = $this->_right;
  1485.                     $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont());
  1486.                 }
  1487.             }
  1488.         } else {
  1489.             $this->_getLineStyle();
  1490.             $this->_getFillStyle(); 
  1491.                         
  1492.             if ($this->_transpose) {
  1493.                 $data = array(
  1494.                         'x0' => $this->_left,
  1495.                         'y0' => $this->_top,
  1496.                         'x1' => $this->_right,
  1497.                         'y1' => $this->_top
  1498.                     );
  1499.             } else {
  1500.                 $data = array(
  1501.                         'x0' => $this->_right,
  1502.                         'y0' => $this->_bottom,
  1503.                         'x1' => $this->_right,
  1504.                         'y1' => $this->_top
  1505.                     );
  1506.             }
  1507.             if ($this->_showArrow) {
  1508.                 if ($this->_getMaximum() <= 0) {
  1509.                     $data['end0'] = 'arrow2';
  1510.                     $data['size0'] = 7;
  1511.                 }
  1512.                 else {
  1513.                     $data['end1'] = 'arrow2';
  1514.                     $data['size1'] = 7;
  1515.                 }
  1516.             } 
  1517.             $this->_canvas->line($data);            
  1518.  
  1519.             if ($this->_title) {
  1520.                 if ($this->_transpose) {
  1521.                     $y = $this->_bottom;
  1522.                     $x = $this->_left + $this->width() / 2;
  1523.                     $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont());
  1524.                 }
  1525.                 else {
  1526.                     $y = $this->_top + $this->height() / 2;
  1527.                     $x = $this->_left;
  1528.                     $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont());
  1529.                 }
  1530.             }
  1531.         }
  1532.     }
  1533.  
  1534.     /**
  1535.      * Causes the object to update all sub elements coordinates
  1536.      *
  1537.      * (Image_Graph_Common, does not itself have coordinates, this is basically
  1538.      * an abstract method)
  1539.      *
  1540.      * @access private
  1541.      */
  1542.     function _updateCoords()
  1543.     {
  1544.         parent::_updateCoords();
  1545.         $this->_calcDelta();
  1546.     }
  1547.     
  1548.     /**
  1549.      * Output the axis
  1550.      *
  1551.      * @return bool Was the output 'good' (true) or 'bad' (false).
  1552.      * @access private
  1553.      */
  1554.     function _done()
  1555.     {
  1556.         $this->_canvas->startGroup(get_class($this));        
  1557.  
  1558.         if (parent::_done() === false) {
  1559.             return false;
  1560.         }
  1561.         
  1562.         $this->_drawAxisLines();
  1563.  
  1564.         $this->_canvas->startGroup(get_class($this) . '_ticks');        
  1565.         ksort($this->_labelOptions);
  1566.         foreach ($this->_labelOptions as $level => $labelOption) {
  1567.             $value = false;
  1568.             while (($value = $this->_getNextLabel($value, $level)) !== false) {
  1569.                 if ((((abs($value) > 0.0001) || ($this->_showLabelZero)) &&
  1570.                     (($value > $this->_getMinimum()) || ($this->_showLabelMinimum)) &&
  1571.                     (($value < $this->_getMaximum()) || ($this->_showLabelMaximum))) &&
  1572.                     ($value >= $this->_getMinimum()) && ($value <= $this->_getMaximum())
  1573.                 ) {
  1574.                     $this->_drawTick($value, $level);
  1575.                 }
  1576.             }
  1577.         }
  1578.         $this->_canvas->endGroup();        
  1579.  
  1580.         $tickStart = -3;
  1581.         $tickEnd = 2;
  1582.  
  1583.         foreach ($this->_marks as $mark) {
  1584.             if (is_array($mark)) {
  1585.                 if ($this->_type == IMAGE_GRAPH_AXIS_X) {
  1586.                     if ($this->_transpose) {
  1587.                         $x0 = $this->_right + $tickStart;
  1588.                         $y0 = $this->_point($mark[1]);
  1589.                         $x1 = $this->_right + $tickEnd;
  1590.                         $y1 = $this->_point($mark[0]);
  1591.                     }
  1592.                     else {
  1593.                         $x0 = $this->_point($mark[0]);
  1594.                         $y0 = $this->_top + $tickStart;
  1595.                         $x1 = $this->_point($mark[1]);
  1596.                         $y1 = $this->_top + $tickEnd;
  1597.                     }
  1598.                 } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) {
  1599.                     if ($this->_transpose) {
  1600.                         $x0 = $this->_point($mark[0]);
  1601.                         $y0 = $this->_top + $tickStart;
  1602.                         $x1 = $this->_point($mark[1]);
  1603.                         $y1 = $this->_top + $tickEnd;
  1604.                     }
  1605.                     else {
  1606.                         $x0 = $this->_right + $tickStart;
  1607.                         $y0 = $this->_point($mark[1]);
  1608.                         $x1 = $this->_right + $tickEnd;
  1609.                         $y1 = $this->_point($mark[0]);
  1610.                     }
  1611.                 } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
  1612.                     if ($this->_transpose) {
  1613.                         $x0 = $this->_point($mark[0]);
  1614.                         $y0 = $this->_bottom + $tickStart;
  1615.                         $x1 = $this->_point($mark[1]);
  1616.                         $y1 = $this->_bottom + $tickEnd;
  1617.                     }
  1618.                     else {
  1619.                         $x0 = $this->_left + $tickStart;
  1620.                         $y0 = $this->_point($mark[1]);
  1621.                         $x1 = $this->_left + $tickEnd;
  1622.                         $y1 = $this->_point($mark[0]);
  1623.                     }                        
  1624.                 }
  1625.                 $this->_getFillStyle();
  1626.                 $this->_getLineStyle();
  1627.                 $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1));
  1628.             } else {
  1629.                 if ($this->_type == IMAGE_GRAPH_AXIS_X) {
  1630.                     if ($this->_transpose) {
  1631.                         $x0 = $this->_right + 5;
  1632.                         $y0 = $this->_point($mark);
  1633.                         $x1 = $this->_right + 15;
  1634.                         $y1 = $y0;
  1635.                     }
  1636.                     else {
  1637.                         $x0 = $this->_point($mark);
  1638.                         $y0 = $this->_top - 5;
  1639.                         $x1 = $x0;
  1640.                         $y1 = $this->_top - 15;
  1641.                     }
  1642.                 } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) {
  1643.                     if ($this->_transpose) {
  1644.                         $x0 = $this->_point($mark);
  1645.                         $y0 = $this->_top - 5;
  1646.                         $x1 = $x0;
  1647.                         $y1 = $this->_top - 15;
  1648.                     }
  1649.                     else {
  1650.                         $x0 = $this->_right + 5;
  1651.                         $y0 = $this->_point($mark);
  1652.                         $x1 = $this->_right + 15;
  1653.                         $y1 = $y0;
  1654.                     }
  1655.                 } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
  1656.                     if ($this->_transpose) {
  1657.                         $x0 = $this->_point($mark);
  1658.                         $y0 = $this->_bottom + 5;
  1659.                         $x1 = $x0;
  1660.                         $y1 = $this->_bottom + 15;
  1661.                     }
  1662.                     else {
  1663.                         $x0 = $this->_left - 5;
  1664.                         $y0 = $this->_point($mark);
  1665.                         $x1 = $this->_left - 15;
  1666.                         $y1 = $y0;
  1667.                     }                        
  1668.                 }
  1669.                 $this->_getFillStyle();
  1670.                 $this->_getLineStyle();
  1671.                 $this->_canvas->line(
  1672.                     array(
  1673.                         'x0' => $x0,
  1674.                         'y0' => $y0, 
  1675.                         'x1' => $x1, 
  1676.                         'y1' => $y1, 
  1677.                         'end0' => 'arrow2',
  1678.                         'size0' => 5                        
  1679.                     )
  1680.                 );
  1681.             }
  1682.         }
  1683.         $this->_canvas->endGroup();        
  1684.  
  1685.         return true;
  1686.     }
  1687.  
  1688. }
  1689.  
  1690. ?>