<?php if (!defined('PmWiki')) exit();

  /*  goalmeter.php, a module written for pmwiki 2
    A goal thermometer image generator, for fundraising thermometers and more.
    Copyright 2006 Hans Bracker, based on original script by Wendell Brown.
    
    This program is free software; you can redistribute it 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.
    
    Markup syntax: basic: (:goalmeter current= goal= height= :)
    Add other parameters to suit. See default list below for available keys.
    For more than one goalmeter use id= parameter.
    Color values need to be in hex. An alpha opacity value can be added as 
    a fourth hex pair, maximum transparency -> FF, no transp -> 00, medium -> 7F.
*/
$RecipeInfo['GoalMeter']['Version'] = '2009-01-29';

  // img files are cached in cache direcory
    SDV($PubCacheDir, "pub/cache");
    SDV($PubCacheUrl, "$PubDirUrl/cache");
    SDV($GoalMeterCacheDir, $PubCacheDir);
    SDV($GoalMeterCacheUrl, $PubCacheUrl);
    mkdirp($GoalMeterCacheDir);

# add markup (:goalmeter ....:)
Markup('goalmeter', 'directives', '/\\(:goalmeter\\s*(.*?):\\)/ei',
      "GoalMeter(\$pagename, PSS('$1'))");

function GoalMeter($pagename, $opt) {
  global $GoalMeterCacheDir, $GoalMeterCacheUrl;
  
  // set defaults
  $defaults = array(
    'current' => '0',    # current value
    'goal'    => '100',  # goal value
    'max'     => '',     # max value as alternative to goal, goal will not be displayed
    'height'  => '360',  # outer height
    'width'   => '',     # outer width, default automatic calculation
    'bar'     => '3',    # bar thickness 
    'font'    => '4',    #font size 1 ... 5
    'bg'      => 'ffffff7f',# background color (transparent)
    'fill'    => 'FF0000',  # main fill and border color
    'topfill' => 'FFFFCC',  # top fill color
    'bulbfill'=> '',        # bulb fill color (defaults to main fill color)
    'scale'   => '666666',  # scale color
    'value'   => '000000',  # value text color
    'percent' => 'FFFFFF',  # percent text color
    'border'  => '',    # outer border color     
    'nobulb'  => '',   # set to 1 for column only display
    'noscale' => '',    # set to 1 for no scale display
    'padding' => '8',  # img padding
    'rpad'    => '40', # right hand extra padding 
    'base' => '',      # basepage to check for value updates
   );
  $opt = array_merge($defaults, ParseArgs($opt));
  
  // define variables
  static $id=0; $id++;
  $height = $opt['height'];
  $current = $opt['current'];
  $goal = $opt['goal'];
  $font = $opt['font'];
  $c = $opt['bar']/10;
  $p = $opt['padding'];
  $y = $height-2*$p;
  $rpad = (ImageFontWidth($font))*(strlen($goal))-$p; //calculate right padding
  $width = $opt['width'];
  if(!$opt['width']) $width = 80 + $rpad;   // auto width
  $x = $width-2*$p-$rpad; // thermometer width
  
  // extract digits for $max and $cur
  if($opt['max']) { 
      $max = $opt['max'];
      $goal = '';
  }
  else $max = preg_replace('/\\D+/', '',$goal);
  $cur = preg_replace('/\\D+/', '',$current);


 // file handling
 $imgname = "thermo_".$pagename."_".$id.".png";
 $imgfile = FmtPageName("$GoalMeterCacheDir/$imgname", $pagename);
 $imgurl = FmtPageName("$GoalMeterCacheUrl/$imgname", $pagename);
 $fmodtime = @filemtime($imgfile);
 
 // set mod time to last page change or last change of base page
 $base = $opt['base'] ? MakePageName($pagename, $opt['base']) : $pagename;
 $page = ReadPage($base);
 $modified = $page["time"];

 // create new file only if older than last page mod, or does not exist
 if ($fmodtime < $modified || $fmodtime==0 || $modified==0) {
    // create outer image
    $img0 = ImageCreate($width, $height); 
    // create img for thermometer
    $img = ImageCreate($x, $y);
    
    // convert & set colors
    $bg = fromhex($opt['bg'],$img);
    $fill = fromhex($opt['fill'],$img);
    if($opt['bulb']) $bulbfill = fromhex($opt['bulb'],$img);
    else $bulbfill = $fill;
    $topfill = fromhex($opt['topfill'],$img);
    $scale = fromhex($opt['scale'],$img);
    $percent = fromhex($opt['percent'],$img);

    // First build background to assign background color
    ImageFilledRectangle($img0,0,0,$width,$height,$bg);

    // set bottom y space
    if($opt['nobulb']) $by = ImageFontHeight($font)+3;
    else $by = $x;

     //  Draw Top Border
    ImageRectangle( $img,
                    ($x/2)-(($x/2)*$c),
                    0,
                    ($x/2)+(($x/2)*$c),
                    $y-$by+1,
                    $fill);

   //  Fill Top Rectangle
    ImageFilledRectangle( $img,
                    ($x/2)-(($x/2)*$c)+1,
                    1,
                    ($x/2)+(($x/2)*$c)-1,
                    $y-$by+1,
                    $topfill);

    //  Fill to Current %
    ImageFilledRectangle( $img,
                    ($x/2)-(($x/2)*$c)+1,
                    ($y-$by)*(1-($cur/$max))+1,
                    ($x/2)+(($x/2)*$c)-1,
                    $y-$by+1,
                    $fill);

      //  Fill bulb
    if(!$opt['nobulb']) {      
      ImageFilledArc($img,
                    $x/2, 
                    $y-$x/2, 
                    $x-1, $x-1, 0, 360, $bulbfill, IMG_ARC_PIE);

      //  Fill bulb segment top
      $r = $x/2;
      $h = ceil($r-sqrt(($r*$r)-($x*$x*$c*$c/4)));
      ImageFilledRectangle($img,
                          ($x/2)-(($x/2)*$c), //x1
                          $y-$x,
                          ($x/2)+(($x/2)*$c),  //x2
                          $y-$x+$h,
                         $fill );
     }

    // Fill scale lines: 20 lines
    if(!$opt['noscale']) {
       for( $k=0; $k<=100; $k+=5 ) {
           $scx = $x/15;
           $scy = $scx/3;
           ImageFilledRectangle( $img,
                  ($x/2)+(($x/2)*$c) -1 -$scx,
                  ($y-$by)-($y-$by)*($k/100),
                  ($x/2)+(($x/2)*$c) -1,
                  ($y-$by)-($y-$by)*($k/100) +$scy, $scale );

           /* // add percent numbers to scale
           ImageString($img, $font,
                  ($x/2)+(($x/2)*$c) +2,
                  (($y-$by)-($y-$by)*($k/100)) - (ImageFontHeight($font)/2) +$p,
                  sprintf( "%2d", $k),$scale);*/
       }
    }

    // Add Text Current value in percent inside bulb
    $pct = sprintf( "%d%%", ($cur/$max)*100 );
    ImageString( $img, $font+2, ($x/2)-((strlen($pct)/2)*ImageFontWidth($font+2)),
       ($y-($by/2))+2 -(ImageFontHeight($font+2) / 2),
       $pct, $percent);
       
    // copy img to apply padding and header space
    ImageCopy ( $img0, $img, $p, $p+$hdr, 0, 0, $x, $y );

    // Now work on outer image
    // Add some colors
    $value = fromhex($opt['value'],$img0);
    $border = fromhex($opt['border'],$img0);
    
    // Add outer border if set
    if($opt['border']) ImageRectangle($img0,0,0,$width-1,$height-1,$border);
    

    // Add Text Current value
        ImageString($img0, $font,
               ($x/2)+(($x/2)*$c)+10+$p,
               (($y-$by)*(1-($cur/$max)))-(ImageFontHeight($font)/2) +$p,
               $current, $value);               
    // Add Text Goal value
        ImageString($img0, $font,
               ($x/2)+(($x/2)*$c)+10+$p,
                $p - (ImageFontHeight($font)/2)+5,
                $goal, $value); 

    // Create a new image file
    ImagePng($img0, $imgfile);
    // clean memory
    ImageDestroy($img);
    ImageDestroy($img0);
    }
    
 // deliver img tags
 $out = "<img name='$imgname' src='$imgurl' width='$width' height='$height' alt='Current: $current' title='Current: $current' />";
 return Keep($out);
}

# helperfunction to convert hexstrings to color allocations
function fromhex($val,&$img) {
  $val = trim($val,'#');
  if(strlen($val)<7) {
     sscanf($val, "%2x%2x%2x", $red, $green, $blue);
     return ImageColorAllocate($img,$red,$green,$blue);
     }
  // add alpha opacity if provided
  else {
     sscanf($val, "%2x%2x%2x%2x", $red, $green, $blue, $alpha);
     return ImageColorAllocateAlpha($img,$red,$green,$blue,$alpha/2);
     }
}