includes/graphs.php
author Dan
Tue, 14 Apr 2009 21:03:25 -0400
changeset 910 e5de998b934b
parent 801 eb8b23f11744
permissions -rw-r--r--
Meh, finished my half-written-out thought in a FIXME in Special:Log code.

<?php

/*
 * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
 * Version 1.1.6 (Caoineag beta 1)
 * Copyright (C) 2006-2008 Dan Fuhry
 *
 * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for details.
 */

// BarGraph for PHP
// Source: http://www.phpclasses.org/browse/package/1567.html
// License: PHP license, see licenses/phplic.html included with this package

class GraphMaker {
  /**
   * GraphMaker::bar_width
   * Width of bars
   */
  var $bar_width = 32;
  /**
   * GraphMaker::bar_height
   * Height of bars
   */
  var $bar_height = 8;
  /**
   * GraphMaker::bar_data
   * Data of all bars
   */
  var $bar_data = array('a' => 7, 'b' => 3, 'c' => 6, 'd' => 0, 'e' => 2);
  /**
   * GraphMaker::bar_padding
   * Padding of bars
   */
  var $bar_padding = 5;
  /**
   * GraphMaker::bar_bordercolor
   * Border color of bars
   */
  var $bar_bordercolor = array(39, 78, 120);
  /**
   * GraphMaker::bar_bgcolor
   * Background color of bars
   */
  var $bar_bgcolor = array(69, 129, 194);
  //---------------------------------------------
  /**
   * GraphMaker::graph_areaheight
   * Height of graphic area
   */
  var $graph_areaheight = 100;
  /**
   * GraphMaker::graph_padding
   * Paddings of graph
   */
  var $graph_padding = array('left' => 50, 'top' => 20, 'right'  => 20, 'bottom' => 20);
  /**
   * GraphMaker::graph_title
   * Title text of graph
   */
  var $graph_title = "";
  /**
   * GraphMaker::graph_bgcolor
   * Background color of graph
   */
  var $graph_bgcolor = array(255, 255, 255);
  /**
   * GraphMaker::graph_bgtransparent
   * Boolean for background transparency
   */
  var $graph_bgtransparent = 0;
  /**
   * GraphMaker::graph_transparencylevel
   * Transparency level (0=opaque, 127=transparent)
   */
  var $graph_transparencylevel = 0;
  /**
   * GraphMaker::graph_borderwidth
   * Width of graph border
   */
  var $graph_borderwidth = 1;
  /**
   * GraphMaker::graph_bordercolor
   * Border color of graph
   */
  var $graph_bordercolor = array(218, 218, 239);
  /**
   * GraphMaker::graph_titlecolor
   * Color of title text of graph
   */
  var $graph_titlecolor = array(99, 88, 78);
  //---------------------------------------------
  /**
   * GraphMaker::axis_step
   * Scale step of axis
   */
  var $axis_step = 2;
  /**
   * GraphMaker::axis_bordercolor
   * Border color of axis
   */
  var $axis_bordercolor = array(99, 88, 78);
  /**
   * GraphMaker::axis_bgcolor
   * Background color of axis
   */
  var $axis_bgcolor = array(152, 137, 124);

  /****************************************************************
                              GRAPH
  ****************************************************************/

  /**
   * GraphMaker::SetGraphAreaHeight()
   * Sets graph height (not counting top and bottom margins)
   **/
  function SetGraphAreaHeight($height) {
    if ($height > 0) $this->graph_areaheight = $height;
  }

  /**
   * GraphMaker::SetGraphPadding()
   * Sets graph padding (margins)
   **/
  function SetGraphPadding($left, $top, $right, $bottom) {
    $this->graph_padding = array('left'   => (int) $left,
                                 'top'    => (int) $top,
                                 'right'  => (int) $right,
                                 'bottom' => (int) $bottom);
  }

  /**
   * GraphMaker::SetGraphTitle()
   * Set title text
   **/
  function SetGraphTitle($title) {
    $this->graph_title = $title;
  }

  /**
   * GraphMaker::SetGraphBorderColor()
   * Sets border color for graph
   **/
  function SetGraphBorderColor($red, $green, $blue) {
    $this->graph_bordercolor = array($red, $green, $blue);
  }

