<?php

require_once dirname(__FILE__) . '/../XML/SVG.php';

/**
 * SVG implementation of the Horde_Graph Horde graphing suite.
 *
 * Implements an interface for graph generation producing SVG graphs,
 * using the XML_SVG utility library.
 *
 * $Horde: horde/lib/Graph/svg.php,v 1.3 2003/07/30 14:13:15 chuck Exp $
 *
 * Copyright 2002-2003 Chuck Hagenbuch <chuck@horde.org>
 *
 * See the enclosed file COPYING for license information (LGPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 *
 * @author  Chuck Hagenbuch <chuck@horde.org>
 * @version $Revision: 1.3 $
 * @since   Horde 3.0
 * @package Horde_Graph
 */
class Horde_Graph_svg extends Horde_Graph {

    var $_graphs = array('horizontalBar',
                         'multiHorizontalBar');

    var $_svg;

    function _horizontalBarGraph($data)
    {
        $ChartFontHeight = 14;
        $colorBody = '#e9e9e9';
        $colorBorder = 'black';
        $colorText = 'black';

        $longest = 0;
        $labels = array_keys($data);
        while ($label = array_shift($labels)) {
            $longest = max($longest, String::length($label));
        }
        $BoxX = 10 + $longest * 10;

        // determine graphic size
        $this->_width = $BoxX + (max($data) * $this->_scale) + 50;
        $this->_height = 20 + (($ChartFontHeight + 2) * count($data));

        $this->_svg = &new XML_SVG_Document(array('width' => $this->_width,
                                                  'height' => $this->_height));

        $this->_svg->addChild(new XML_SVG_Rect(array('x' => 0,
                                                     'y' => 0,
                                                     'width' => $this->_width,
                                                     'height' => $this->_height,
                                                     'style' => "fill:$colorBody;")));

        $index = 0;
        $sText = new XML_SVG_Text();
        $sText->setParam('style', "fill:$colorText; font-size:$ChartFontHeight");
        foreach ($data as $label => $Value) {
            $CurrentColor = $this->getColor($index);
            $BoxY = ++$index * ($ChartFontHeight + 3) - 5;
            $labelY = $BoxY + $ChartFontHeight - 2;

            // draw label
            $sText->setParam('x', 10);
            $sText->setParam('y', $labelY);
            $sText->setParam('text', $label);
            $this->_svg->addChild($sText, true);

            // draw color box
            $this->_svg->addChild(new XML_SVG_Rect(array('x' => $BoxX,
                                                         'y' => $BoxY,
                                                         'width' => $Value * $this->_scale,
                                                         'height' => $ChartFontHeight,
                                                         'style' => "fill:$CurrentColor; stroke:$colorBorder; stroke-width:1")));

            // draw number
            $sText->setParam('y', $labelY);
            $sText->setParam('x', ($Value * $this->_scale) + $BoxX + 5);
            $sText->setParam('text', '(' . $Value . ')');
            $this->_svg->addChild($sText, true);
        }
    }

    function _multiHorizontalBarGraph($data)
    {
        $ChartFontHeight = 14;
        $colorBody = '#e9e9e9';
        $colorBorder = 'black';
        $colorText = 'black';
        $groupSpacing = .7;

        $longest = '';
        $labels = array_keys($data);
        while ($label = array_shift($labels)) {
            $longest = max($longest, String::length($label));
        }
        $BoxX = 10 + $longest * 10;

        // Find biggest data element.
        $max = 0;
        foreach ($data as $vals) {
            $max = max($max, $vals[0], $vals[1]);
        }

        // determine graphic size
        $this->_width = $BoxX + ($max * $this->_scale) + 50;
        reset($data);
        list(, $vals) = each($data);
        $this->_height = 20 + (($ChartFontHeight + 2) * ((count($data) * count($vals)) + (count($data) * $groupSpacing)));

        $this->_svg = &new XML_SVG_Document(array('width' => $this->_width,
                                                  'height' => $this->_height));

        $this->_svg->addChild(new XML_SVG_Rect(array('x' => 0,
                                                     'y' => 0,
                                                     'width' => $this->_width,
                                                     'height' => $this->_height,
                                                     'style' => "fill:$colorBody;")));

        $index = 0;
        $sText = new XML_SVG_Text();
        $sText->setParam('style', "fill:$colorText; font-size:$ChartFontHeight");
        foreach ($data as $label => $values) {
            $j = 0;
            $heights = array();
            foreach ($values as $value) {
                $CurrentColor = $this->getColor($j);
                $BoxY = ($index + $j + 1) * ($ChartFontHeight + 3) - 5;
                $labelY = $BoxY + $ChartFontHeight - 2;
                $heights[] = $labelY;

                // draw color box
                $this->_svg->addChild(new XML_SVG_Rect(array('x' => $BoxX,
                                                             'y' => $BoxY,
                                                             'width' => $value * $this->_scale,
                                                             'height' => $ChartFontHeight,
                                                             'style' => "fill:$CurrentColor; stroke:$colorBorder; stroke-width:1")));

                // draw number
                $sText->setParam('y', $BoxY + $ChartFontHeight - 2);
                $sText->setParam('x', $value * $this->_scale + $BoxX + 5);
                $sText->setParam('text', '(' . $value . ')');
                $this->_svg->addChild($sText, true);
                $j++;
            }

            // draw label
            $sText->setParam('x', 10);
            $sText->setParam('y', array_sum($heights) / count($values));
            $sText->setParam('text', $label);
            $this->_svg->addChild($sText, true);

            $index += count($values) + $groupSpacing;
        }
    }

    function display()
    {
        $this->_svg->printElement();
    }

    function _createSymbol($s, $id)
    {
        $s->setParam('id', $id);
        $defs = &new XML_SVG_Defs();
        $defs->addChild($s);
        $this->_svg->addChild($defs);
    }

    function _createDropShadow()
    {
        $defs = &new XML_SVG_Defs();
        $filter = &new XML_SVG_Filter(array('id' => 'dropShadow'));
        $filter->addPrimitive('GaussianBlur', array('in' => 'SourceAlpha',
                                                    'stdDeviation' => 2,
                                                    'result' => 'blur'));
        $filter->addPrimitive('Offset', array('in' => 'blur',
                                              'dx' => 4,
                                              'dy' => 4,
                                              'result' => 'offsetBlur'));
        $merge = new XML_SVG_FilterPrimitive('Merge');
        $merge->addMergeNode('offsetBlur');
        $merge->addMergeNode('SourceGraphic');

        $filter->addChild($merge);
        $defs->addChild($filter);
        $this->_svg->addChild($defs);
    }

}