  /**
   * GraphMaker::SetGraphBorderWidth()
   * Set width of border. 0 disables border
   **/
  function SetGraphBorderWidth($width = 0) {
    $this->graph_borderwidth = $width;
  }

  /**
   * GraphMaker::SetGraphBackgroundColor()
   * Sets background color for graph
   **/
  function SetGraphBackgroundColor($red, $green, $blue) {
    $this->graph_bgcolor = array($red, $green, $blue);
  }

  /**
   * GraphMaker::SetGraphBackgroundTransparent()
   * Sets background color for graph (and set it transparent)
   **/
  function SetGraphBackgroundTransparent($red, $green, $blue, $addtransparency = 1) {
    $this->graph_bgcolor = array($red, $green, $blue);
    $this->graph_bgtransparent = ($addtransparency ? 1 : 0);
  }

  /**
   * GraphMaker::SetGraphTitleColor()
   * Sets title color for graph
   **/
  function SetGraphTitleColor($red, $green, $blue) {
    $this->graph_titlecolor = array($red, $green, $blue);
  }

  /**
   * GraphMaker::SetGraphTransparency()
   * Sets transparency for graph
   **/
  function SetGraphTransparency($percent) {
    if ($percent < 0) $percent = 0;
    elseif ($percent > 100) $percent = 127;
    else $percent = $percent * 1.27;
    $this->graph_transparencylevel = $percent;
  }

  /****************************************************************
                               BAR
  ****************************************************************/

  /**
   * GraphMaker::SetBarBorderColor()
   * Sets border color for bars
   **/
  function SetBarBorderColor($red, $green, $blue) {
    $this->bar_bordercolor = array($red, $green, $blue);
  }

  /**
   * GraphMaker::SetBarBackgroundColor()
   * Sets background color for bars
   **/
  function SetBarBackgroundColor($red, $green, $blue) {
    $this->bar_bgcolor = array($red, $green, $blue);
  }

  /**
   * GraphMaker::SetBarData()
   * Sets data of graph (parameter should be an array with key
   * being the name of the bar and the value the value of the bar.
   **/
  function SetBarData($data) {
    if (is_array($data)) $this->bar_data = $data;
  }

  /**
   * GraphMaker::SetBarDimensions()
   * Sets with and height of each bar
   **/
  function SetBarDimensions($width, $height) {
    if ($width > 0) $this->bar_width = $width;
    if ($height > 0) $this->bar_height = $height;
  }

  /**
   * GraphMaker::SetBarPadding()
   * Sets padding (border) around each bar
   **/
  function SetBarPadding($padding) {
    if ($padding > 0) $this->bar_padding = $padding;
  }

  /****************************************************************
                               AXIS
  ****************************************************************/

  /**
   * GraphMaker::SetAxisBorderColor()
   * Sets border color for axis
   **/
  function SetAxisBorderColor($red, $green, $blue) {
    $this->axis_bordercolor = array($red, $green, $blue);
  }

  /**
   * GraphMaker::SetAxisBackgroundColor()
   * Sets background color for axis
   **/
  function SetAxisBackgroundColor($red, $green, $blue) {
    $this->axis_bgcolor = array($red, $green, $blue);
  }

  /**
   * GraphMaker::SetAxisStep()
   * Sets axis scale step
   **/
  function SetAxisStep($step) {
    if ($step > 0) $this->axis_step = $step;
  }

  /**
   * GraphMaker::GetFinalGraphDimensions()
   * From the values already setted, it calculates image
   * width and height
   **/
  function GetFinalGraphDimensions() {
    $w = $this->graph_padding['left'] +
         (count($this->bar_data) * ($this->bar_width + ($this->bar_padding * 2))) +
         $this->graph_padding['right'];
    $h = $this->graph_padding['top'] +
         $this->graph_areaheight +
         $this->graph_padding['bottom'];
    return array($w, $h);
  }

  /**
   * GraphMaker::LoadGraph()
   * Loads definitions from a file
   **/
  function LoadGraph($path) {
    if (($fp = @fopen($path, "r")) !== false) {
      $content = "";
      while (!feof($fp)) {              // I do not use filesize() here
        $content .= fread($fp, 4096);   // because of remote files. If
      }                                 // there is no problem with them
      fclose($fp);                      // please let me know
      $this->__LoadGraphDefinitions($content);
      return true;
    } else return false;
  }

  /**
   * GraphMaker::DrawGraph()
   * Draw all the graph: bg, axis, bars, text.. and output it
   * Optional file parameter turns output to file, and bool on success
   **/
  function DrawGraph($file = "") {
    list($w, $h) = $this->GetFinalGraphDimensions();
    $this->graph_width = $w;
    $this->graph_height = $h;

    $this->im = imagecreatetruecolor($w, $h);
    if ($this->graph_transparencylevel) {
      imagealphablending($this->im, true);
    }

    $this->__PaintBackground();
    $this->__DrawAxis();

    $p = 0;
    foreach ($this->bar_data as $name => $value) {
      $p++;
      $this->__DrawBarText($p, $name);
      $this->__DrawBar($p, $value);
    }

    if (strlen($this->graph_title)) {
      $this->__AllocateColor("im_graph_titlecolor",
                             $this->graph_titlecolor,
                             $this->graph_transparencylevel);
      $this->__DrawText($this->graph_title,
                        floor($this->graph_width / 2),
                        $this->graph_borderwidth + 2,
                        $this->im_graph_titlecolor,
                        2,
                        1);
    }

    if (strlen($file)) {
      $ret = imagepng($this->im, $file);
    } else {
      header('Content-Type: image/png');
      imagepng($this->im);
      $ret = true;
    }
    imagedestroy($this->im);
    return $ret;
  }

  /**
   * GraphMaker::PaintBackground()
   * Draw all the graph: bg, axis, bars, text.. and output it
   * Optional file parameter turns output to file, and bool on success
   **/
  function __PaintBackground() {
    $this->__AllocateColor("im_graph_bgcolor",
                           $this->graph_bgcolor,
                           0);
    imagefilledrectangle($this->im,
                         0,
                         0,
                         $this->graph_width,
                         $this->graph_height,
                         $this->im_graph_bgcolor);
    if ($this->graph_bgtransparent) {
      imagecolortransparent($this->im, $this->im_graph_bgcolor);
    }
    if ($this->graph_borderwidth) {
      $this->__AllocateColor("im_graph_bordercolor",
                             $this->graph_bordercolor,
                             $this->graph_transparencylevel);
      for ($i = 0; $i < $this->graph_borderwidth; $i++) {
        imagerectangle($this->im,
                       $i,
                       $i,
                       $this->graph_width - 1 - $i,
                       $this->graph_height - 1 - $i,
                       $this->im_graph_bordercolor);
      }
    }
  }

  /**
   * GraphMaker::__DrawAxis()
   * Draws all the axis stuff (and scale steps)
   **/
  function __DrawAxis() {
    $this->__AllocateColor("im_axis_bordercolor",
                           $this->axis_bordercolor,
                           $this->graph_transparencylevel);
    $this->__AllocateColor("im_axis_bgcolor",
                           $this->axis_bgcolor,
                           $this->graph_transparencylevel);
    $this->__DrawPolygon($this->graph_padding['left'], $this->graph_height - $this->graph_padding['bottom'],
                         $this->graph_padding['left'], $this->graph_padding['top'],
                         $this->graph_padding['left'] + $this->bar_height - 1, $this->graph_padding['top'] - $this->bar_height + 1,
                         $this->graph_padding['left'] + $this->bar_height - 1, $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height + 1,
                         $this->im_axis_bgcolor, true);
    $this->__DrawPolygon($this->graph_padding['left'], $this->graph_height - $this->graph_padding['bottom'],
                         $this->graph_padding['left'], $this->graph_padding['top'],
                         $this->graph_padding['left'] + $this->bar_height - 1, $this->graph_padding['top'] - $this->bar_height + 1,
                         $this->graph_padding['left'] + $this->bar_height - 1, $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height + 1,
                         $this->im_axis_bordercolor);

    $this->__DrawPolygon($this->graph_padding['left'], $this->graph_height - $this->graph_padding['bottom'],
                         $this->graph_padding['left'] + $this->bar_height - 1, $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height + 1,
                         $this->graph_width - $this->graph_padding['right'] + $this->bar_height - 1, $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height + 1,
                         $this->graph_width - $this->graph_padding['right'], $this->graph_height - $this->graph_padding['bottom'],
                         $this->im_axis_bgcolor, true);
    $this->__DrawPolygon($this->graph_padding['left'], $this->graph_height - $this->graph_padding['bottom'],
                         $this->graph_padding['left'] + $this->bar_height - 1, $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height + 1,
                         $this->graph_width - $this->graph_padding['right'] + $this->bar_height - 1, $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height + 1,
                         $this->graph_width - $this->graph_padding['right'], $this->graph_height - $this->graph_padding['bottom'],
                         $this->im_axis_bordercolor);

    // draw lines that separate bars
    $total_bars = count($this->bar_data);
    for ($i = 1; $i < $total_bars; $i++) {
      $offset = $this->graph_padding['left'] +
                (($this->bar_width + ($this->bar_padding * 2)) * $i);
      imageline($this->im,
                $offset,
                $this->graph_height - $this->graph_padding['bottom'],
                $offset + $this->bar_height - 1,
                $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height + 1,
                $this->im_axis_bordercolor);
    }

    // draw scale steps
    $max_value = $this->__GetMaxGraphValue();
    if (($max_value % 10) > 0) {
      $max_value = $max_value + (10 - ($max_value % 10));
    }
    $this->axis_max = $max_value;
    $y = 0;
    $style = array($this->im_axis_bordercolor, $this->im_graph_bgcolor);
    imagesetstyle($this->im, $style);
    while ($y <= $max_value) {
      if ($max_value == 0) { $max_value=1; } // corrected by Marcelo Trenkenchu
      $offset = floor($this->graph_height - $this->graph_padding['bottom'] -
                ($y * $this->graph_areaheight / $max_value));
      imageline($this->im,
                $this->graph_padding['left'],
                $offset,
                $this->graph_padding['left'] + $this->bar_height - 1,
                $offset - $this->bar_height + 1,
                $this->im_axis_bordercolor);
      $this->__DrawText($y,
                        $this->graph_padding['left'],
                        $offset,
                        $this->im_axis_bordercolor,
                        1,
                        2,
                        1);
      // gridline
      if ($y > 0) {
        imageline($this->im,
                  $this->graph_padding['left'] + $this->bar_height,
                  $offset - $this->bar_height + 1,
                  $this->graph_width - $this->graph_padding['right'] + $this->bar_height - 1,
                  $offset - $this->bar_height + 1,
                  IMG_COLOR_STYLED);
      }
      $y += $this->axis_step;
    }

    imageline($this->im,
              $this->graph_width - $this->graph_padding['right'] + $this->bar_height - 1,
              $this->graph_padding['top'] - $this->bar_height + 1,
              $this->graph_width - $this->graph_padding['right'] + $this->bar_height - 1,
              $this->graph_height - $this->graph_padding['bottom'] - $this->bar_height,
              IMG_COLOR_STYLED);
  }

  /**
   * GraphMaker::__DrawText()
   * Draws text on image with color, size and alignment options
   **/
  function __DrawText($text, $x, $y, $color, $size = 1, $align = 0, $valign = 0) {
    /*
     * Align: 0=left | 1=center | 2=right
     */
    if ($align == 1) $x -= floor(strlen($text) * imagefontwidth($size) / 2);
    elseif ($align == 2) $x -= (strlen($text) * imagefontwidth($size));
    if ($valign == 1) $y -= floor(imagefontheight($size) / 2);
    elseif ($valign == 2) $y -= imagefontheight($size);
    imagestring($this->im,
                $size,
                $x,
                $y,
                $text,
                $color);
  }

  /**
   * GraphMaker::__GetMaxGraphValue()
   * Returns max bar value
   **/
  function __GetMaxGraphValue() {
    $max_value = 0;
    foreach ($this->bar_data as $name => $value) {
      if ($value > $max_value) $max_value = $value;
    }
    return $max_value;
  }

  /**
   * GraphMaker::__DrawBarText()
   * Determines top and left to draw text to a choosen bar
   **/
  function __DrawBarText($bar, $text) {
    $this->__DrawText($text,
                      $this->graph_padding['left'] + (($this->bar_width + ($this->bar_padding * 2)) * ($bar - 0.5)),
                      $this->graph_height - $this->graph_padding['bottom'] + 1,
                      $this->axis_bordercolor,
                      1,
                      1);
  }

  /**
   * GraphMaker::__DrawBar()
   * Draws a choosen bar with it's value
   **/
  function __DrawBar($bar, $value) {
    $x = $this->graph_padding['left'] +
         (($this->bar_width + ($this->bar_padding * 2)) * ($bar - 1)) +
         $this->bar_padding;
    if ($this->axis_max == 0) { $this->axis_max = 1; } // corrected by Marcelo Trenkenchu
    $y = $value * $this->graph_areaheight / $this->axis_max;
    $this->____DrawBar($x,
                       $this->graph_height - $this->graph_padding['bottom'] - $y,
                       $x + $this->bar_width,
                       $this->graph_height - $this->graph_padding['bottom']);
  }

  /**
   * GraphMaker::____DrawBar()
   * Draws the actual rectangles that form a bar
   **/
  function ____DrawBar($x1, $y1, $x2, $y2) {
    $this->__AllocateColor("im_bar_bordercolor",
                           $this->bar_bordercolor,
                           $this->graph_transparencylevel);
    $this->__AllocateColor("im_bar_bgcolor",
                           $this->bar_bgcolor,
                           $this->graph_transparencylevel);
    $this->__DrawPolygon($x1,                         $y1,
                         $x2,                         $y1,
                         $x2,                         $y2,
                         $x1,                         $y2,
                         $this->im_bar_bgcolor,       true);
    $this->__DrawPolygon($x1,                         $y1,
                         $x2,                         $y1,
                         $x2,                         $y2,
                         $x1,                         $y2,
                         $this->im_bar_bordercolor);
    $this->__DrawPolygon($x1,                         $y1,
                         $x2,                         $y1,
                         $x2 + $this->bar_height - 1, $y1 - $this->bar_height + 1,
                         $x1 + $this->bar_height - 1, $y1 - $this->bar_height + 1,
                         $this->im_bar_bgcolor,       true);
    $this->__DrawPolygon($x1,                         $y1,
                         $x2,                         $y1,
                         $x2 + $this->bar_height - 1, $y1 - $this->bar_height + 1,
                         $x1 + $this->bar_height - 1, $y1 - $this->bar_height + 1,
                         $this->im_bar_bordercolor);
    $this->__DrawPolygon($x2,                         $y2,
                         $x2,                         $y1,
                         $x2 + $this->bar_height - 1, $y1 - $this->bar_height + 1,
                         $x2 + $this->bar_height - 1, $y2 - $this->bar_height + 1,
                         $this->im_bar_bgcolor,       true);
    $this->__DrawPolygon($x2,                         $y2,
                         $x2,                         $y1,
                         $x2 + $this->bar_height - 1, $y1 - $this->bar_height + 1,
                         $x2 + $this->bar_height - 1, $y2 - $this->bar_height + 1,
                         $this->im_bar_bordercolor);
  }

  /**
   * GraphMaker::__DrawPolygon()
   * Draws a (filled) (ir)regular polygon
   **/
  function __DrawPolygon($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4, $color, $filled = false) {
    if ($filled) {
      imagefilledpolygon($this->im, array($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4), 4, $color);
    } else {
      imagepolygon($this->im, array($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4), 4, $color);
    }
  }

  /**
   * GraphMaker::__LoadGraphDefinitions()
   * Loads definitions to a graph from text lines (normaly
   * they come from a file). This function is called by
   * GraphMaker::LoadGraph()
   **/
  function __LoadGraphDefinitions($text) {
    $text = preg_split("/\r?\n/", $text);
    $data = array();
    $section = '';
    for ($i = 0; $i < count($text); $i++) {
      if (preg_match("/^\s*#/", $text[$i])) {
        //ignore.. it's just a comment
      } elseif (preg_match("/^\s*\}\s*/", $text[$i])) {
        $section = '';
      } elseif (preg_match("/^\s*(\w+)\s*\{\s*$/", $text[$i], $r)) {
        $section = $r[1];
      } else {
        $p = strpos($text[$i], "=");
        if ($p !== false) {
          $data[$section][trim(substr($text[$i], 0, $p))] = trim(substr($text[$i], $p + 1));
        }
      }
    }
    if (is_array($data['graph'])) {
      $this->__LoadGraphValues($data['graph']);
    }
    if (is_array($data['bar'])) {
      $this->__LoadBarValues($data['bar']);
    }
    if (is_array($data['axis'])) {
      $this->__LoadAxisValues($data['axis']);
    }
    if (is_array($data['data'])) {
      $this->bar_data = $data['data'];
    }
  }

  /**
   * GraphMaker::__LoadGraphValues()
   * Loads definitions to main graph settings
   **/
  function __LoadGraphValues($data) {
    foreach ($data as $name => $value) {
      $name = strtolower($name);
      switch ($name) {
        case 'background-color':
          $this->__SetColorToValue("graph_bgcolor", $value);
          break;
        case 'border-color':
          $this->__SetColorToValue("graph_bordercolor", $value);
          break;
        case 'title-color':
          $this->__SetColorToValue("graph_titlecolor", $value);
          break;
        case 'background-transparent':
          $this->graph_bgtransparent = ($value == 1 || $value == 'yes' ? 1 : 0);
          break;
        case 'transparency':
          $this->SetGraphTransparency(str_replace('%', '', $value));
          break;
        case 'title':
          $this->graph_title = $value;
          break;
        case 'border-width':
          $this->graph_borderwidth = (int) $value;
          break;
        case 'area-height':
          $this->graph_areaheight = (int) $value;
          break;
        default:
          if (substr($name, 0, 8) == 'padding-' && strlen($name) > 8) {
            $this->graph_padding[substr($name, 8)] = $value;
          }
      }
    }
  }

  /**
   * GraphMaker::__LoadBarValues()
   * Loads definitions to bar settings
   **/
  function __LoadBarValues($data) {
    foreach ($data as $name => $value) {
      $name = strtolower($name);
      switch ($name) {
        case 'background-color':
          $this->__SetColorToValue("bar_bgcolor", $value);
          break;
        case 'border-color':
          $this->__SetColorToValue("bar_bordercolor", $value);
          break;
        case 'padding':
          $this->bar_padding = $value;
          break;
        case 'width':
          $this->bar_width = (int) $value;
          break;
        case 'height':
          $this->bar_height = (int) $value;
          break;
      }
    }
  }

  /**
   * GraphMaker::__LoadAxisValues()
   * Loads definitions to axis settings
   **/
  function __LoadAxisValues($data) {
    foreach ($data as $name => $value) {
      switch (strtolower($name)) {
        case 'step':
          $this->SetAxisStep($value);
          break;
        case 'background-color':
          $this->__SetColorToValue("axis_bgcolor", $value);
          break;
        case 'border-color':
          $this->__SetColorToValue("axis_bordercolor", $value);
      }
    }
  }

  /**
   * GraphMaker::__SetColorToValue()
   * Sets a color (rgb or in html format) to a variable
   **/
  function __SetColorToValue($varname, $color) {
    if ($color[0] == "#") { // if it's hex (html format), change to rgb array
      if (strlen($color) == 4) {
        // if only 3 hex values (I assume it's a shade of grey: #ddd)
        $color .= substr($color, -3);
      }
      $color = array(hexdec($color[1].$color[2]),
                     hexdec($color[3].$color[4]),
                     hexdec($color[5].$color[6]));
    }
    $this->$varname = $color;
  }

  function __AllocateColor($varname, $color, $alpha) {
    $this->$varname = imagecolorallocatealpha($this->im,
                                              $color[0],
                                              $color[1],
                                              $color[2],
                                              $alpha);
  }
}

// Graph Generator for PHP
// Originally located at http://szewo.com/php/graph, but link was broken, so this file was retrieved from:
// http://web.archive.org/web/20030130065944/szewo.com/php/graph/graph.class.php3.txt
// License unknown, however sources on the web have shown this to be either GPL or public domain.

// At this point this class has been very nearly rewritten for Enano.

class GraphMaker_compat {
  var $_values;
  var $_ShowLabels;
  var $_ShowCounts;
  var $_ShowCountsMode;

  var $_BarWidth;
  var $_GraphWidth;
  var $_BarImg;
  var $_BarBorderWidth;
  var $_BarBorderColor;
  var $_BarBackgroundColor;
  var $_RowSortMode;
  var $_TDClassHead;
  var $_TDClassLabel;
  var $_TDClassCount;
  var $_GraphTitle;

  function __construct() {
    $this->_values = array();
    $this->_ShowLabels = true;
    $this->_BarWidth = 32;
    $this->_GraphWidth = 360;
    $this->_BarImg = scriptPath . "/images/graphbit.png";
    $this->_BarBorderWidth = 0;
    $this->_BarBorderColor = "red";
    $this->_ShowCountsMode = 2;
    $this->_RowSortMode = 1;
    $this->_TDClassHead = "graph-title";
    $this->_TDClassLabel = "graph-label";
    $this->_TDClassCount = "graph-count";
    $this->_GraphTitle="Graph title";
    $this->_BarBackgroundColor = "#456798";
  }

  function GraphMaker_compat() {
    $this->__construct();
  }

  function SetBarBorderWidth($width) {
    $this->_BarBorderWidth = $width;
  }
  function SetBorderColor($color) {
    $this->_BarBorderColor = $color;
  }
  
  function SetBarBackgroundColor($color)
  {
    $this->_BarBackgroundColor = $color;
  }

//  mode = 1 labels asc, 2 label desc
  function SetSortMode($mode) {
    switch ($mode) {
      case 1:
        asort($this->_values);
        break;
      case 2:
        arsort($this->_values);
        break;
      default:
        break;
      }

  }

  function AddValue($labelName, $theValue) {
    array_push($this->_values, array("label" => $labelName, "value" => $theValue));
  }

  function SetBarData($data)
  {
      foreach ( $data as $name => $value )
      {
          $this->AddValue($name, $value);
      }
  }
  function DrawGraph()
  {
      $this->BarGraphVert();
  }
  function SetBarWidth($width)
  {
    $this->_BarWidth = $width;
  }
  function SetBarImg($img)
  {
    $this->_BarImg = $img;
  }
  function SetShowLabels($lables)
  {
    $this->_ShowLabels = $labels;
  }
  function SetGraphWidth($width)
  {
    $this->_GraphWidth = $width;
  }
  function SetGraphTitle($title)
  {
    $this->_GraphTitle = $title;
  }
  //mode = percentage or counts
  function SetShowCountsMode($mode)
  {
    $this->_ShowCountsMode = $mode;
  }
  //mode = none(0) label(1) or count(2)
  function SetRowSortMode($sortmode)
  {
    $this->_RowSortMode = $sortmode;
  }

  function SetTDClassHead($class)
  {
    $this->_TDClassHead = $class;
  }
  function SetTDClassLabel($class)
  {
    $this->_TDClassLabel = $class;
  }
  function SetTDClassCount($class)
  {
    $this->_TDClassCount = $class;
  }
  function GetMaxVal()
  {
    $maxval = 0;
    foreach ( $this->_values as $value )
    {
      if ( $maxval < $value["value"] )
      {
        $maxval = $value["value"];
      }
    }
    return $maxval;
  }
  function BarGraphVert()
  {
    $maxval = $this->GetMaxVal();
    foreach($this->_values as $value)
    {
      $sumval += $value["value"];
    }
    
    $this->SetSortMode($this->_RowSortMode);
    
    echo "\n<!-- ----------------------------------------- -->\n<div class=\"tblholder\" style=\"width: 100%; clip: rect(0px,auto,auto,0px); overflow: auto;\">\n<table border=\"0\" cellspacing=\"1\" cellpadding=\"4\">\n  ";
    
    if ( strlen($this->_GraphTitle) > 0 )
    {
      echo "<tr>\n    <th colspan=\"".count($this->_values)."\" class=\"".$this->_TDClassHead."\">".$this->_GraphTitle."</th>\n  </tr>\n  ";
    }
    
    echo "<tr>\n  ";
    $css_class = 'row1';
    
    foreach($this->_values as $value)
    {
      $css_class = ( $css_class == 'row1' ) ? 'row3' : 'row1';
      echo "  <td valign=\"bottom\" align=\"center\" class=\"$css_class\">\n      ";
      $width = $this->_BarWidth;
      $height = ceil( $value["value"] * $this->_GraphWidth / $maxval );

      echo "<div style=\"width: {$width}px; height: {$height}px; background-color: {$this->_BarBackgroundColor}; border: ".$this->_BarBorderWidth."px solid ".$this->_BarBorderColor."\">\n      ";
      echo "</div>\n    ";
      
      // echo "<img src=\"".$this->_BarImg."\" height=\"$width\" width=\"$height\" ";
      // echo "  style=\"border: ".$this->_BarBorderWidth."px solid ".$this->_BarBorderColor."\"";
      // echo ">";

      echo "</td>\n  ";
    }
    echo "</tr>\n  ";
    if ( $this->_ShowCountsMode > 0 )
    {
      $css_class = 'row1';
      echo "<tr>\n  ";
      foreach($this->_values as $value)
      {
        $css_class = ( $css_class == 'row1' ) ? 'row3' : 'row1';
        switch ($this->_ShowCountsMode)
        {
          case 1:
            $count = round ( 100 * $value["value"] / $sumval ) . "%";
            break;
          case 2:
            $count = $value["value"];
            break;
          default:
            break;
        }
        echo "  <td align=\"center\" class=\"$css_class ".$this->_TDClassCount."\">$count</td>\n  ";
      }
      echo "</tr>\n";
    }

    if ($this->_ShowLabels)
    {
      $css_class = 'row1';
      echo "  <tr>\n  ";
      foreach($this->_values as $value)
      {
        $css_class = ( $css_class == 'row1' ) ? 'row3' : 'row1';
        echo "  <td align=\"center\" class=\"$css_class ".$this->_TDClassLabel."\"";
        echo ">".$value["label"]."</td>\n  ";
      }
      echo "</tr>\n";
    }

    echo "</table>";
  }

  function BarGraphHoriz()
  {
    $maxval = $this->GetMaxVal();
    
    foreach($this->_values as $value)
    {
      $sumval += $value["value"];
    }
    
    $this->SetSortMode($this->_RowSortMode);
    
    echo "<table border=\"0\">";
    
    if ( strlen($this->_GraphTitle) > 0 )
    {
      echo "<tr><td ";
      if ( $this->_ShowCountsMode > 0 )
      {
        echo " colspan=\"2\"";
      }
      echo " class=\"".$this->_TDClassHead."\">".$this->_GraphTitle."</td></tr>";
    }
    foreach($this->_values as $value)
    {
      if ($this->_ShowLabels)
      {
        echo "<tr>";
        echo "<td class=\"".$this->_TDClassLabel."\"";
        if ( $this->_ShowCountsMode > 0 )
        {
          echo " colspan=\"2\"";
        }
        echo ">".$value["label"]."</td></tr>";
      }
      echo "<tr>";
      if ( $this->_ShowCountsMode > 0 )
      {
        switch ($this->_ShowCountsMode)
        {
          case 1:
            $count = round(100 * $value["value"] / $sumval )."%";
            break;
          case 2:
            $count = $value["value"];
            break;  /* Exit the switch and the while. */
          default:
            break;
        }
        echo "<td class=\"".$this->_TDClassCount."\">$count</TD>";
      }
      echo "<td>";
      $height = $this->_BarWidth;
      $width = ceil( $value["value"] * $this->_GraphWidth / $maxval );
      echo "<div style=\"width: {$width}px; height: {$height}px; background-color: #456798; border: ".$this->_BarBorderWidth."px solid ".$this->_BarBorderColor."\">\n      ";
      echo "</div>\n    ";
      //echo "<img SRC=\"".$this->_BarImg."\" height=$height width=$width ";
      //echo "  style=\"border: ".$this->_BarBorderWidth."px solid ".$this->_BarBorderColor."\"";
      //echo ">";
      echo "</td></tr>";
    }
    echo "</table>";
  }
  /**
   * Dummy functions for compatibility with the GD version of the class
   */
  
  function SetGraphPadding($a, $b, $c, $d)
  {
    return true;
  }
  function SetBarPadding($a)
  {
    return true;
  }
  function SetAxisStep($a)
  {
    return true;
  }
  function SetGraphBackgroundTransparent($r, $g, $b, $a)
  {
    return true;
  }
  function SetGraphTransparency($a)
  {
    return true;
  }
  function SetGraphAreaHeight($a)
  {
    return true;
  }
}